Merge "WiFi: Basic support for 11be"
diff --git a/Android.bp b/Android.bp
index 8d82b38..8bc5d7a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -77,7 +77,6 @@
         // Java/AIDL sources under frameworks/base
         ":framework-annotations",
         ":framework-blobstore-sources",
-        ":framework-bluetooth-sources", // TODO(b/214988855) : Remove once framework-bluetooth jar is ready
         ":framework-connectivity-tiramisu-sources",
         ":framework-core-sources",
         ":framework-drm-sources",
@@ -297,6 +296,7 @@
     defaults: ["framework-aidl-export-defaults"],
     srcs: [
         ":framework-non-updatable-sources",
+        ":framework-bluetooth-sources", // TODO(b/214988855) : Remove once framework-bluetooth jar is ready
         "core/java/**/*.logtags",
         ":apex-info-list",
     ],
@@ -602,6 +602,7 @@
     libs: [
         "art.module.public.api",
         "sdk_module-lib_current_framework-tethering",
+        "sdk_public_current_framework-bluetooth",
         // There are a few classes from modules used by the core that
         // need to be resolved by metalava. We use a prebuilt stub of the
         // full sdk to ensure we can resolve them. If a new class gets added,
diff --git a/ApiDocs.bp b/ApiDocs.bp
index 3d6b52f..c50d446 100644
--- a/ApiDocs.bp
+++ b/ApiDocs.bp
@@ -102,6 +102,7 @@
 
         ":framework-appsearch-sources",
         ":framework-connectivity-sources",
+        ":framework-bluetooth-sources",
         ":framework-connectivity-tiramisu-updatable-sources",
         ":framework-graphics-srcs",
         ":framework-mediaprovider-sources",
diff --git a/StubLibraries.bp b/StubLibraries.bp
index 8a15758..a0a426e 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -215,52 +215,6 @@
 // from stub sources
 /////////////////////////////////////////////////////////////////////
 
-modules_public_stubs = [
-    "android.net.ipsec.ike.stubs",
-    "art.module.public.api.stubs",
-    "conscrypt.module.public.api.stubs",
-    "framework-appsearch.stubs",
-    "framework-connectivity.stubs",
-    "framework-connectivity-tiramisu.stubs",
-    "framework-graphics.stubs",
-    "framework-media.stubs",
-    "framework-mediaprovider.stubs",
-    "framework-nearby.stubs",
-    "framework-permission.stubs",
-    "framework-permission-s.stubs",
-    "framework-scheduling.stubs",
-    "framework-sdkextensions.stubs",
-    "framework-statsd.stubs",
-    "framework-supplementalprocess.stubs",
-    "framework-tethering.stubs",
-    "framework-uwb.stubs",
-    "framework-wifi.stubs",
-    "i18n.module.public.api.stubs",
-]
-
-modules_system_stubs = [
-    "android.net.ipsec.ike.stubs.system",
-    "art.module.public.api.stubs.system",
-    "conscrypt.module.public.api.stubs", // Only has public stubs
-    "framework-appsearch.stubs.system",
-    "framework-connectivity.stubs.system",
-    "framework-connectivity-tiramisu.stubs.system",
-    "framework-graphics.stubs.system",
-    "framework-media.stubs.system",
-    "framework-mediaprovider.stubs.system",
-    "framework-nearby.stubs.system",
-    "framework-permission.stubs.system",
-    "framework-permission-s.stubs.system",
-    "framework-scheduling.stubs.system",
-    "framework-sdkextensions.stubs.system",
-    "framework-statsd.stubs.system",
-    "framework-supplementalprocess.stubs",
-    "framework-tethering.stubs.system",
-    "framework-uwb.stubs.system",
-    "framework-wifi.stubs.system",
-    "i18n.module.public.api.stubs", // Only has public stubs
-]
-
 java_defaults {
     name: "android-non-updatable_defaults_stubs_current",
     libs: ["stub-annotations"],
@@ -282,14 +236,7 @@
     name: "android-non-updatable.stubs",
     defaults: ["android-non-updatable_defaults_stubs_current"],
     srcs: [":api-stubs-docs-non-updatable"],
-    libs: modules_public_stubs,
-    soong_config_variables: {
-        include_nonpublic_framework_api: {
-            libs: [
-                "framework-supplementalapi.stubs",
-            ],
-        },
-    },
+    libs: ["all-modules-public-stubs"],
     dist: {
         dir: "apistubs/android/public",
     },
@@ -299,14 +246,7 @@
     name: "android-non-updatable.stubs.system",
     defaults: ["android-non-updatable_defaults_stubs_current"],
     srcs: [":system-api-stubs-docs-non-updatable"],
-    libs: modules_system_stubs,
-    soong_config_variables: {
-        include_nonpublic_framework_api: {
-            libs: [
-                "framework-supplementalapi.stubs",
-            ],
-        },
-    },
+    libs: ["all-modules-system-stubs"],
     dist: {
         dir: "apistubs/android/system",
     },
@@ -318,6 +258,8 @@
     srcs: [":module-lib-api-stubs-docs-non-updatable"],
     libs: [
         "sdk_module-lib_current_framework-tethering",
+        "sdk_public_current_framework-bluetooth",
+        // NOTE: The below can be removed once the prebuilt stub contains bluetooth.
         "sdk_system_current_android",
         // NOTE: The below can be removed once the prebuilt stub contains IKE.
         "sdk_system_current_android.net.ipsec.ike",
@@ -331,14 +273,7 @@
     name: "android-non-updatable.stubs.test",
     defaults: ["android-non-updatable_defaults_stubs_current"],
     srcs: [":test-api-stubs-docs-non-updatable"],
-    libs: modules_system_stubs,
-    soong_config_variables: {
-        include_nonpublic_framework_api: {
-            libs: [
-                "framework-supplementalapi.stubs",
-            ],
-        },
-    },
+    libs: ["all-modules-system-stubs"],
     dist: {
         dir: "apistubs/android/test",
     },
@@ -356,33 +291,21 @@
 
 java_library_with_nonpublic_deps {
     name: "android_stubs_current",
-    static_libs: modules_public_stubs + [
+    static_libs: [
+        "all-modules-public-stubs",
         "android-non-updatable.stubs",
         "private-stub-annotations-jar",
     ],
-    soong_config_variables: {
-        include_nonpublic_framework_api: {
-            static_libs: [
-                "framework-supplementalapi.stubs",
-            ],
-        },
-    },
     defaults: ["android.jar_defaults"],
 }
 
 java_library_with_nonpublic_deps {
     name: "android_system_stubs_current",
-    static_libs: modules_system_stubs + [
+    static_libs: [
+        "all-modules-system-stubs",
         "android-non-updatable.stubs.system",
         "private-stub-annotations-jar",
     ],
-    soong_config_variables: {
-        include_nonpublic_framework_api: {
-            static_libs: [
-                "framework-supplementalapi.stubs",
-            ],
-        },
-    },
     defaults: [
         "android.jar_defaults",
         "android_stubs_dists_default",
@@ -404,17 +327,11 @@
     name: "android_test_stubs_current",
     // Modules do not have test APIs, but we want to include their SystemApis, like we include
     // the SystemApi of framework-non-updatable-sources.
-    static_libs: modules_system_stubs + [
+    static_libs: [
+        "all-modules-system-stubs",
         "android-non-updatable.stubs.test",
         "private-stub-annotations-jar",
     ],
-    soong_config_variables: {
-        include_nonpublic_framework_api: {
-            static_libs: [
-                "framework-supplementalapi.stubs",
-            ],
-        },
-    },
     defaults: [
         "android.jar_defaults",
         "android_stubs_dists_default",
diff --git a/api/Android.bp b/api/Android.bp
index a22c2f6..d8727f9 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -110,6 +110,7 @@
         "art.module.public.api",
         "conscrypt.module.public.api",
         "framework-appsearch",
+        "framework-bluetooth",
         "framework-connectivity",
         "framework-connectivity-tiramisu",
         "framework-graphics",
diff --git a/api/api.go b/api/api.go
index 4b6ebc1..aa9e399e 100644
--- a/api/api.go
+++ b/api/api.go
@@ -27,6 +27,7 @@
 const art = "art.module.public.api"
 const conscrypt = "conscrypt.module.public.api"
 const i18n = "i18n.module.public.api"
+var modules_with_only_public_scope = []string{i18n, conscrypt}
 
 // The intention behind this soong plugin is to generate a number of "merged"
 // API-related modules that would otherwise require a large amount of very
@@ -183,6 +184,27 @@
 	ctx.CreateModule(genrule.GenRuleFactory, &props)
 }
 
+func createMergedPublicStubs(ctx android.LoadHookContext, modules []string) {
+	props := libraryProps{}
+	props.Name = proptools.StringPtr("all-modules-public-stubs")
+	props.Static_libs = transformArray(modules, "", ".stubs")
+	props.Sdk_version = proptools.StringPtr("module_current")
+	props.Visibility = []string{"//frameworks/base"}
+	ctx.CreateModule(java.LibraryFactory, &props)
+}
+
+func createMergedSystemStubs(ctx android.LoadHookContext, modules []string) {
+	props := libraryProps{}
+	modules_with_system_stubs := removeAll(modules, modules_with_only_public_scope)
+	props.Name = proptools.StringPtr("all-modules-system-stubs")
+	props.Static_libs = append(
+		transformArray(modules_with_only_public_scope, "", ".stubs"),
+		transformArray(modules_with_system_stubs, "", ".stubs.system")...)
+	props.Sdk_version = proptools.StringPtr("module_current")
+	props.Visibility = []string{"//frameworks/base"}
+	ctx.CreateModule(java.LibraryFactory, &props)
+}
+
 func createMergedModuleLibStubs(ctx android.LoadHookContext, modules []string) {
 	// The user of this module compiles against the "core" SDK, so remove core libraries to avoid dupes.
 	modules = removeAll(modules, []string{art, conscrypt, i18n})
@@ -205,7 +227,7 @@
 func createMergedTxts(ctx android.LoadHookContext, bootclasspath, system_server_classpath []string) {
 	var textFiles []MergedTxtDefinition
 	// Two module libraries currently do not support @SystemApi so only have the public scope.
-	bcpWithSystemApi := removeAll(bootclasspath, []string{conscrypt, i18n})
+	bcpWithSystemApi := removeAll(bootclasspath, modules_with_only_public_scope)
 
 	tagSuffix := []string{".api.txt}", ".removed-api.txt}"}
 	for i, f := range []string{"current.txt", "removed.txt"} {
@@ -253,6 +275,8 @@
 
 	createMergedStubsSrcjar(ctx, bootclasspath)
 
+	createMergedPublicStubs(ctx, bootclasspath)
+	createMergedSystemStubs(ctx, bootclasspath)
 	createMergedModuleLibStubs(ctx, bootclasspath)
 
 	createMergedAnnotations(ctx, bootclasspath)
diff --git a/core/api/current.txt b/core/api/current.txt
index cb2ede8..0316875 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -8874,1365 +8874,6 @@
 
 }
 
-package android.bluetooth {
-
-  public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile {
-    method public void finalize();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isA2dpPlaying(android.bluetooth.BluetoothDevice);
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_PLAYING_STATE_CHANGED = "android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED";
-    field public static final int STATE_NOT_PLAYING = 11; // 0xb
-    field public static final int STATE_PLAYING = 10; // 0xa
-  }
-
-  public final class BluetoothAdapter {
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public boolean cancelDiscovery();
-    method public static boolean checkBluetoothAddress(String);
-    method public void closeProfileProxy(int, android.bluetooth.BluetoothProfile);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disable();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean enable();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, "android.permission.LOCAL_MAC_ADDRESS"}) public String getAddress();
-    method public android.bluetooth.le.BluetoothLeAdvertiser getBluetoothLeAdvertiser();
-    method public android.bluetooth.le.BluetoothLeScanner getBluetoothLeScanner();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.Set<android.bluetooth.BluetoothDevice> getBondedDevices();
-    method @Deprecated public static android.bluetooth.BluetoothAdapter getDefaultAdapter();
-    method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public java.time.Duration getDiscoverableTimeout();
-    method public int getLeMaximumAdvertisingDataLength();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getMaxConnectedAudioDevices();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public String getName();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getProfileConnectionState(int);
-    method public boolean getProfileProxy(android.content.Context, android.bluetooth.BluetoothProfile.ServiceListener, int);
-    method public android.bluetooth.BluetoothDevice getRemoteDevice(String);
-    method public android.bluetooth.BluetoothDevice getRemoteDevice(byte[]);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public int getScanMode();
-    method public int getState();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public boolean isDiscovering();
-    method public boolean isEnabled();
-    method public boolean isLe2MPhySupported();
-    method public int isLeAudioBroadcastAssistantSupported();
-    method public int isLeAudioBroadcastSourceSupported();
-    method public int isLeAudioSupported();
-    method public boolean isLeCodedPhySupported();
-    method public boolean isLeExtendedAdvertisingSupported();
-    method public boolean isLePeriodicAdvertisingSupported();
-    method public boolean isMultipleAdvertisementSupported();
-    method public boolean isOffloadedFilteringSupported();
-    method public boolean isOffloadedScanBatchingSupported();
-    method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothServerSocket listenUsingInsecureL2capChannel() throws java.io.IOException;
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String, java.util.UUID) throws java.io.IOException;
-    method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothServerSocket listenUsingL2capChannel() throws java.io.IOException;
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothServerSocket listenUsingRfcommWithServiceRecord(String, java.util.UUID) throws java.io.IOException;
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean setName(String);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public boolean startDiscovery();
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public boolean startLeScan(android.bluetooth.BluetoothAdapter.LeScanCallback);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public boolean startLeScan(java.util.UUID[], android.bluetooth.BluetoothAdapter.LeScanCallback);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void stopLeScan(android.bluetooth.BluetoothAdapter.LeScanCallback);
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public static final String ACTION_DISCOVERY_FINISHED = "android.bluetooth.adapter.action.DISCOVERY_FINISHED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public static final String ACTION_DISCOVERY_STARTED = "android.bluetooth.adapter.action.DISCOVERY_STARTED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_LOCAL_NAME_CHANGED = "android.bluetooth.adapter.action.LOCAL_NAME_CHANGED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public static final String ACTION_REQUEST_DISCOVERABLE = "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_REQUEST_ENABLE = "android.bluetooth.adapter.action.REQUEST_ENABLE";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public static final String ACTION_SCAN_MODE_CHANGED = "android.bluetooth.adapter.action.SCAN_MODE_CHANGED";
-    field public static final String ACTION_STATE_CHANGED = "android.bluetooth.adapter.action.STATE_CHANGED";
-    field public static final int ERROR = -2147483648; // 0x80000000
-    field public static final String EXTRA_CONNECTION_STATE = "android.bluetooth.adapter.extra.CONNECTION_STATE";
-    field public static final String EXTRA_DISCOVERABLE_DURATION = "android.bluetooth.adapter.extra.DISCOVERABLE_DURATION";
-    field public static final String EXTRA_LOCAL_NAME = "android.bluetooth.adapter.extra.LOCAL_NAME";
-    field public static final String EXTRA_PREVIOUS_CONNECTION_STATE = "android.bluetooth.adapter.extra.PREVIOUS_CONNECTION_STATE";
-    field public static final String EXTRA_PREVIOUS_SCAN_MODE = "android.bluetooth.adapter.extra.PREVIOUS_SCAN_MODE";
-    field public static final String EXTRA_PREVIOUS_STATE = "android.bluetooth.adapter.extra.PREVIOUS_STATE";
-    field public static final String EXTRA_SCAN_MODE = "android.bluetooth.adapter.extra.SCAN_MODE";
-    field public static final String EXTRA_STATE = "android.bluetooth.adapter.extra.STATE";
-    field public static final int SCAN_MODE_CONNECTABLE = 21; // 0x15
-    field public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23; // 0x17
-    field public static final int SCAN_MODE_NONE = 20; // 0x14
-    field public static final int STATE_CONNECTED = 2; // 0x2
-    field public static final int STATE_CONNECTING = 1; // 0x1
-    field public static final int STATE_DISCONNECTED = 0; // 0x0
-    field public static final int STATE_DISCONNECTING = 3; // 0x3
-    field public static final int STATE_OFF = 10; // 0xa
-    field public static final int STATE_ON = 12; // 0xc
-    field public static final int STATE_TURNING_OFF = 13; // 0xd
-    field public static final int STATE_TURNING_ON = 11; // 0xb
-  }
-
-  public static interface BluetoothAdapter.LeScanCallback {
-    method public void onLeScan(android.bluetooth.BluetoothDevice, int, byte[]);
-  }
-
-  public class BluetoothAssignedNumbers {
-    field public static final int AAMP_OF_AMERICA = 190; // 0xbe
-    field public static final int ACCEL_SEMICONDUCTOR = 74; // 0x4a
-    field public static final int ACE_SENSOR = 188; // 0xbc
-    field public static final int ADIDAS = 195; // 0xc3
-    field public static final int ADVANCED_PANMOBIL_SYSTEMS = 145; // 0x91
-    field public static final int AIROHA_TECHNOLOGY = 148; // 0x94
-    field public static final int ALCATEL = 36; // 0x24
-    field public static final int ALPWISE = 154; // 0x9a
-    field public static final int AMICCOM_ELECTRONICS = 192; // 0xc0
-    field public static final int APLIX = 189; // 0xbd
-    field public static final int APPLE = 76; // 0x4c
-    field public static final int APT_LICENSING = 79; // 0x4f
-    field public static final int ARCHOS = 207; // 0xcf
-    field public static final int ARP_DEVICES = 168; // 0xa8
-    field public static final int ATHEROS_COMMUNICATIONS = 69; // 0x45
-    field public static final int ATMEL = 19; // 0x13
-    field public static final int AUSTCO_COMMUNICATION_SYSTEMS = 213; // 0xd5
-    field public static final int AUTONET_MOBILE = 127; // 0x7f
-    field public static final int AVAGO = 78; // 0x4e
-    field public static final int AVM_BERLIN = 31; // 0x1f
-    field public static final int A_AND_D_ENGINEERING = 105; // 0x69
-    field public static final int A_AND_R_CAMBRIDGE = 124; // 0x7c
-    field public static final int BANDSPEED = 32; // 0x20
-    field public static final int BAND_XI_INTERNATIONAL = 100; // 0x64
-    field public static final int BDE_TECHNOLOGY = 180; // 0xb4
-    field public static final int BEATS_ELECTRONICS = 204; // 0xcc
-    field public static final int BEAUTIFUL_ENTERPRISE = 108; // 0x6c
-    field public static final int BEKEY = 178; // 0xb2
-    field public static final int BELKIN_INTERNATIONAL = 92; // 0x5c
-    field public static final int BINAURIC = 203; // 0xcb
-    field public static final int BIOSENTRONICS = 219; // 0xdb
-    field public static final int BLUEGIGA = 71; // 0x47
-    field public static final int BLUERADIOS = 133; // 0x85
-    field public static final int BLUETOOTH_SIG = 63; // 0x3f
-    field public static final int BLUETREK_TECHNOLOGIES = 151; // 0x97
-    field public static final int BOSE = 158; // 0x9e
-    field public static final int BRIARTEK = 109; // 0x6d
-    field public static final int BROADCOM = 15; // 0xf
-    field public static final int CAEN_RFID = 170; // 0xaa
-    field public static final int CAMBRIDGE_SILICON_RADIO = 10; // 0xa
-    field public static final int CATC = 52; // 0x34
-    field public static final int CINETIX = 175; // 0xaf
-    field public static final int CLARINOX_TECHNOLOGIES = 179; // 0xb3
-    field public static final int COLORFY = 156; // 0x9c
-    field public static final int COMMIL = 51; // 0x33
-    field public static final int CONEXANT_SYSTEMS = 28; // 0x1c
-    field public static final int CONNECTBLUE = 113; // 0x71
-    field public static final int CONTINENTAL_AUTOMOTIVE = 75; // 0x4b
-    field public static final int CONWISE_TECHNOLOGY = 66; // 0x42
-    field public static final int CREATIVE_TECHNOLOGY = 118; // 0x76
-    field public static final int C_TECHNOLOGIES = 38; // 0x26
-    field public static final int DANLERS = 225; // 0xe1
-    field public static final int DELORME_PUBLISHING_COMPANY = 128; // 0x80
-    field public static final int DEXCOM = 208; // 0xd0
-    field public static final int DIALOG_SEMICONDUCTOR = 210; // 0xd2
-    field public static final int DIGIANSWER = 12; // 0xc
-    field public static final int ECLIPSE = 53; // 0x35
-    field public static final int ECOTEST = 136; // 0x88
-    field public static final int ELGATO_SYSTEMS = 206; // 0xce
-    field public static final int EM_MICROELECTRONIC_MARIN = 90; // 0x5a
-    field public static final int EQUINOX_AG = 134; // 0x86
-    field public static final int ERICSSON_TECHNOLOGY = 0; // 0x0
-    field public static final int EVLUMA = 201; // 0xc9
-    field public static final int FREE2MOVE = 83; // 0x53
-    field public static final int FUNAI_ELECTRIC = 144; // 0x90
-    field public static final int GARMIN_INTERNATIONAL = 135; // 0x87
-    field public static final int GCT_SEMICONDUCTOR = 45; // 0x2d
-    field public static final int GELO = 200; // 0xc8
-    field public static final int GENEQ = 194; // 0xc2
-    field public static final int GENERAL_MOTORS = 104; // 0x68
-    field public static final int GENNUM = 59; // 0x3b
-    field public static final int GEOFORCE = 157; // 0x9d
-    field public static final int GIBSON_GUITARS = 98; // 0x62
-    field public static final int GN_NETCOM = 103; // 0x67
-    field public static final int GN_RESOUND = 137; // 0x89
-    field public static final int GOOGLE = 224; // 0xe0
-    field public static final int GREEN_THROTTLE_GAMES = 172; // 0xac
-    field public static final int GROUP_SENSE = 115; // 0x73
-    field public static final int HANLYNN_TECHNOLOGIES = 123; // 0x7b
-    field public static final int HARMAN_INTERNATIONAL = 87; // 0x57
-    field public static final int HEWLETT_PACKARD = 101; // 0x65
-    field public static final int HITACHI = 41; // 0x29
-    field public static final int HOSIDEN = 221; // 0xdd
-    field public static final int IBM = 3; // 0x3
-    field public static final int INFINEON_TECHNOLOGIES = 9; // 0x9
-    field public static final int INGENIEUR_SYSTEMGRUPPE_ZAHN = 171; // 0xab
-    field public static final int INTEGRATED_SILICON_SOLUTION = 65; // 0x41
-    field public static final int INTEGRATED_SYSTEM_SOLUTION = 57; // 0x39
-    field public static final int INTEL = 2; // 0x2
-    field public static final int INVENTEL = 30; // 0x1e
-    field public static final int IPEXTREME = 61; // 0x3d
-    field public static final int I_TECH_DYNAMIC_GLOBAL_DISTRIBUTION = 153; // 0x99
-    field public static final int JAWBONE = 138; // 0x8a
-    field public static final int JIANGSU_TOPPOWER_AUTOMOTIVE_ELECTRONICS = 155; // 0x9b
-    field public static final int JOHNSON_CONTROLS = 185; // 0xb9
-    field public static final int J_AND_M = 82; // 0x52
-    field public static final int KAWANTECH = 212; // 0xd4
-    field public static final int KC_TECHNOLOGY = 22; // 0x16
-    field public static final int KENSINGTON_COMPUTER_PRODUCTS_GROUP = 160; // 0xa0
-    field public static final int LAIRD_TECHNOLOGIES = 119; // 0x77
-    field public static final int LESSWIRE = 121; // 0x79
-    field public static final int LG_ELECTRONICS = 196; // 0xc4
-    field public static final int LINAK = 164; // 0xa4
-    field public static final int LUCENT = 7; // 0x7
-    field public static final int LUDUS_HELSINKI = 132; // 0x84
-    field public static final int MACRONIX = 44; // 0x2c
-    field public static final int MAGNETI_MARELLI = 169; // 0xa9
-    field public static final int MANSELLA = 33; // 0x21
-    field public static final int MARVELL = 72; // 0x48
-    field public static final int MATSUSHITA_ELECTRIC = 58; // 0x3a
-    field public static final int MC10 = 202; // 0xca
-    field public static final int MEDIATEK = 70; // 0x46
-    field public static final int MESO_INTERNATIONAL = 182; // 0xb6
-    field public static final int META_WATCH = 163; // 0xa3
-    field public static final int MEWTEL_TECHNOLOGY = 47; // 0x2f
-    field public static final int MICOMMAND = 99; // 0x63
-    field public static final int MICROCHIP_TECHNOLOGY = 205; // 0xcd
-    field public static final int MICROSOFT = 6; // 0x6
-    field public static final int MINDTREE = 106; // 0x6a
-    field public static final int MISFIT_WEARABLES = 223; // 0xdf
-    field public static final int MITEL_SEMICONDUCTOR = 16; // 0x10
-    field public static final int MITSUBISHI_ELECTRIC = 20; // 0x14
-    field public static final int MOBILIAN_CORPORATION = 55; // 0x37
-    field public static final int MONSTER = 112; // 0x70
-    field public static final int MOTOROLA = 8; // 0x8
-    field public static final int MSTAR_SEMICONDUCTOR = 122; // 0x7a
-    field public static final int MUZIK = 222; // 0xde
-    field public static final int NEC = 34; // 0x22
-    field public static final int NEC_LIGHTING = 149; // 0x95
-    field public static final int NEWLOGIC = 23; // 0x17
-    field public static final int NIKE = 120; // 0x78
-    field public static final int NINE_SOLUTIONS = 102; // 0x66
-    field public static final int NOKIA_MOBILE_PHONES = 1; // 0x1
-    field public static final int NORDIC_SEMICONDUCTOR = 89; // 0x59
-    field public static final int NORWOOD_SYSTEMS = 46; // 0x2e
-    field public static final int ODM_TECHNOLOGY = 150; // 0x96
-    field public static final int OMEGAWAVE = 174; // 0xae
-    field public static final int ONSET_COMPUTER = 197; // 0xc5
-    field public static final int OPEN_INTERFACE = 39; // 0x27
-    field public static final int OTL_DYNAMICS = 165; // 0xa5
-    field public static final int PANDA_OCEAN = 166; // 0xa6
-    field public static final int PARROT = 67; // 0x43
-    field public static final int PARTHUS_TECHNOLOGIES = 14; // 0xe
-    field public static final int PASSIF_SEMICONDUCTOR = 176; // 0xb0
-    field public static final int PETER_SYSTEMTECHNIK = 173; // 0xad
-    field public static final int PHILIPS_SEMICONDUCTORS = 37; // 0x25
-    field public static final int PLANTRONICS = 85; // 0x55
-    field public static final int POLAR_ELECTRO = 107; // 0x6b
-    field public static final int POLAR_ELECTRO_EUROPE = 209; // 0xd1
-    field public static final int PROCTER_AND_GAMBLE = 220; // 0xdc
-    field public static final int QUALCOMM = 29; // 0x1d
-    field public static final int QUALCOMM_CONNECTED_EXPERIENCES = 216; // 0xd8
-    field public static final int QUALCOMM_INNOVATION_CENTER = 184; // 0xb8
-    field public static final int QUALCOMM_LABS = 140; // 0x8c
-    field public static final int QUALCOMM_TECHNOLOGIES = 215; // 0xd7
-    field public static final int QUINTIC = 142; // 0x8e
-    field public static final int QUUPPA = 199; // 0xc7
-    field public static final int RALINK_TECHNOLOGY = 91; // 0x5b
-    field public static final int RDA_MICROELECTRONICS = 97; // 0x61
-    field public static final int REALTEK_SEMICONDUCTOR = 93; // 0x5d
-    field public static final int RED_M = 50; // 0x32
-    field public static final int RENESAS_TECHNOLOGY = 54; // 0x36
-    field public static final int RESEARCH_IN_MOTION = 60; // 0x3c
-    field public static final int RF_MICRO_DEVICES = 40; // 0x28
-    field public static final int RIVIERAWAVES = 96; // 0x60
-    field public static final int ROHDE_AND_SCHWARZ = 25; // 0x19
-    field public static final int RTX_TELECOM = 21; // 0x15
-    field public static final int SAMSUNG_ELECTRONICS = 117; // 0x75
-    field public static final int SARIS_CYCLING_GROUP = 177; // 0xb1
-    field public static final int SEERS_TECHNOLOGY = 125; // 0x7d
-    field public static final int SEIKO_EPSON = 64; // 0x40
-    field public static final int SELFLY = 198; // 0xc6
-    field public static final int SEMILINK = 226; // 0xe2
-    field public static final int SENNHEISER_COMMUNICATIONS = 130; // 0x82
-    field public static final int SHANGHAI_SUPER_SMART_ELECTRONICS = 114; // 0x72
-    field public static final int SHENZHEN_EXCELSECU_DATA_TECHNOLOGY = 193; // 0xc1
-    field public static final int SIGNIA_TECHNOLOGIES = 27; // 0x1b
-    field public static final int SILICON_WAVE = 11; // 0xb
-    field public static final int SIRF_TECHNOLOGY = 80; // 0x50
-    field public static final int SOCKET_MOBILE = 68; // 0x44
-    field public static final int SONY_ERICSSON = 86; // 0x56
-    field public static final int SOUND_ID = 111; // 0x6f
-    field public static final int SPORTS_TRACKING_TECHNOLOGIES = 126; // 0x7e
-    field public static final int SR_MEDIZINELEKTRONIK = 161; // 0xa1
-    field public static final int STACCATO_COMMUNICATIONS = 77; // 0x4d
-    field public static final int STALMART_TECHNOLOGY = 191; // 0xbf
-    field public static final int STARKEY_LABORATORIES = 186; // 0xba
-    field public static final int STOLLMAN_E_PLUS_V = 143; // 0x8f
-    field public static final int STONESTREET_ONE = 94; // 0x5e
-    field public static final int ST_MICROELECTRONICS = 48; // 0x30
-    field public static final int SUMMIT_DATA_COMMUNICATIONS = 110; // 0x6e
-    field public static final int SUUNTO = 159; // 0x9f
-    field public static final int SWIRL_NETWORKS = 181; // 0xb5
-    field public static final int SYMBOL_TECHNOLOGIES = 42; // 0x2a
-    field public static final int SYNOPSYS = 49; // 0x31
-    field public static final int SYSTEMS_AND_CHIPS = 62; // 0x3e
-    field public static final int S_POWER_ELECTRONICS = 187; // 0xbb
-    field public static final int TAIXINGBANG_TECHNOLOGY = 211; // 0xd3
-    field public static final int TENOVIS = 43; // 0x2b
-    field public static final int TERAX = 56; // 0x38
-    field public static final int TEXAS_INSTRUMENTS = 13; // 0xd
-    field public static final int THINKOPTICS = 146; // 0x92
-    field public static final int THREECOM = 5; // 0x5
-    field public static final int THREE_DIJOY = 84; // 0x54
-    field public static final int THREE_DSP = 73; // 0x49
-    field public static final int TIMEKEEPING_SYSTEMS = 131; // 0x83
-    field public static final int TIMEX_GROUP_USA = 214; // 0xd6
-    field public static final int TOPCORN_POSITIONING_SYSTEMS = 139; // 0x8b
-    field public static final int TOSHIBA = 4; // 0x4
-    field public static final int TRANSILICA = 24; // 0x18
-    field public static final int TRELAB = 183; // 0xb7
-    field public static final int TTPCOM = 26; // 0x1a
-    field public static final int TXTR = 218; // 0xda
-    field public static final int TZERO_TECHNOLOGIES = 81; // 0x51
-    field public static final int UNIVERSAL_ELECTRONICS = 147; // 0x93
-    field public static final int VERTU = 162; // 0xa2
-    field public static final int VISTEON = 167; // 0xa7
-    field public static final int VIZIO = 88; // 0x58
-    field public static final int VOYETRA_TURTLE_BEACH = 217; // 0xd9
-    field public static final int WAVEPLUS_TECHNOLOGY = 35; // 0x23
-    field public static final int WICENTRIC = 95; // 0x5f
-    field public static final int WIDCOMM = 17; // 0x11
-    field public static final int WUXI_VIMICRO = 129; // 0x81
-    field public static final int ZEEVO = 18; // 0x12
-    field public static final int ZER01_TV = 152; // 0x98
-    field public static final int ZOMM = 116; // 0x74
-    field public static final int ZSCAN_SOFTWARE = 141; // 0x8d
-  }
-
-  public final class BluetoothClass implements android.os.Parcelable {
-    method public int describeContents();
-    method public boolean doesClassMatch(int);
-    method public int getDeviceClass();
-    method public int getMajorDeviceClass();
-    method public boolean hasService(int);
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothClass> CREATOR;
-    field public static final int PROFILE_A2DP = 1; // 0x1
-    field public static final int PROFILE_HEADSET = 0; // 0x0
-    field public static final int PROFILE_HID = 3; // 0x3
-  }
-
-  public static class BluetoothClass.Device {
-    ctor public BluetoothClass.Device();
-    field public static final int AUDIO_VIDEO_CAMCORDER = 1076; // 0x434
-    field public static final int AUDIO_VIDEO_CAR_AUDIO = 1056; // 0x420
-    field public static final int AUDIO_VIDEO_HANDSFREE = 1032; // 0x408
-    field public static final int AUDIO_VIDEO_HEADPHONES = 1048; // 0x418
-    field public static final int AUDIO_VIDEO_HIFI_AUDIO = 1064; // 0x428
-    field public static final int AUDIO_VIDEO_LOUDSPEAKER = 1044; // 0x414
-    field public static final int AUDIO_VIDEO_MICROPHONE = 1040; // 0x410
-    field public static final int AUDIO_VIDEO_PORTABLE_AUDIO = 1052; // 0x41c
-    field public static final int AUDIO_VIDEO_SET_TOP_BOX = 1060; // 0x424
-    field public static final int AUDIO_VIDEO_UNCATEGORIZED = 1024; // 0x400
-    field public static final int AUDIO_VIDEO_VCR = 1068; // 0x42c
-    field public static final int AUDIO_VIDEO_VIDEO_CAMERA = 1072; // 0x430
-    field public static final int AUDIO_VIDEO_VIDEO_CONFERENCING = 1088; // 0x440
-    field public static final int AUDIO_VIDEO_VIDEO_DISPLAY_AND_LOUDSPEAKER = 1084; // 0x43c
-    field public static final int AUDIO_VIDEO_VIDEO_GAMING_TOY = 1096; // 0x448
-    field public static final int AUDIO_VIDEO_VIDEO_MONITOR = 1080; // 0x438
-    field public static final int AUDIO_VIDEO_WEARABLE_HEADSET = 1028; // 0x404
-    field public static final int COMPUTER_DESKTOP = 260; // 0x104
-    field public static final int COMPUTER_HANDHELD_PC_PDA = 272; // 0x110
-    field public static final int COMPUTER_LAPTOP = 268; // 0x10c
-    field public static final int COMPUTER_PALM_SIZE_PC_PDA = 276; // 0x114
-    field public static final int COMPUTER_SERVER = 264; // 0x108
-    field public static final int COMPUTER_UNCATEGORIZED = 256; // 0x100
-    field public static final int COMPUTER_WEARABLE = 280; // 0x118
-    field public static final int HEALTH_BLOOD_PRESSURE = 2308; // 0x904
-    field public static final int HEALTH_DATA_DISPLAY = 2332; // 0x91c
-    field public static final int HEALTH_GLUCOSE = 2320; // 0x910
-    field public static final int HEALTH_PULSE_OXIMETER = 2324; // 0x914
-    field public static final int HEALTH_PULSE_RATE = 2328; // 0x918
-    field public static final int HEALTH_THERMOMETER = 2312; // 0x908
-    field public static final int HEALTH_UNCATEGORIZED = 2304; // 0x900
-    field public static final int HEALTH_WEIGHING = 2316; // 0x90c
-    field public static final int PHONE_CELLULAR = 516; // 0x204
-    field public static final int PHONE_CORDLESS = 520; // 0x208
-    field public static final int PHONE_ISDN = 532; // 0x214
-    field public static final int PHONE_MODEM_OR_GATEWAY = 528; // 0x210
-    field public static final int PHONE_SMART = 524; // 0x20c
-    field public static final int PHONE_UNCATEGORIZED = 512; // 0x200
-    field public static final int TOY_CONTROLLER = 2064; // 0x810
-    field public static final int TOY_DOLL_ACTION_FIGURE = 2060; // 0x80c
-    field public static final int TOY_GAME = 2068; // 0x814
-    field public static final int TOY_ROBOT = 2052; // 0x804
-    field public static final int TOY_UNCATEGORIZED = 2048; // 0x800
-    field public static final int TOY_VEHICLE = 2056; // 0x808
-    field public static final int WEARABLE_GLASSES = 1812; // 0x714
-    field public static final int WEARABLE_HELMET = 1808; // 0x710
-    field public static final int WEARABLE_JACKET = 1804; // 0x70c
-    field public static final int WEARABLE_PAGER = 1800; // 0x708
-    field public static final int WEARABLE_UNCATEGORIZED = 1792; // 0x700
-    field public static final int WEARABLE_WRIST_WATCH = 1796; // 0x704
-  }
-
-  public static class BluetoothClass.Device.Major {
-    ctor public BluetoothClass.Device.Major();
-    field public static final int AUDIO_VIDEO = 1024; // 0x400
-    field public static final int COMPUTER = 256; // 0x100
-    field public static final int HEALTH = 2304; // 0x900
-    field public static final int IMAGING = 1536; // 0x600
-    field public static final int MISC = 0; // 0x0
-    field public static final int NETWORKING = 768; // 0x300
-    field public static final int PERIPHERAL = 1280; // 0x500
-    field public static final int PHONE = 512; // 0x200
-    field public static final int TOY = 2048; // 0x800
-    field public static final int UNCATEGORIZED = 7936; // 0x1f00
-    field public static final int WEARABLE = 1792; // 0x700
-  }
-
-  public static final class BluetoothClass.Service {
-    ctor public BluetoothClass.Service();
-    field public static final int AUDIO = 2097152; // 0x200000
-    field public static final int CAPTURE = 524288; // 0x80000
-    field public static final int INFORMATION = 8388608; // 0x800000
-    field public static final int LE_AUDIO = 16384; // 0x4000
-    field public static final int LIMITED_DISCOVERABILITY = 8192; // 0x2000
-    field public static final int NETWORKING = 131072; // 0x20000
-    field public static final int OBJECT_TRANSFER = 1048576; // 0x100000
-    field public static final int POSITIONING = 65536; // 0x10000
-    field public static final int RENDER = 262144; // 0x40000
-    field public static final int TELEPHONY = 4194304; // 0x400000
-  }
-
-  public final class BluetoothCodecConfig implements android.os.Parcelable {
-    ctor public BluetoothCodecConfig(int);
-    method public int describeContents();
-    method public int getBitsPerSample();
-    method public int getChannelMode();
-    method public int getCodecPriority();
-    method public long getCodecSpecific1();
-    method public long getCodecSpecific2();
-    method public long getCodecSpecific3();
-    method public long getCodecSpecific4();
-    method public int getCodecType();
-    method public static int getMaxCodecType();
-    method public int getSampleRate();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final int BITS_PER_SAMPLE_16 = 1; // 0x1
-    field public static final int BITS_PER_SAMPLE_24 = 2; // 0x2
-    field public static final int BITS_PER_SAMPLE_32 = 4; // 0x4
-    field public static final int BITS_PER_SAMPLE_NONE = 0; // 0x0
-    field public static final int CHANNEL_MODE_MONO = 1; // 0x1
-    field public static final int CHANNEL_MODE_NONE = 0; // 0x0
-    field public static final int CHANNEL_MODE_STEREO = 2; // 0x2
-    field public static final int CODEC_PRIORITY_DEFAULT = 0; // 0x0
-    field public static final int CODEC_PRIORITY_DISABLED = -1; // 0xffffffff
-    field public static final int CODEC_PRIORITY_HIGHEST = 1000000; // 0xf4240
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothCodecConfig> CREATOR;
-    field public static final int SAMPLE_RATE_176400 = 16; // 0x10
-    field public static final int SAMPLE_RATE_192000 = 32; // 0x20
-    field public static final int SAMPLE_RATE_44100 = 1; // 0x1
-    field public static final int SAMPLE_RATE_48000 = 2; // 0x2
-    field public static final int SAMPLE_RATE_88200 = 4; // 0x4
-    field public static final int SAMPLE_RATE_96000 = 8; // 0x8
-    field public static final int SAMPLE_RATE_NONE = 0; // 0x0
-    field public static final int SOURCE_CODEC_TYPE_AAC = 1; // 0x1
-    field public static final int SOURCE_CODEC_TYPE_APTX = 2; // 0x2
-    field public static final int SOURCE_CODEC_TYPE_APTX_HD = 3; // 0x3
-    field public static final int SOURCE_CODEC_TYPE_INVALID = 1000000; // 0xf4240
-    field public static final int SOURCE_CODEC_TYPE_LC3 = 5; // 0x5
-    field public static final int SOURCE_CODEC_TYPE_LDAC = 4; // 0x4
-    field public static final int SOURCE_CODEC_TYPE_SBC = 0; // 0x0
-  }
-
-  public static final class BluetoothCodecConfig.Builder {
-    ctor public BluetoothCodecConfig.Builder();
-    method @NonNull public android.bluetooth.BluetoothCodecConfig build();
-    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setBitsPerSample(int);
-    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setChannelMode(int);
-    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecPriority(int);
-    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecSpecific1(long);
-    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecSpecific2(long);
-    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecSpecific3(long);
-    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecSpecific4(long);
-    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecType(int);
-    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setSampleRate(int);
-  }
-
-  public final class BluetoothCodecStatus implements android.os.Parcelable {
-    ctor public BluetoothCodecStatus(@Nullable android.bluetooth.BluetoothCodecConfig, @Nullable java.util.List<android.bluetooth.BluetoothCodecConfig>, @Nullable java.util.List<android.bluetooth.BluetoothCodecConfig>);
-    method public int describeContents();
-    method @Nullable public android.bluetooth.BluetoothCodecConfig getCodecConfig();
-    method @NonNull public java.util.List<android.bluetooth.BluetoothCodecConfig> getCodecsLocalCapabilities();
-    method @NonNull public java.util.List<android.bluetooth.BluetoothCodecConfig> getCodecsSelectableCapabilities();
-    method public boolean isCodecConfigSelectable(@Nullable android.bluetooth.BluetoothCodecConfig);
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothCodecStatus> CREATOR;
-    field public static final String EXTRA_CODEC_STATUS = "android.bluetooth.extra.CODEC_STATUS";
-  }
-
-  public final class BluetoothCsipSetCoordinator implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
-    method public void close();
-    method protected void finalize();
-    method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method public int getConnectionState(@Nullable android.bluetooth.BluetoothDevice);
-    method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]);
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CSIS_CONNECTION_STATE_CHANGED = "android.bluetooth.action.CSIS_CONNECTION_STATE_CHANGED";
-  }
-
-  public final class BluetoothDevice implements android.os.Parcelable {
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int, android.os.Handler);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean createBond();
-    method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothSocket createInsecureL2capChannel(int) throws java.io.IOException;
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
-    method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothSocket createL2capChannel(int) throws java.io.IOException;
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
-    method public int describeContents();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean fetchUuidsWithSdp();
-    method public String getAddress();
-    method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public String getAlias();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothClass getBluetoothClass();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getBondState();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public String getName();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getType();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.os.ParcelUuid[] getUuids();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int setAlias(@Nullable String);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setPairingConfirmation(boolean);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean setPin(byte[]);
-    method public void writeToParcel(android.os.Parcel, int);
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_ACL_CONNECTED = "android.bluetooth.device.action.ACL_CONNECTED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_ACL_DISCONNECTED = "android.bluetooth.device.action.ACL_DISCONNECTED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_ACL_DISCONNECT_REQUESTED = "android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_ALIAS_CHANGED = "android.bluetooth.device.action.ALIAS_CHANGED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_BOND_STATE_CHANGED = "android.bluetooth.device.action.BOND_STATE_CHANGED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CLASS_CHANGED = "android.bluetooth.device.action.CLASS_CHANGED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public static final String ACTION_FOUND = "android.bluetooth.device.action.FOUND";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_NAME_CHANGED = "android.bluetooth.device.action.NAME_CHANGED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_PAIRING_REQUEST = "android.bluetooth.device.action.PAIRING_REQUEST";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_UUID = "android.bluetooth.device.action.UUID";
-    field public static final int ADDRESS_TYPE_PUBLIC = 0; // 0x0
-    field public static final int ADDRESS_TYPE_RANDOM = 1; // 0x1
-    field public static final int BOND_BONDED = 12; // 0xc
-    field public static final int BOND_BONDING = 11; // 0xb
-    field public static final int BOND_NONE = 10; // 0xa
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothDevice> CREATOR;
-    field public static final int DEVICE_TYPE_CLASSIC = 1; // 0x1
-    field public static final int DEVICE_TYPE_DUAL = 3; // 0x3
-    field public static final int DEVICE_TYPE_LE = 2; // 0x2
-    field public static final int DEVICE_TYPE_UNKNOWN = 0; // 0x0
-    field public static final int ERROR = -2147483648; // 0x80000000
-    field public static final String EXTRA_BOND_STATE = "android.bluetooth.device.extra.BOND_STATE";
-    field public static final String EXTRA_CLASS = "android.bluetooth.device.extra.CLASS";
-    field public static final String EXTRA_DEVICE = "android.bluetooth.device.extra.DEVICE";
-    field public static final String EXTRA_IS_COORDINATED_SET_MEMBER = "android.bluetooth.extra.IS_COORDINATED_SET_MEMBER";
-    field public static final String EXTRA_NAME = "android.bluetooth.device.extra.NAME";
-    field public static final String EXTRA_PAIRING_KEY = "android.bluetooth.device.extra.PAIRING_KEY";
-    field public static final String EXTRA_PAIRING_VARIANT = "android.bluetooth.device.extra.PAIRING_VARIANT";
-    field public static final String EXTRA_PREVIOUS_BOND_STATE = "android.bluetooth.device.extra.PREVIOUS_BOND_STATE";
-    field public static final String EXTRA_RSSI = "android.bluetooth.device.extra.RSSI";
-    field public static final String EXTRA_TRANSPORT = "android.bluetooth.device.extra.TRANSPORT";
-    field public static final String EXTRA_UUID = "android.bluetooth.device.extra.UUID";
-    field public static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2; // 0x2
-    field public static final int PAIRING_VARIANT_PIN = 0; // 0x0
-    field public static final int PHY_LE_1M = 1; // 0x1
-    field public static final int PHY_LE_1M_MASK = 1; // 0x1
-    field public static final int PHY_LE_2M = 2; // 0x2
-    field public static final int PHY_LE_2M_MASK = 2; // 0x2
-    field public static final int PHY_LE_CODED = 3; // 0x3
-    field public static final int PHY_LE_CODED_MASK = 4; // 0x4
-    field public static final int PHY_OPTION_NO_PREFERRED = 0; // 0x0
-    field public static final int PHY_OPTION_S2 = 1; // 0x1
-    field public static final int PHY_OPTION_S8 = 2; // 0x2
-    field public static final int TRANSPORT_AUTO = 0; // 0x0
-    field public static final int TRANSPORT_BREDR = 1; // 0x1
-    field public static final int TRANSPORT_LE = 2; // 0x2
-  }
-
-  public final class BluetoothGatt implements android.bluetooth.BluetoothProfile {
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void abortReliableWrite();
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void abortReliableWrite(android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean beginReliableWrite();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void close();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean connect();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void disconnect();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean discoverServices();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean executeReliableWrite();
-    method @Deprecated public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method @Deprecated public int getConnectionState(android.bluetooth.BluetoothDevice);
-    method public android.bluetooth.BluetoothDevice getDevice();
-    method @Deprecated public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
-    method public android.bluetooth.BluetoothGattService getService(java.util.UUID);
-    method public java.util.List<android.bluetooth.BluetoothGattService> getServices();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean readCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean readDescriptor(android.bluetooth.BluetoothGattDescriptor);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void readPhy();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean readRemoteRssi();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean requestConnectionPriority(int);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean requestMtu(int);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean setCharacteristicNotification(android.bluetooth.BluetoothGattCharacteristic, boolean);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void setPreferredPhy(int, int, int);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean writeCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int writeCharacteristic(@NonNull android.bluetooth.BluetoothGattCharacteristic, @NonNull byte[], int);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean writeDescriptor(android.bluetooth.BluetoothGattDescriptor);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int writeDescriptor(@NonNull android.bluetooth.BluetoothGattDescriptor, @NonNull byte[]);
-    field public static final int CONNECTION_PRIORITY_BALANCED = 0; // 0x0
-    field public static final int CONNECTION_PRIORITY_HIGH = 1; // 0x1
-    field public static final int CONNECTION_PRIORITY_LOW_POWER = 2; // 0x2
-    field public static final int GATT_CONNECTION_CONGESTED = 143; // 0x8f
-    field public static final int GATT_FAILURE = 257; // 0x101
-    field public static final int GATT_INSUFFICIENT_AUTHENTICATION = 5; // 0x5
-    field public static final int GATT_INSUFFICIENT_AUTHORIZATION = 8; // 0x8
-    field public static final int GATT_INSUFFICIENT_ENCRYPTION = 15; // 0xf
-    field public static final int GATT_INVALID_ATTRIBUTE_LENGTH = 13; // 0xd
-    field public static final int GATT_INVALID_OFFSET = 7; // 0x7
-    field public static final int GATT_READ_NOT_PERMITTED = 2; // 0x2
-    field public static final int GATT_REQUEST_NOT_SUPPORTED = 6; // 0x6
-    field public static final int GATT_SUCCESS = 0; // 0x0
-    field public static final int GATT_WRITE_NOT_PERMITTED = 3; // 0x3
-  }
-
-  public abstract class BluetoothGattCallback {
-    ctor public BluetoothGattCallback();
-    method @Deprecated public void onCharacteristicChanged(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic);
-    method public void onCharacteristicChanged(@NonNull android.bluetooth.BluetoothGatt, @NonNull android.bluetooth.BluetoothGattCharacteristic, @NonNull byte[]);
-    method @Deprecated public void onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
-    method public void onCharacteristicRead(@NonNull android.bluetooth.BluetoothGatt, @NonNull android.bluetooth.BluetoothGattCharacteristic, @NonNull byte[], int);
-    method public void onCharacteristicWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
-    method public void onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int);
-    method @Deprecated public void onDescriptorRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int);
-    method public void onDescriptorRead(@NonNull android.bluetooth.BluetoothGatt, @NonNull android.bluetooth.BluetoothGattDescriptor, int, @NonNull byte[]);
-    method public void onDescriptorWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int);
-    method public void onMtuChanged(android.bluetooth.BluetoothGatt, int, int);
-    method public void onPhyRead(android.bluetooth.BluetoothGatt, int, int, int);
-    method public void onPhyUpdate(android.bluetooth.BluetoothGatt, int, int, int);
-    method public void onReadRemoteRssi(android.bluetooth.BluetoothGatt, int, int);
-    method public void onReliableWriteCompleted(android.bluetooth.BluetoothGatt, int);
-    method public void onServiceChanged(@NonNull android.bluetooth.BluetoothGatt);
-    method public void onServicesDiscovered(android.bluetooth.BluetoothGatt, int);
-  }
-
-  public class BluetoothGattCharacteristic implements android.os.Parcelable {
-    ctor public BluetoothGattCharacteristic(java.util.UUID, int, int);
-    method public boolean addDescriptor(android.bluetooth.BluetoothGattDescriptor);
-    method public int describeContents();
-    method public android.bluetooth.BluetoothGattDescriptor getDescriptor(java.util.UUID);
-    method public java.util.List<android.bluetooth.BluetoothGattDescriptor> getDescriptors();
-    method @Deprecated public Float getFloatValue(int, int);
-    method public int getInstanceId();
-    method @Deprecated public Integer getIntValue(int, int);
-    method public int getPermissions();
-    method public int getProperties();
-    method public android.bluetooth.BluetoothGattService getService();
-    method @Deprecated public String getStringValue(int);
-    method public java.util.UUID getUuid();
-    method @Deprecated public byte[] getValue();
-    method public int getWriteType();
-    method @Deprecated public boolean setValue(byte[]);
-    method @Deprecated public boolean setValue(int, int, int);
-    method @Deprecated public boolean setValue(int, int, int, int);
-    method @Deprecated public boolean setValue(String);
-    method public void setWriteType(int);
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattCharacteristic> CREATOR;
-    field public static final int FORMAT_FLOAT = 52; // 0x34
-    field public static final int FORMAT_SFLOAT = 50; // 0x32
-    field public static final int FORMAT_SINT16 = 34; // 0x22
-    field public static final int FORMAT_SINT32 = 36; // 0x24
-    field public static final int FORMAT_SINT8 = 33; // 0x21
-    field public static final int FORMAT_UINT16 = 18; // 0x12
-    field public static final int FORMAT_UINT32 = 20; // 0x14
-    field public static final int FORMAT_UINT8 = 17; // 0x11
-    field public static final int PERMISSION_READ = 1; // 0x1
-    field public static final int PERMISSION_READ_ENCRYPTED = 2; // 0x2
-    field public static final int PERMISSION_READ_ENCRYPTED_MITM = 4; // 0x4
-    field public static final int PERMISSION_WRITE = 16; // 0x10
-    field public static final int PERMISSION_WRITE_ENCRYPTED = 32; // 0x20
-    field public static final int PERMISSION_WRITE_ENCRYPTED_MITM = 64; // 0x40
-    field public static final int PERMISSION_WRITE_SIGNED = 128; // 0x80
-    field public static final int PERMISSION_WRITE_SIGNED_MITM = 256; // 0x100
-    field public static final int PROPERTY_BROADCAST = 1; // 0x1
-    field public static final int PROPERTY_EXTENDED_PROPS = 128; // 0x80
-    field public static final int PROPERTY_INDICATE = 32; // 0x20
-    field public static final int PROPERTY_NOTIFY = 16; // 0x10
-    field public static final int PROPERTY_READ = 2; // 0x2
-    field public static final int PROPERTY_SIGNED_WRITE = 64; // 0x40
-    field public static final int PROPERTY_WRITE = 8; // 0x8
-    field public static final int PROPERTY_WRITE_NO_RESPONSE = 4; // 0x4
-    field public static final int WRITE_TYPE_DEFAULT = 2; // 0x2
-    field public static final int WRITE_TYPE_NO_RESPONSE = 1; // 0x1
-    field public static final int WRITE_TYPE_SIGNED = 4; // 0x4
-    field protected java.util.List<android.bluetooth.BluetoothGattDescriptor> mDescriptors;
-  }
-
-  public class BluetoothGattDescriptor implements android.os.Parcelable {
-    ctor public BluetoothGattDescriptor(java.util.UUID, int);
-    method public int describeContents();
-    method public android.bluetooth.BluetoothGattCharacteristic getCharacteristic();
-    method public int getPermissions();
-    method public java.util.UUID getUuid();
-    method @Deprecated public byte[] getValue();
-    method @Deprecated public boolean setValue(byte[]);
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattDescriptor> CREATOR;
-    field public static final byte[] DISABLE_NOTIFICATION_VALUE;
-    field public static final byte[] ENABLE_INDICATION_VALUE;
-    field public static final byte[] ENABLE_NOTIFICATION_VALUE;
-    field public static final int PERMISSION_READ = 1; // 0x1
-    field public static final int PERMISSION_READ_ENCRYPTED = 2; // 0x2
-    field public static final int PERMISSION_READ_ENCRYPTED_MITM = 4; // 0x4
-    field public static final int PERMISSION_WRITE = 16; // 0x10
-    field public static final int PERMISSION_WRITE_ENCRYPTED = 32; // 0x20
-    field public static final int PERMISSION_WRITE_ENCRYPTED_MITM = 64; // 0x40
-    field public static final int PERMISSION_WRITE_SIGNED = 128; // 0x80
-    field public static final int PERMISSION_WRITE_SIGNED_MITM = 256; // 0x100
-  }
-
-  public final class BluetoothGattServer implements android.bluetooth.BluetoothProfile {
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean addService(android.bluetooth.BluetoothGattService);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void cancelConnection(android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void clearServices();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void close();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean connect(android.bluetooth.BluetoothDevice, boolean);
-    method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method public int getConnectionState(android.bluetooth.BluetoothDevice);
-    method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
-    method public android.bluetooth.BluetoothGattService getService(java.util.UUID);
-    method public java.util.List<android.bluetooth.BluetoothGattService> getServices();
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean notifyCharacteristicChanged(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothGattCharacteristic, boolean);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int notifyCharacteristicChanged(@NonNull android.bluetooth.BluetoothDevice, @NonNull android.bluetooth.BluetoothGattCharacteristic, boolean, @NonNull byte[]);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void readPhy(android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean removeService(android.bluetooth.BluetoothGattService);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean sendResponse(android.bluetooth.BluetoothDevice, int, int, int, byte[]);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void setPreferredPhy(android.bluetooth.BluetoothDevice, int, int, int);
-  }
-
-  public abstract class BluetoothGattServerCallback {
-    ctor public BluetoothGattServerCallback();
-    method public void onCharacteristicReadRequest(android.bluetooth.BluetoothDevice, int, int, android.bluetooth.BluetoothGattCharacteristic);
-    method public void onCharacteristicWriteRequest(android.bluetooth.BluetoothDevice, int, android.bluetooth.BluetoothGattCharacteristic, boolean, boolean, int, byte[]);
-    method public void onConnectionStateChange(android.bluetooth.BluetoothDevice, int, int);
-    method public void onDescriptorReadRequest(android.bluetooth.BluetoothDevice, int, int, android.bluetooth.BluetoothGattDescriptor);
-    method public void onDescriptorWriteRequest(android.bluetooth.BluetoothDevice, int, android.bluetooth.BluetoothGattDescriptor, boolean, boolean, int, byte[]);
-    method public void onExecuteWrite(android.bluetooth.BluetoothDevice, int, boolean);
-    method public void onMtuChanged(android.bluetooth.BluetoothDevice, int);
-    method public void onNotificationSent(android.bluetooth.BluetoothDevice, int);
-    method public void onPhyRead(android.bluetooth.BluetoothDevice, int, int, int);
-    method public void onPhyUpdate(android.bluetooth.BluetoothDevice, int, int, int);
-    method public void onServiceAdded(int, android.bluetooth.BluetoothGattService);
-  }
-
-  public class BluetoothGattService implements android.os.Parcelable {
-    ctor public BluetoothGattService(java.util.UUID, int);
-    method public boolean addCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
-    method public boolean addService(android.bluetooth.BluetoothGattService);
-    method public int describeContents();
-    method public android.bluetooth.BluetoothGattCharacteristic getCharacteristic(java.util.UUID);
-    method public java.util.List<android.bluetooth.BluetoothGattCharacteristic> getCharacteristics();
-    method public java.util.List<android.bluetooth.BluetoothGattService> getIncludedServices();
-    method public int getInstanceId();
-    method public int getType();
-    method public java.util.UUID getUuid();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattService> CREATOR;
-    field public static final int SERVICE_TYPE_PRIMARY = 0; // 0x0
-    field public static final int SERVICE_TYPE_SECONDARY = 1; // 0x1
-    field protected java.util.List<android.bluetooth.BluetoothGattCharacteristic> mCharacteristics;
-    field protected java.util.List<android.bluetooth.BluetoothGattService> mIncludedServices;
-  }
-
-  public final class BluetoothHeadset implements android.bluetooth.BluetoothProfile {
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isAudioConnected(android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isNoiseReductionSupported(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isVoiceRecognitionSupported(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean sendVendorSpecificResultCode(android.bluetooth.BluetoothDevice, String, String);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean startVoiceRecognition(android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean stopVoiceRecognition(android.bluetooth.BluetoothDevice);
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_AUDIO_STATE_CHANGED = "android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_VENDOR_SPECIFIC_HEADSET_EVENT = "android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT";
-    field public static final int AT_CMD_TYPE_ACTION = 4; // 0x4
-    field public static final int AT_CMD_TYPE_BASIC = 3; // 0x3
-    field public static final int AT_CMD_TYPE_READ = 0; // 0x0
-    field public static final int AT_CMD_TYPE_SET = 2; // 0x2
-    field public static final int AT_CMD_TYPE_TEST = 1; // 0x1
-    field public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS = "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_ARGS";
-    field public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD = "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_CMD";
-    field public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE = "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE";
-    field public static final int STATE_AUDIO_CONNECTED = 12; // 0xc
-    field public static final int STATE_AUDIO_CONNECTING = 11; // 0xb
-    field public static final int STATE_AUDIO_DISCONNECTED = 10; // 0xa
-    field public static final String VENDOR_RESULT_CODE_COMMAND_ANDROID = "+ANDROID";
-    field public static final String VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY = "android.bluetooth.headset.intent.category.companyid";
-  }
-
-  @Deprecated public final class BluetoothHealth implements android.bluetooth.BluetoothProfile {
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean connectChannelToSource(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothHealthAppConfiguration);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disconnectChannel(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothHealthAppConfiguration, int);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(android.bluetooth.BluetoothDevice);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.os.ParcelFileDescriptor getMainChannelFd(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothHealthAppConfiguration);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean registerSinkAppConfiguration(String, int, android.bluetooth.BluetoothHealthCallback);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean unregisterAppConfiguration(android.bluetooth.BluetoothHealthAppConfiguration);
-    field @Deprecated public static final int APP_CONFIG_REGISTRATION_FAILURE = 1; // 0x1
-    field @Deprecated public static final int APP_CONFIG_REGISTRATION_SUCCESS = 0; // 0x0
-    field @Deprecated public static final int APP_CONFIG_UNREGISTRATION_FAILURE = 3; // 0x3
-    field @Deprecated public static final int APP_CONFIG_UNREGISTRATION_SUCCESS = 2; // 0x2
-    field @Deprecated public static final int CHANNEL_TYPE_RELIABLE = 10; // 0xa
-    field @Deprecated public static final int CHANNEL_TYPE_STREAMING = 11; // 0xb
-    field @Deprecated public static final int SINK_ROLE = 2; // 0x2
-    field @Deprecated public static final int SOURCE_ROLE = 1; // 0x1
-    field @Deprecated public static final int STATE_CHANNEL_CONNECTED = 2; // 0x2
-    field @Deprecated public static final int STATE_CHANNEL_CONNECTING = 1; // 0x1
-    field @Deprecated public static final int STATE_CHANNEL_DISCONNECTED = 0; // 0x0
-    field @Deprecated public static final int STATE_CHANNEL_DISCONNECTING = 3; // 0x3
-  }
-
-  @Deprecated public final class BluetoothHealthAppConfiguration implements android.os.Parcelable {
-    method @Deprecated public int describeContents();
-    method @Deprecated public int getDataType();
-    method @Deprecated public String getName();
-    method @Deprecated public int getRole();
-    method @Deprecated public void writeToParcel(android.os.Parcel, int);
-    field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothHealthAppConfiguration> CREATOR;
-  }
-
-  @Deprecated public abstract class BluetoothHealthCallback {
-    ctor @Deprecated public BluetoothHealthCallback();
-    method @Deprecated @BinderThread public void onHealthAppConfigurationStatusChange(android.bluetooth.BluetoothHealthAppConfiguration, int);
-    method @Deprecated @BinderThread public void onHealthChannelStateChange(android.bluetooth.BluetoothHealthAppConfiguration, android.bluetooth.BluetoothDevice, int, int, android.os.ParcelFileDescriptor, int);
-  }
-
-  public final class BluetoothHearingAid implements android.bluetooth.BluetoothProfile {
-    method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice);
-    method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]);
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.hearingaid.profile.action.CONNECTION_STATE_CHANGED";
-  }
-
-  public final class BluetoothHidDevice implements android.bluetooth.BluetoothProfile {
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean connect(android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disconnect(android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean registerApp(android.bluetooth.BluetoothHidDeviceAppSdpSettings, android.bluetooth.BluetoothHidDeviceAppQosSettings, android.bluetooth.BluetoothHidDeviceAppQosSettings, java.util.concurrent.Executor, android.bluetooth.BluetoothHidDevice.Callback);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean replyReport(android.bluetooth.BluetoothDevice, byte, byte, byte[]);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean reportError(android.bluetooth.BluetoothDevice, byte);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean sendReport(android.bluetooth.BluetoothDevice, int, byte[]);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean unregisterApp();
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.hiddevice.profile.action.CONNECTION_STATE_CHANGED";
-    field public static final byte ERROR_RSP_INVALID_PARAM = 4; // 0x4
-    field public static final byte ERROR_RSP_INVALID_RPT_ID = 2; // 0x2
-    field public static final byte ERROR_RSP_NOT_READY = 1; // 0x1
-    field public static final byte ERROR_RSP_SUCCESS = 0; // 0x0
-    field public static final byte ERROR_RSP_UNKNOWN = 14; // 0xe
-    field public static final byte ERROR_RSP_UNSUPPORTED_REQ = 3; // 0x3
-    field public static final byte PROTOCOL_BOOT_MODE = 0; // 0x0
-    field public static final byte PROTOCOL_REPORT_MODE = 1; // 0x1
-    field public static final byte REPORT_TYPE_FEATURE = 3; // 0x3
-    field public static final byte REPORT_TYPE_INPUT = 1; // 0x1
-    field public static final byte REPORT_TYPE_OUTPUT = 2; // 0x2
-    field public static final byte SUBCLASS1_COMBO = -64; // 0xffffffc0
-    field public static final byte SUBCLASS1_KEYBOARD = 64; // 0x40
-    field public static final byte SUBCLASS1_MOUSE = -128; // 0xffffff80
-    field public static final byte SUBCLASS1_NONE = 0; // 0x0
-    field public static final byte SUBCLASS2_CARD_READER = 6; // 0x6
-    field public static final byte SUBCLASS2_DIGITIZER_TABLET = 5; // 0x5
-    field public static final byte SUBCLASS2_GAMEPAD = 2; // 0x2
-    field public static final byte SUBCLASS2_JOYSTICK = 1; // 0x1
-    field public static final byte SUBCLASS2_REMOTE_CONTROL = 3; // 0x3
-    field public static final byte SUBCLASS2_SENSING_DEVICE = 4; // 0x4
-    field public static final byte SUBCLASS2_UNCATEGORIZED = 0; // 0x0
-  }
-
-  public abstract static class BluetoothHidDevice.Callback {
-    ctor public BluetoothHidDevice.Callback();
-    method public void onAppStatusChanged(android.bluetooth.BluetoothDevice, boolean);
-    method public void onConnectionStateChanged(android.bluetooth.BluetoothDevice, int);
-    method public void onGetReport(android.bluetooth.BluetoothDevice, byte, byte, int);
-    method public void onInterruptData(android.bluetooth.BluetoothDevice, byte, byte[]);
-    method public void onSetProtocol(android.bluetooth.BluetoothDevice, byte);
-    method public void onSetReport(android.bluetooth.BluetoothDevice, byte, byte, byte[]);
-    method public void onVirtualCableUnplug(android.bluetooth.BluetoothDevice);
-  }
-
-  public final class BluetoothHidDeviceAppQosSettings implements android.os.Parcelable {
-    ctor public BluetoothHidDeviceAppQosSettings(int, int, int, int, int, int);
-    method public int describeContents();
-    method public int getDelayVariation();
-    method public int getLatency();
-    method public int getPeakBandwidth();
-    method public int getServiceType();
-    method public int getTokenBucketSize();
-    method public int getTokenRate();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothHidDeviceAppQosSettings> CREATOR;
-    field public static final int MAX = -1; // 0xffffffff
-    field public static final int SERVICE_BEST_EFFORT = 1; // 0x1
-    field public static final int SERVICE_GUARANTEED = 2; // 0x2
-    field public static final int SERVICE_NO_TRAFFIC = 0; // 0x0
-  }
-
-  public final class BluetoothHidDeviceAppSdpSettings implements android.os.Parcelable {
-    ctor public BluetoothHidDeviceAppSdpSettings(String, String, String, byte, byte[]);
-    method public int describeContents();
-    method public String getDescription();
-    method public byte[] getDescriptors();
-    method public String getName();
-    method public String getProvider();
-    method public byte getSubclass();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothHidDeviceAppSdpSettings> CREATOR;
-  }
-
-  public final class BluetoothLeAudio implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
-    method public void close();
-    method protected void finalize();
-    method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothDevice getConnectedGroupLeadDevice(int);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice);
-    method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getGroupId(@NonNull android.bluetooth.BluetoothDevice);
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED = "android.bluetooth.action.LE_AUDIO_CONNECTION_STATE_CHANGED";
-  }
-
-  public final class BluetoothLeAudioCodecConfig implements android.os.Parcelable {
-    method public int describeContents();
-    method public int getBitsPerSample();
-    method public int getChannelMode();
-    method @NonNull public String getCodecName();
-    method public int getCodecPriority();
-    method public int getCodecType();
-    method public int getFrameDuration();
-    method public static int getMaxCodecType();
-    method public int getOctetsPerFrame();
-    method public int getSampleRate();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field public static final int BITS_PER_SAMPLE_16 = 1; // 0x1
-    field public static final int BITS_PER_SAMPLE_24 = 2; // 0x2
-    field public static final int BITS_PER_SAMPLE_32 = 3; // 0x3
-    field public static final int BITS_PER_SAMPLE_NONE = 0; // 0x0
-    field public static final int CHANNEL_MODE_MONO = 1; // 0x1
-    field public static final int CHANNEL_MODE_NONE = 0; // 0x0
-    field public static final int CHANNEL_MODE_STEREO = 2; // 0x2
-    field public static final int CODEC_PRIORITY_DEFAULT = 0; // 0x0
-    field public static final int CODEC_PRIORITY_DISABLED = -1; // 0xffffffff
-    field public static final int CODEC_PRIORITY_HIGHEST = 1000000; // 0xf4240
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothLeAudioCodecConfig> CREATOR;
-    field public static final int FRAME_DURATION_10000 = 2; // 0x2
-    field public static final int FRAME_DURATION_7500 = 1; // 0x1
-    field public static final int FRAME_DURATION_NONE = 0; // 0x0
-    field public static final int SAMPLE_RATE_16000 = 2; // 0x2
-    field public static final int SAMPLE_RATE_24000 = 3; // 0x3
-    field public static final int SAMPLE_RATE_32000 = 4; // 0x4
-    field public static final int SAMPLE_RATE_44100 = 5; // 0x5
-    field public static final int SAMPLE_RATE_48000 = 6; // 0x6
-    field public static final int SAMPLE_RATE_8000 = 1; // 0x1
-    field public static final int SAMPLE_RATE_NONE = 0; // 0x0
-    field public static final int SOURCE_CODEC_TYPE_INVALID = 1000000; // 0xf4240
-    field public static final int SOURCE_CODEC_TYPE_LC3 = 0; // 0x0
-  }
-
-  public static final class BluetoothLeAudioCodecConfig.Builder {
-    ctor public BluetoothLeAudioCodecConfig.Builder();
-    ctor public BluetoothLeAudioCodecConfig.Builder(@NonNull android.bluetooth.BluetoothLeAudioCodecConfig);
-    method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig build();
-    method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig.Builder setBitsPerSample(int);
-    method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig.Builder setChannelMode(int);
-    method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig.Builder setCodecPriority(int);
-    method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig.Builder setCodecType(int);
-    method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig.Builder setFrameDuration(int);
-    method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig.Builder setOctetsPerFrame(int);
-    method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig.Builder setSampleRate(int);
-  }
-
-  public final class BluetoothManager {
-    method public android.bluetooth.BluetoothAdapter getAdapter();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(int);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(android.bluetooth.BluetoothDevice, int);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int, int[]);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothGattServer openGattServer(android.content.Context, android.bluetooth.BluetoothGattServerCallback);
-  }
-
-  public interface BluetoothProfile {
-    method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method public int getConnectionState(android.bluetooth.BluetoothDevice);
-    method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
-    field public static final int A2DP = 2; // 0x2
-    field public static final int CSIP_SET_COORDINATOR = 25; // 0x19
-    field public static final String EXTRA_PREVIOUS_STATE = "android.bluetooth.profile.extra.PREVIOUS_STATE";
-    field public static final String EXTRA_STATE = "android.bluetooth.profile.extra.STATE";
-    field public static final int GATT = 7; // 0x7
-    field public static final int GATT_SERVER = 8; // 0x8
-    field public static final int HAP_CLIENT = 28; // 0x1c
-    field public static final int HEADSET = 1; // 0x1
-    field @Deprecated public static final int HEALTH = 3; // 0x3
-    field public static final int HEARING_AID = 21; // 0x15
-    field public static final int HID_DEVICE = 19; // 0x13
-    field public static final int LE_AUDIO = 22; // 0x16
-    field public static final int SAP = 10; // 0xa
-    field public static final int STATE_CONNECTED = 2; // 0x2
-    field public static final int STATE_CONNECTING = 1; // 0x1
-    field public static final int STATE_DISCONNECTED = 0; // 0x0
-    field public static final int STATE_DISCONNECTING = 3; // 0x3
-  }
-
-  public static interface BluetoothProfile.ServiceListener {
-    method public void onServiceConnected(int, android.bluetooth.BluetoothProfile);
-    method public void onServiceDisconnected(int);
-  }
-
-  public final class BluetoothServerSocket implements java.io.Closeable {
-    method public android.bluetooth.BluetoothSocket accept() throws java.io.IOException;
-    method public android.bluetooth.BluetoothSocket accept(int) throws java.io.IOException;
-    method public void close() throws java.io.IOException;
-    method public int getPsm();
-  }
-
-  public final class BluetoothSocket implements java.io.Closeable {
-    method public void close() throws java.io.IOException;
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void connect() throws java.io.IOException;
-    method public int getConnectionType();
-    method public java.io.InputStream getInputStream() throws java.io.IOException;
-    method public int getMaxReceivePacketSize();
-    method public int getMaxTransmitPacketSize();
-    method public java.io.OutputStream getOutputStream() throws java.io.IOException;
-    method public android.bluetooth.BluetoothDevice getRemoteDevice();
-    method public boolean isConnected();
-    field public static final int TYPE_L2CAP = 3; // 0x3
-    field public static final int TYPE_RFCOMM = 1; // 0x1
-    field public static final int TYPE_SCO = 2; // 0x2
-  }
-
-  public final class BluetoothStatusCodes {
-    field public static final int ERROR_BLUETOOTH_NOT_ALLOWED = 2; // 0x2
-    field public static final int ERROR_BLUETOOTH_NOT_ENABLED = 1; // 0x1
-    field public static final int ERROR_DEVICE_NOT_BONDED = 3; // 0x3
-    field public static final int ERROR_GATT_WRITE_NOT_ALLOWED = 200; // 0xc8
-    field public static final int ERROR_GATT_WRITE_REQUEST_BUSY = 201; // 0xc9
-    field public static final int ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION = 6; // 0x6
-    field public static final int ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION = 8; // 0x8
-    field public static final int ERROR_PROFILE_SERVICE_NOT_BOUND = 9; // 0x9
-    field public static final int ERROR_UNKNOWN = 2147483647; // 0x7fffffff
-    field public static final int FEATURE_NOT_SUPPORTED = 11; // 0xb
-    field public static final int FEATURE_SUPPORTED = 10; // 0xa
-    field public static final int SUCCESS = 0; // 0x0
-  }
-
-}
-
-package android.bluetooth.le {
-
-  public abstract class AdvertiseCallback {
-    ctor public AdvertiseCallback();
-    method public void onStartFailure(int);
-    method public void onStartSuccess(android.bluetooth.le.AdvertiseSettings);
-    field public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3; // 0x3
-    field public static final int ADVERTISE_FAILED_DATA_TOO_LARGE = 1; // 0x1
-    field public static final int ADVERTISE_FAILED_FEATURE_UNSUPPORTED = 5; // 0x5
-    field public static final int ADVERTISE_FAILED_INTERNAL_ERROR = 4; // 0x4
-    field public static final int ADVERTISE_FAILED_TOO_MANY_ADVERTISERS = 2; // 0x2
-  }
-
-  public final class AdvertiseData implements android.os.Parcelable {
-    method public int describeContents();
-    method public boolean getIncludeDeviceName();
-    method public boolean getIncludeTxPowerLevel();
-    method public android.util.SparseArray<byte[]> getManufacturerSpecificData();
-    method public java.util.Map<android.os.ParcelUuid,byte[]> getServiceData();
-    method @NonNull public java.util.List<android.os.ParcelUuid> getServiceSolicitationUuids();
-    method public java.util.List<android.os.ParcelUuid> getServiceUuids();
-    method @NonNull public java.util.List<android.bluetooth.le.TransportDiscoveryData> getTransportDiscoveryData();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertiseData> CREATOR;
-  }
-
-  public static final class AdvertiseData.Builder {
-    ctor public AdvertiseData.Builder();
-    method public android.bluetooth.le.AdvertiseData.Builder addManufacturerData(int, byte[]);
-    method public android.bluetooth.le.AdvertiseData.Builder addServiceData(android.os.ParcelUuid, byte[]);
-    method @NonNull public android.bluetooth.le.AdvertiseData.Builder addServiceSolicitationUuid(@NonNull android.os.ParcelUuid);
-    method public android.bluetooth.le.AdvertiseData.Builder addServiceUuid(android.os.ParcelUuid);
-    method @NonNull public android.bluetooth.le.AdvertiseData.Builder addTransportDiscoveryData(@NonNull android.bluetooth.le.TransportDiscoveryData);
-    method public android.bluetooth.le.AdvertiseData build();
-    method public android.bluetooth.le.AdvertiseData.Builder setIncludeDeviceName(boolean);
-    method public android.bluetooth.le.AdvertiseData.Builder setIncludeTxPowerLevel(boolean);
-  }
-
-  public final class AdvertiseSettings implements android.os.Parcelable {
-    method public int describeContents();
-    method public int getMode();
-    method public int getTimeout();
-    method public int getTxPowerLevel();
-    method public boolean isConnectable();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final int ADVERTISE_MODE_BALANCED = 1; // 0x1
-    field public static final int ADVERTISE_MODE_LOW_LATENCY = 2; // 0x2
-    field public static final int ADVERTISE_MODE_LOW_POWER = 0; // 0x0
-    field public static final int ADVERTISE_TX_POWER_HIGH = 3; // 0x3
-    field public static final int ADVERTISE_TX_POWER_LOW = 1; // 0x1
-    field public static final int ADVERTISE_TX_POWER_MEDIUM = 2; // 0x2
-    field public static final int ADVERTISE_TX_POWER_ULTRA_LOW = 0; // 0x0
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertiseSettings> CREATOR;
-  }
-
-  public static final class AdvertiseSettings.Builder {
-    ctor public AdvertiseSettings.Builder();
-    method public android.bluetooth.le.AdvertiseSettings build();
-    method public android.bluetooth.le.AdvertiseSettings.Builder setAdvertiseMode(int);
-    method public android.bluetooth.le.AdvertiseSettings.Builder setConnectable(boolean);
-    method public android.bluetooth.le.AdvertiseSettings.Builder setTimeout(int);
-    method public android.bluetooth.le.AdvertiseSettings.Builder setTxPowerLevel(int);
-  }
-
-  public final class AdvertisingSet {
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void enableAdvertising(boolean, int, int);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void setAdvertisingData(android.bluetooth.le.AdvertiseData);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void setAdvertisingParameters(android.bluetooth.le.AdvertisingSetParameters);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void setPeriodicAdvertisingData(android.bluetooth.le.AdvertiseData);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void setPeriodicAdvertisingEnabled(boolean);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void setPeriodicAdvertisingParameters(android.bluetooth.le.PeriodicAdvertisingParameters);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void setScanResponseData(android.bluetooth.le.AdvertiseData);
-  }
-
-  public abstract class AdvertisingSetCallback {
-    ctor public AdvertisingSetCallback();
-    method public void onAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int);
-    method public void onAdvertisingEnabled(android.bluetooth.le.AdvertisingSet, boolean, int);
-    method public void onAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int, int);
-    method public void onAdvertisingSetStarted(android.bluetooth.le.AdvertisingSet, int, int);
-    method public void onAdvertisingSetStopped(android.bluetooth.le.AdvertisingSet);
-    method public void onPeriodicAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int);
-    method public void onPeriodicAdvertisingEnabled(android.bluetooth.le.AdvertisingSet, boolean, int);
-    method public void onPeriodicAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int);
-    method public void onScanResponseDataSet(android.bluetooth.le.AdvertisingSet, int);
-    field public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3; // 0x3
-    field public static final int ADVERTISE_FAILED_DATA_TOO_LARGE = 1; // 0x1
-    field public static final int ADVERTISE_FAILED_FEATURE_UNSUPPORTED = 5; // 0x5
-    field public static final int ADVERTISE_FAILED_INTERNAL_ERROR = 4; // 0x4
-    field public static final int ADVERTISE_FAILED_TOO_MANY_ADVERTISERS = 2; // 0x2
-    field public static final int ADVERTISE_SUCCESS = 0; // 0x0
-  }
-
-  public final class AdvertisingSetParameters implements android.os.Parcelable {
-    method public int describeContents();
-    method public int getInterval();
-    method public int getPrimaryPhy();
-    method public int getSecondaryPhy();
-    method public int getTxPowerLevel();
-    method public boolean includeTxPower();
-    method public boolean isAnonymous();
-    method public boolean isConnectable();
-    method public boolean isLegacy();
-    method public boolean isScannable();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertisingSetParameters> CREATOR;
-    field public static final int INTERVAL_HIGH = 1600; // 0x640
-    field public static final int INTERVAL_LOW = 160; // 0xa0
-    field public static final int INTERVAL_MAX = 16777215; // 0xffffff
-    field public static final int INTERVAL_MEDIUM = 400; // 0x190
-    field public static final int INTERVAL_MIN = 160; // 0xa0
-    field public static final int TX_POWER_HIGH = 1; // 0x1
-    field public static final int TX_POWER_LOW = -15; // 0xfffffff1
-    field public static final int TX_POWER_MAX = 1; // 0x1
-    field public static final int TX_POWER_MEDIUM = -7; // 0xfffffff9
-    field public static final int TX_POWER_MIN = -127; // 0xffffff81
-    field public static final int TX_POWER_ULTRA_LOW = -21; // 0xffffffeb
-  }
-
-  public static final class AdvertisingSetParameters.Builder {
-    ctor public AdvertisingSetParameters.Builder();
-    method public android.bluetooth.le.AdvertisingSetParameters build();
-    method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymous(boolean);
-    method public android.bluetooth.le.AdvertisingSetParameters.Builder setConnectable(boolean);
-    method public android.bluetooth.le.AdvertisingSetParameters.Builder setIncludeTxPower(boolean);
-    method public android.bluetooth.le.AdvertisingSetParameters.Builder setInterval(int);
-    method public android.bluetooth.le.AdvertisingSetParameters.Builder setLegacyMode(boolean);
-    method public android.bluetooth.le.AdvertisingSetParameters.Builder setPrimaryPhy(int);
-    method public android.bluetooth.le.AdvertisingSetParameters.Builder setScannable(boolean);
-    method public android.bluetooth.le.AdvertisingSetParameters.Builder setSecondaryPhy(int);
-    method public android.bluetooth.le.AdvertisingSetParameters.Builder setTxPowerLevel(int);
-  }
-
-  public final class BluetoothLeAdvertiser {
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, int, android.bluetooth.le.AdvertisingSetCallback);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, int, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void stopAdvertising(android.bluetooth.le.AdvertiseCallback);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void stopAdvertisingSet(android.bluetooth.le.AdvertisingSetCallback);
-  }
-
-  public final class BluetoothLeScanner {
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void flushPendingScanResults(android.bluetooth.le.ScanCallback);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void startScan(android.bluetooth.le.ScanCallback);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public int startScan(@Nullable java.util.List<android.bluetooth.le.ScanFilter>, @Nullable android.bluetooth.le.ScanSettings, @NonNull android.app.PendingIntent);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void stopScan(android.bluetooth.le.ScanCallback);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void stopScan(android.app.PendingIntent);
-    field public static final String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE";
-    field public static final String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE";
-    field public static final String EXTRA_LIST_SCAN_RESULT = "android.bluetooth.le.extra.LIST_SCAN_RESULT";
-  }
-
-  public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
-    method public int describeContents();
-    method public boolean getIncludeTxPower();
-    method public int getInterval();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.bluetooth.le.PeriodicAdvertisingParameters> CREATOR;
-  }
-
-  public static final class PeriodicAdvertisingParameters.Builder {
-    ctor public PeriodicAdvertisingParameters.Builder();
-    method public android.bluetooth.le.PeriodicAdvertisingParameters build();
-    method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setIncludeTxPower(boolean);
-    method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setInterval(int);
-  }
-
-  public abstract class ScanCallback {
-    ctor public ScanCallback();
-    method public void onBatchScanResults(java.util.List<android.bluetooth.le.ScanResult>);
-    method public void onScanFailed(int);
-    method public void onScanResult(int, android.bluetooth.le.ScanResult);
-    field public static final int SCAN_FAILED_ALREADY_STARTED = 1; // 0x1
-    field public static final int SCAN_FAILED_APPLICATION_REGISTRATION_FAILED = 2; // 0x2
-    field public static final int SCAN_FAILED_FEATURE_UNSUPPORTED = 4; // 0x4
-    field public static final int SCAN_FAILED_INTERNAL_ERROR = 3; // 0x3
-  }
-
-  public final class ScanFilter implements android.os.Parcelable {
-    method public int describeContents();
-    method @Nullable public String getDeviceAddress();
-    method @Nullable public String getDeviceName();
-    method @Nullable public byte[] getManufacturerData();
-    method @Nullable public byte[] getManufacturerDataMask();
-    method public int getManufacturerId();
-    method @Nullable public byte[] getServiceData();
-    method @Nullable public byte[] getServiceDataMask();
-    method @Nullable public android.os.ParcelUuid getServiceDataUuid();
-    method @Nullable public android.os.ParcelUuid getServiceSolicitationUuid();
-    method @Nullable public android.os.ParcelUuid getServiceSolicitationUuidMask();
-    method @Nullable public android.os.ParcelUuid getServiceUuid();
-    method @Nullable public android.os.ParcelUuid getServiceUuidMask();
-    method public boolean matches(android.bluetooth.le.ScanResult);
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanFilter> CREATOR;
-  }
-
-  public static final class ScanFilter.Builder {
-    ctor public ScanFilter.Builder();
-    method public android.bluetooth.le.ScanFilter build();
-    method public android.bluetooth.le.ScanFilter.Builder setDeviceAddress(String);
-    method public android.bluetooth.le.ScanFilter.Builder setDeviceName(String);
-    method public android.bluetooth.le.ScanFilter.Builder setManufacturerData(int, byte[]);
-    method public android.bluetooth.le.ScanFilter.Builder setManufacturerData(int, byte[], byte[]);
-    method public android.bluetooth.le.ScanFilter.Builder setServiceData(android.os.ParcelUuid, byte[]);
-    method public android.bluetooth.le.ScanFilter.Builder setServiceData(android.os.ParcelUuid, byte[], byte[]);
-    method @NonNull public android.bluetooth.le.ScanFilter.Builder setServiceSolicitationUuid(@Nullable android.os.ParcelUuid);
-    method @NonNull public android.bluetooth.le.ScanFilter.Builder setServiceSolicitationUuid(@Nullable android.os.ParcelUuid, @Nullable android.os.ParcelUuid);
-    method public android.bluetooth.le.ScanFilter.Builder setServiceUuid(android.os.ParcelUuid);
-    method public android.bluetooth.le.ScanFilter.Builder setServiceUuid(android.os.ParcelUuid, android.os.ParcelUuid);
-  }
-
-  public final class ScanRecord {
-    method public int getAdvertiseFlags();
-    method public byte[] getBytes();
-    method @Nullable public String getDeviceName();
-    method public android.util.SparseArray<byte[]> getManufacturerSpecificData();
-    method @Nullable public byte[] getManufacturerSpecificData(int);
-    method public java.util.Map<android.os.ParcelUuid,byte[]> getServiceData();
-    method @Nullable public byte[] getServiceData(android.os.ParcelUuid);
-    method @NonNull public java.util.List<android.os.ParcelUuid> getServiceSolicitationUuids();
-    method public java.util.List<android.os.ParcelUuid> getServiceUuids();
-    method public int getTxPowerLevel();
-  }
-
-  public final class ScanResult implements android.os.Parcelable {
-    ctor @Deprecated public ScanResult(android.bluetooth.BluetoothDevice, android.bluetooth.le.ScanRecord, int, long);
-    ctor public ScanResult(android.bluetooth.BluetoothDevice, int, int, int, int, int, int, int, android.bluetooth.le.ScanRecord, long);
-    method public int describeContents();
-    method public int getAdvertisingSid();
-    method public int getDataStatus();
-    method public android.bluetooth.BluetoothDevice getDevice();
-    method public int getPeriodicAdvertisingInterval();
-    method public int getPrimaryPhy();
-    method public int getRssi();
-    method @Nullable public android.bluetooth.le.ScanRecord getScanRecord();
-    method public int getSecondaryPhy();
-    method public long getTimestampNanos();
-    method public int getTxPower();
-    method public boolean isConnectable();
-    method public boolean isLegacy();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanResult> CREATOR;
-    field public static final int DATA_COMPLETE = 0; // 0x0
-    field public static final int DATA_TRUNCATED = 2; // 0x2
-    field public static final int PERIODIC_INTERVAL_NOT_PRESENT = 0; // 0x0
-    field public static final int PHY_UNUSED = 0; // 0x0
-    field public static final int SID_NOT_PRESENT = 255; // 0xff
-    field public static final int TX_POWER_NOT_PRESENT = 127; // 0x7f
-  }
-
-  public final class ScanSettings implements android.os.Parcelable {
-    method public int describeContents();
-    method public int getCallbackType();
-    method public boolean getLegacy();
-    method public int getPhy();
-    method public long getReportDelayMillis();
-    method public int getScanMode();
-    method public int getScanResultType();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final int CALLBACK_TYPE_ALL_MATCHES = 1; // 0x1
-    field public static final int CALLBACK_TYPE_FIRST_MATCH = 2; // 0x2
-    field public static final int CALLBACK_TYPE_MATCH_LOST = 4; // 0x4
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanSettings> CREATOR;
-    field public static final int MATCH_MODE_AGGRESSIVE = 1; // 0x1
-    field public static final int MATCH_MODE_STICKY = 2; // 0x2
-    field public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2; // 0x2
-    field public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3; // 0x3
-    field public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1; // 0x1
-    field public static final int PHY_LE_ALL_SUPPORTED = 255; // 0xff
-    field public static final int SCAN_MODE_BALANCED = 1; // 0x1
-    field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2
-    field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0
-    field public static final int SCAN_MODE_OPPORTUNISTIC = -1; // 0xffffffff
-  }
-
-  public static final class ScanSettings.Builder {
-    ctor public ScanSettings.Builder();
-    method public android.bluetooth.le.ScanSettings build();
-    method public android.bluetooth.le.ScanSettings.Builder setCallbackType(int);
-    method public android.bluetooth.le.ScanSettings.Builder setLegacy(boolean);
-    method public android.bluetooth.le.ScanSettings.Builder setMatchMode(int);
-    method public android.bluetooth.le.ScanSettings.Builder setNumOfMatches(int);
-    method public android.bluetooth.le.ScanSettings.Builder setPhy(int);
-    method public android.bluetooth.le.ScanSettings.Builder setReportDelay(long);
-    method public android.bluetooth.le.ScanSettings.Builder setScanMode(int);
-  }
-
-  public final class TransportBlock implements android.os.Parcelable {
-    ctor public TransportBlock(int, int, int, @Nullable byte[]);
-    method public int describeContents();
-    method public int getOrgId();
-    method public int getTdsFlags();
-    method @Nullable public byte[] getTransportData();
-    method public int getTransportDataLength();
-    method @Nullable public byte[] toByteArray();
-    method public int totalBytes();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.TransportBlock> CREATOR;
-  }
-
-  public final class TransportDiscoveryData implements android.os.Parcelable {
-    ctor public TransportDiscoveryData(int, @NonNull java.util.List<android.bluetooth.le.TransportBlock>);
-    ctor public TransportDiscoveryData(@NonNull byte[]);
-    method public int describeContents();
-    method @NonNull public java.util.List<android.bluetooth.le.TransportBlock> getTransportBlocks();
-    method public int getTransportDataType();
-    method @Nullable public byte[] toByteArray();
-    method public int totalBytes();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.TransportDiscoveryData> CREATOR;
-  }
-
-}
-
 package android.companion {
 
   public final class AssociationInfo implements android.os.Parcelable {
@@ -13575,6 +12216,7 @@
   }
 
   public final class ShortcutInfo implements android.os.Parcelable {
+    method @NonNull public static android.content.pm.ShortcutInfo createFromGenericDocument(@NonNull android.content.Context, @NonNull android.app.appsearch.GenericDocument);
     method public int describeContents();
     method @Nullable public android.content.ComponentName getActivity();
     method @NonNull public java.util.List<java.lang.String> getCapabilityParameterValues(@NonNull String, @NonNull String);
@@ -19930,7 +18572,6 @@
   public abstract class AbstractInputMethodService extends android.app.Service implements android.view.KeyEvent.Callback {
     ctor public AbstractInputMethodService();
     method public android.view.KeyEvent.DispatcherState getKeyDispatcherState();
-    method public final boolean isUiContext();
     method public final android.os.IBinder onBind(android.content.Intent);
     method public abstract android.inputmethodservice.AbstractInputMethodService.AbstractInputMethodImpl onCreateInputMethodInterface();
     method public abstract android.inputmethodservice.AbstractInputMethodService.AbstractInputMethodSessionImpl onCreateInputMethodSessionInterface();
@@ -22615,12 +21256,14 @@
     field @Deprecated public static final int COLOR_FormatYUV422SemiPlanar = 24; // 0x18
     field public static final int COLOR_FormatYUV444Flexible = 2135181448; // 0x7f444888
     field @Deprecated public static final int COLOR_FormatYUV444Interleaved = 29; // 0x1d
+    field public static final int COLOR_FormatYUVP010 = 54; // 0x36
     field @Deprecated public static final int COLOR_QCOM_FormatYUV420SemiPlanar = 2141391872; // 0x7fa30c00
     field @Deprecated public static final int COLOR_TI_FormatYUV420PackedSemiPlanar = 2130706688; // 0x7f000100
     field public static final String FEATURE_AdaptivePlayback = "adaptive-playback";
     field public static final String FEATURE_DynamicTimestamp = "dynamic-timestamp";
     field public static final String FEATURE_EncodingStatistics = "encoding-statistics";
     field public static final String FEATURE_FrameParsing = "frame-parsing";
+    field public static final String FEATURE_HdrEditing = "hdr-editing";
     field public static final String FEATURE_IntraRefresh = "intra-refresh";
     field public static final String FEATURE_LowLatency = "low-latency";
     field public static final String FEATURE_MultipleFrames = "multiple-frames";
@@ -24574,6 +23217,7 @@
     method public static android.net.Uri getValidRingtoneUri(android.content.Context);
     method public boolean hasHapticChannels(int);
     method public static boolean hasHapticChannels(@NonNull android.net.Uri);
+    method public static boolean hasHapticChannels(@NonNull android.content.Context, @NonNull android.net.Uri);
     method public int inferStreamType();
     method public static boolean isDefault(android.net.Uri);
     method @Nullable public static android.content.res.AssetFileDescriptor openDefaultRingtoneUri(@NonNull android.content.Context, @NonNull android.net.Uri) throws java.io.FileNotFoundException;
@@ -26249,6 +24893,37 @@
 
 package android.media.tv {
 
+  public final class AdRequest implements android.os.Parcelable {
+    ctor public AdRequest(int, int, @Nullable android.os.ParcelFileDescriptor, long, long, long, @Nullable String, @NonNull android.os.Bundle);
+    method public int describeContents();
+    method public long getEchoIntervalMillis();
+    method @Nullable public android.os.ParcelFileDescriptor getFileDescriptor();
+    method public int getId();
+    method @Nullable public String getMediaFileType();
+    method @NonNull public android.os.Bundle getMetadata();
+    method public int getRequestType();
+    method public long getStartTimeMillis();
+    method public long getStopTimeMillis();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.AdRequest> CREATOR;
+    field public static final int REQUEST_TYPE_START = 1; // 0x1
+    field public static final int REQUEST_TYPE_STOP = 2; // 0x2
+  }
+
+  public final class AdResponse implements android.os.Parcelable {
+    ctor public AdResponse(int, int, long);
+    method public int describeContents();
+    method public long getElapsedTimeMillis();
+    method public int getId();
+    method public int getResponseType();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.AdResponse> CREATOR;
+    field public static final int RESPONSE_TYPE_ERROR = 4; // 0x4
+    field public static final int RESPONSE_TYPE_FINISHED = 2; // 0x2
+    field public static final int RESPONSE_TYPE_PLAYING = 1; // 0x1
+    field public static final int RESPONSE_TYPE_STOPPED = 3; // 0x3
+  }
+
   public final class AitInfo implements android.os.Parcelable {
     ctor public AitInfo(int, int);
     method public int describeContents();
@@ -26751,6 +25426,9 @@
     field public static final int RECORDING_ERROR_INSUFFICIENT_SPACE = 1; // 0x1
     field public static final int RECORDING_ERROR_RESOURCE_BUSY = 2; // 0x2
     field public static final int RECORDING_ERROR_UNKNOWN = 0; // 0x0
+    field public static final int SIGNAL_STRENGTH_LOST = 1; // 0x1
+    field public static final int SIGNAL_STRENGTH_STRONG = 3; // 0x3
+    field public static final int SIGNAL_STRENGTH_WEAK = 2; // 0x2
     field public static final long TIME_SHIFT_INVALID_TIME = -9223372036854775808L; // 0x8000000000000000L
     field public static final int TIME_SHIFT_STATUS_AVAILABLE = 3; // 0x3
     field public static final int TIME_SHIFT_STATUS_UNAVAILABLE = 2; // 0x2
@@ -26828,10 +25506,12 @@
   public abstract static class TvInputService.Session implements android.view.KeyEvent.Callback {
     ctor public TvInputService.Session(android.content.Context);
     method public void layoutSurface(int, int, int, int);
+    method public void notifyAdResponse(@NonNull android.media.tv.AdResponse);
     method public void notifyAitInfoUpdated(@NonNull android.media.tv.AitInfo);
     method public void notifyChannelRetuned(android.net.Uri);
     method public void notifyContentAllowed();
     method public void notifyContentBlocked(@NonNull android.media.tv.TvContentRating);
+    method public void notifySignalStrength(int);
     method public void notifyTimeShiftStatusChanged(int);
     method public void notifyTrackSelected(int, String);
     method public void notifyTracksChanged(java.util.List<android.media.tv.TvTrackInfo>);
@@ -26847,6 +25527,7 @@
     method public boolean onKeyUp(int, android.view.KeyEvent);
     method public void onOverlayViewSizeChanged(int, int);
     method public abstract void onRelease();
+    method public void onRequestAd(@NonNull android.media.tv.AdRequest);
     method public boolean onSelectTrack(int, @Nullable String);
     method public abstract void onSetCaptionEnabled(boolean);
     method public void onSetInteractiveAppNotificationEnabled(boolean);
@@ -26984,9 +25665,11 @@
     method public void onContentAllowed(String);
     method public void onContentBlocked(String, android.media.tv.TvContentRating);
     method public void onDisconnected(String);
+    method public void onSignalStrength(@NonNull String, int);
     method public void onTimeShiftStatusChanged(String, int);
     method public void onTrackSelected(String, int, String);
     method public void onTracksChanged(String, java.util.List<android.media.tv.TvTrackInfo>);
+    method public void onTuned(@NonNull String, @NonNull android.net.Uri);
     method public void onVideoAvailable(String);
     method public void onVideoSizeChanged(String, int, int);
     method public void onVideoUnavailable(String, int);
@@ -27011,8 +25694,11 @@
 
   public final class TvInteractiveAppManager {
     method @NonNull public java.util.List<android.media.tv.interactive.TvInteractiveAppInfo> getTvInteractiveAppServiceList();
+    method public void prepare(@NonNull String, int);
     method public void registerCallback(@NonNull android.media.tv.interactive.TvInteractiveAppManager.TvInteractiveAppCallback, @NonNull java.util.concurrent.Executor);
+    method public void sendAppLinkCommand(@NonNull String, @NonNull android.os.Bundle);
     method public void unregisterCallback(@NonNull android.media.tv.interactive.TvInteractiveAppManager.TvInteractiveAppCallback);
+    field public static final String ACTION_APP_LINK_COMMAND = "android.media.tv.interactive.action.APP_LINK_COMMAND";
     field public static final int ERROR_BLOCKED = 5; // 0x5
     field public static final int ERROR_ENCRYPTED = 6; // 0x6
     field public static final int ERROR_NONE = 0; // 0x0
@@ -27021,26 +25707,55 @@
     field public static final int ERROR_UNKNOWN = 1; // 0x1
     field public static final int ERROR_UNKNOWN_CHANNEL = 7; // 0x7
     field public static final int ERROR_WEAK_SIGNAL = 3; // 0x3
+    field public static final String INTENT_KEY_BI_INTERACTIVE_APP_TYPE = "bi_interactive_app_type";
+    field public static final String INTENT_KEY_BI_INTERACTIVE_APP_URI = "bi_interactive_app_uri";
+    field public static final String INTENT_KEY_CHANNEL_URI = "channel_uri";
+    field public static final String INTENT_KEY_INTERACTIVE_APP_SERVICE_ID = "interactive_app_id";
+    field public static final String INTENT_KEY_TV_INPUT_ID = "tv_input_id";
     field public static final int INTERACTIVE_APP_STATE_ERROR = 3; // 0x3
     field public static final int INTERACTIVE_APP_STATE_RUNNING = 2; // 0x2
     field public static final int INTERACTIVE_APP_STATE_STOPPED = 1; // 0x1
+    field public static final String KEY_BACK_URI = "back_uri";
+    field public static final String KEY_CLASS_NAME = "class_name";
+    field public static final String KEY_COMMAND_TYPE = "command_type";
+    field public static final String KEY_PACKAGE_NAME = "package_name";
+    field public static final String KEY_SERVICE_ID = "service_id";
     field public static final int SERVICE_STATE_ERROR = 4; // 0x4
     field public static final int SERVICE_STATE_PREPARING = 2; // 0x2
     field public static final int SERVICE_STATE_READY = 3; // 0x3
     field public static final int SERVICE_STATE_UNREALIZED = 1; // 0x1
+    field public static final int TELETEXT_APP_STATE_ERROR = 3; // 0x3
+    field public static final int TELETEXT_APP_STATE_HIDE = 2; // 0x2
+    field public static final int TELETEXT_APP_STATE_SHOW = 1; // 0x1
   }
 
   public abstract static class TvInteractiveAppManager.TvInteractiveAppCallback {
     ctor public TvInteractiveAppManager.TvInteractiveAppCallback();
+    method public void onInteractiveAppServiceAdded(@NonNull String);
+    method public void onInteractiveAppServiceRemoved(@NonNull String);
+    method public void onInteractiveAppServiceUpdated(@NonNull String);
     method public void onTvInteractiveAppServiceStateChanged(@NonNull String, int, int, int);
   }
 
   public abstract class TvInteractiveAppService extends android.app.Service {
     ctor public TvInteractiveAppService();
     method public final void notifyStateChanged(int, int, int);
-    method public final android.os.IBinder onBind(android.content.Intent);
+    method public void onAppLinkCommand(@NonNull android.os.Bundle);
+    method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
     method @Nullable public abstract android.media.tv.interactive.TvInteractiveAppService.Session onCreateSession(@NonNull String, int);
     method public abstract void onPrepare(int);
+    field public static final String COMMAND_PARAMETER_KEY_CHANGE_CHANNEL_QUIETLY = "command_change_channel_quietly";
+    field public static final String COMMAND_PARAMETER_KEY_CHANNEL_URI = "command_channel_uri";
+    field public static final String COMMAND_PARAMETER_KEY_INPUT_ID = "command_input_id";
+    field public static final String COMMAND_PARAMETER_KEY_TRACK_ID = "command_track_id";
+    field public static final String COMMAND_PARAMETER_KEY_TRACK_TYPE = "command_track_type";
+    field public static final String COMMAND_PARAMETER_KEY_VOLUME = "command_volume";
+    field public static final String PLAYBACK_COMMAND_TYPE_SELECT_TRACK = "select_track";
+    field public static final String PLAYBACK_COMMAND_TYPE_SET_STREAM_VOLUME = "set_stream_volume";
+    field public static final String PLAYBACK_COMMAND_TYPE_STOP = "stop";
+    field public static final String PLAYBACK_COMMAND_TYPE_TUNE = "tune";
+    field public static final String PLAYBACK_COMMAND_TYPE_TUNE_NEXT = "tune_next";
+    field public static final String PLAYBACK_COMMAND_TYPE_TUNE_PREV = "tune_previous";
     field public static final String SERVICE_INTERFACE = "android.media.tv.interactive.TvInteractiveAppService";
     field public static final String SERVICE_META_DATA = "android.media.tv.interactive.app";
   }
@@ -27050,17 +25765,48 @@
     method public void layoutSurface(int, int, int, int);
     method public final void notifyBiInteractiveAppCreated(@NonNull android.net.Uri, @Nullable String);
     method public void notifySessionStateChanged(int, int);
+    method public final void notifyTeletextAppStateChanged(int);
+    method public void onAdResponse(@NonNull android.media.tv.AdResponse);
+    method public void onContentAllowed();
+    method public void onContentBlocked(@NonNull android.media.tv.TvContentRating);
     method public void onCreateBiInteractiveApp(@NonNull android.net.Uri, @Nullable android.os.Bundle);
+    method @Nullable public android.view.View onCreateMediaView();
+    method public void onCurrentChannelLcn(int);
+    method public void onCurrentChannelUri(@Nullable android.net.Uri);
+    method public void onCurrentTvInputId(@Nullable String);
     method public void onDestroyBiInteractiveApp(@NonNull String);
+    method public boolean onGenericMotionEvent(@NonNull android.view.MotionEvent);
     method public boolean onKeyDown(int, @NonNull android.view.KeyEvent);
     method public boolean onKeyLongPress(int, @NonNull android.view.KeyEvent);
     method public boolean onKeyMultiple(int, int, @NonNull android.view.KeyEvent);
     method public boolean onKeyUp(int, @NonNull android.view.KeyEvent);
+    method public void onMediaViewSizeChanged(int, int);
+    method public abstract void onRelease();
+    method public void onResetInteractiveApp();
     method public abstract boolean onSetSurface(@Nullable android.view.Surface);
+    method public void onSetTeletextAppEnabled(boolean);
+    method public void onSignalStrength(int);
     method public void onStartInteractiveApp();
     method public void onStopInteractiveApp();
+    method public void onStreamVolume(float);
     method public void onSurfaceChanged(int, int, int);
+    method public boolean onTouchEvent(@NonNull android.view.MotionEvent);
+    method public void onTrackInfoList(@NonNull java.util.List<android.media.tv.TvTrackInfo>);
+    method public void onTrackSelected(int, @NonNull String);
+    method public boolean onTrackballEvent(@NonNull android.view.MotionEvent);
+    method public void onTracksChanged(@NonNull java.util.List<android.media.tv.TvTrackInfo>);
     method public void onTuned(@NonNull android.net.Uri);
+    method public void onVideoAvailable();
+    method public void onVideoUnavailable(int);
+    method public void requestAd(@NonNull android.media.tv.AdRequest);
+    method public void requestCurrentChannelLcn();
+    method public void requestCurrentChannelUri();
+    method public void requestCurrentTvInputId();
+    method public void requestStreamVolume();
+    method public void requestTrackInfoList();
+    method public void sendPlaybackCommandRequest(@NonNull String, @Nullable android.os.Bundle);
+    method public void setMediaViewEnabled(boolean);
+    method public void setVideoBounds(@NonNull android.graphics.Rect);
   }
 
   public class TvInteractiveAppView extends android.view.ViewGroup {
@@ -27068,19 +25814,48 @@
     ctor public TvInteractiveAppView(@NonNull android.content.Context, @Nullable android.util.AttributeSet);
     ctor public TvInteractiveAppView(@NonNull android.content.Context, @Nullable android.util.AttributeSet, int);
     method public void clearCallback();
+    method public void clearOnUnhandledInputEventListener();
     method public void createBiInteractiveApp(@NonNull android.net.Uri, @Nullable android.os.Bundle);
     method public void destroyBiInteractiveApp(@NonNull String);
+    method public boolean dispatchUnhandledInputEvent(@NonNull android.view.InputEvent);
+    method public void onAttachedToWindow();
+    method public void onDetachedFromWindow();
+    method public void onLayout(boolean, int, int, int, int);
+    method public void onMeasure(int, int);
+    method public boolean onUnhandledInputEvent(@NonNull android.view.InputEvent);
+    method public void onVisibilityChanged(@NonNull android.view.View, int);
     method public void prepareInteractiveApp(@NonNull String, int);
+    method public void reset();
+    method public void resetInteractiveApp();
+    method public void sendCurrentChannelLcn(int);
+    method public void sendCurrentChannelUri(@Nullable android.net.Uri);
+    method public void sendCurrentTvInputId(@Nullable String);
+    method public void sendStreamVolume(float);
+    method public void sendTrackInfoList(@Nullable java.util.List<android.media.tv.TvTrackInfo>);
     method public void setCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.interactive.TvInteractiveAppView.TvInteractiveAppCallback);
+    method public void setOnUnhandledInputEventListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.interactive.TvInteractiveAppView.OnUnhandledInputEventListener);
+    method public void setTeletextAppEnabled(boolean);
     method public int setTvView(@Nullable android.media.tv.TvView);
     method public void startInteractiveApp();
     method public void stopInteractiveApp();
   }
 
+  public static interface TvInteractiveAppView.OnUnhandledInputEventListener {
+    method public boolean onUnhandledInputEvent(@NonNull android.view.InputEvent);
+  }
+
   public abstract static class TvInteractiveAppView.TvInteractiveAppCallback {
     ctor public TvInteractiveAppView.TvInteractiveAppCallback();
     method public void onBiInteractiveAppCreated(@NonNull String, @NonNull android.net.Uri, @Nullable String);
+    method public void onPlaybackCommandRequest(@NonNull String, @NonNull String, @NonNull android.os.Bundle);
+    method public void onRequestCurrentChannelLcn(@NonNull String);
+    method public void onRequestCurrentChannelUri(@NonNull String);
+    method public void onRequestCurrentTvInputId(@NonNull String);
+    method public void onRequestStreamVolume(@NonNull String);
+    method public void onRequestTrackInfoList(@NonNull String);
+    method public void onSetVideoBounds(@NonNull String, @NonNull android.graphics.Rect);
     method public void onStateChanged(@NonNull String, int, int);
+    method public void onTeletextAppStateChanged(@NonNull String, int);
   }
 
 }
@@ -31645,6 +30420,7 @@
     field public static final int BATTERY_HEALTH_UNKNOWN = 1; // 0x1
     field public static final int BATTERY_HEALTH_UNSPECIFIED_FAILURE = 6; // 0x6
     field public static final int BATTERY_PLUGGED_AC = 1; // 0x1
+    field public static final int BATTERY_PLUGGED_DOCK = 8; // 0x8
     field public static final int BATTERY_PLUGGED_USB = 2; // 0x2
     field public static final int BATTERY_PLUGGED_WIRELESS = 4; // 0x4
     field public static final int BATTERY_PROPERTY_CAPACITY = 4; // 0x4
@@ -33152,6 +31928,9 @@
     method public static android.os.VibrationEffect createWaveform(long[], int[], int);
     method public int describeContents();
     method @NonNull public static android.os.VibrationEffect.Composition startComposition();
+    method @NonNull public static android.os.VibrationEffect.WaveformBuilder startWaveform();
+    method @NonNull public static android.os.VibrationEffect.WaveformBuilder startWaveform(@NonNull android.os.VibrationEffect.VibrationParameter);
+    method @NonNull public static android.os.VibrationEffect.WaveformBuilder startWaveform(@NonNull android.os.VibrationEffect.VibrationParameter, @NonNull android.os.VibrationEffect.VibrationParameter);
     field @NonNull public static final android.os.Parcelable.Creator<android.os.VibrationEffect> CREATOR;
     field public static final int DEFAULT_AMPLITUDE = -1; // 0xffffffff
     field public static final int EFFECT_CLICK = 0; // 0x0
@@ -33161,10 +31940,13 @@
   }
 
   public static final class VibrationEffect.Composition {
+    method @NonNull public android.os.VibrationEffect.Composition addEffect(@NonNull android.os.VibrationEffect);
+    method @NonNull public android.os.VibrationEffect.Composition addOffDuration(@NonNull java.time.Duration);
     method @NonNull public android.os.VibrationEffect.Composition addPrimitive(int);
     method @NonNull public android.os.VibrationEffect.Composition addPrimitive(int, @FloatRange(from=0.0f, to=1.0f) float);
     method @NonNull public android.os.VibrationEffect.Composition addPrimitive(int, @FloatRange(from=0.0f, to=1.0f) float, @IntRange(from=0) int);
     method @NonNull public android.os.VibrationEffect compose();
+    method @NonNull public android.os.VibrationEffect.Composition repeatEffectIndefinitely(@NonNull android.os.VibrationEffect);
     field public static final int PRIMITIVE_CLICK = 1; // 0x1
     field public static final int PRIMITIVE_LOW_TICK = 8; // 0x8
     field public static final int PRIMITIVE_QUICK_FALL = 6; // 0x6
@@ -33175,6 +31957,21 @@
     field public static final int PRIMITIVE_TICK = 7; // 0x7
   }
 
+  public static final class VibrationEffect.Composition.UnreachableAfterRepeatingIndefinitelyException extends java.lang.IllegalStateException {
+  }
+
+  public static class VibrationEffect.VibrationParameter {
+    method @NonNull public static android.os.VibrationEffect.VibrationParameter targetAmplitude(@FloatRange(from=0, to=1) float);
+    method @NonNull public static android.os.VibrationEffect.VibrationParameter targetFrequency(@FloatRange(from=1) float);
+  }
+
+  public static final class VibrationEffect.WaveformBuilder {
+    method @NonNull public android.os.VibrationEffect.WaveformBuilder addSustain(@NonNull java.time.Duration);
+    method @NonNull public android.os.VibrationEffect.WaveformBuilder addTransition(@NonNull java.time.Duration, @NonNull android.os.VibrationEffect.VibrationParameter);
+    method @NonNull public android.os.VibrationEffect.WaveformBuilder addTransition(@NonNull java.time.Duration, @NonNull android.os.VibrationEffect.VibrationParameter, @NonNull android.os.VibrationEffect.VibrationParameter);
+    method @NonNull public android.os.VibrationEffect build();
+  }
+
   public abstract class Vibrator {
     method public final int areAllEffectsSupported(@NonNull int...);
     method public final boolean areAllPrimitivesSupported(@NonNull int...);
@@ -41404,8 +40201,10 @@
     field public static final int CAPABILITY_SELF_MANAGED = 2048; // 0x800
     field public static final int CAPABILITY_SIM_SUBSCRIPTION = 4; // 0x4
     field public static final int CAPABILITY_SUPPORTS_VIDEO_CALLING = 1024; // 0x400
+    field public static final int CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS = 65536; // 0x10000
     field public static final int CAPABILITY_VIDEO_CALLING = 8; // 0x8
     field public static final int CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE = 256; // 0x100
+    field public static final int CAPABILITY_VOICE_CALLING_AVAILABLE = 131072; // 0x20000
     field @NonNull public static final android.os.Parcelable.Creator<android.telecom.PhoneAccount> CREATOR;
     field public static final String EXTRA_ADD_SELF_MANAGED_CALLS_TO_INCALLSERVICE = "android.telecom.extra.ADD_SELF_MANAGED_CALLS_TO_INCALLSERVICE";
     field public static final String EXTRA_ALWAYS_USE_VOIP_AUDIO_MODE = "android.telecom.extra.ALWAYS_USE_VOIP_AUDIO_MODE";
@@ -42345,6 +41144,7 @@
     field public static final String KEY_SIP_TIMER_T1_MILLIS_INT = "ims.sip_timer_t1_millis_int";
     field public static final String KEY_SIP_TIMER_T2_MILLIS_INT = "ims.sip_timer_t2_millis_int";
     field public static final String KEY_SIP_TIMER_T4_MILLIS_INT = "ims.sip_timer_t4_millis_int";
+    field public static final String KEY_SUPPORTED_RATS_INT_ARRAY = "ims.supported_rats_int_array";
     field public static final String KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT = "ims.wifi_off_deferring_time_millis_int";
     field public static final int NETWORK_TYPE_HOME = 0; // 0x0
     field public static final int NETWORK_TYPE_ROAMING = 1; // 0x1
@@ -42365,6 +41165,7 @@
     field public static final String KEY_EMERGENCY_QOS_PRECONDITION_SUPPORTED_BOOL = "imsemergency.emergency_qos_precondition_supported_bool";
     field public static final String KEY_EMERGENCY_REGISTRATION_TIMER_MILLIS_INT = "imsemergency.emergency_registration_timer_millis_int";
     field public static final String KEY_PREFIX = "imsemergency.";
+    field public static final String KEY_REFRESH_GEOLOCATION_TIMEOUT_MILLIS_INT = "imsemergency.refresh_geolocation_timeout_millis_int";
     field public static final String KEY_RETRY_EMERGENCY_ON_IMS_PDN_BOOL = "imsemergency.retry_emergency_on_ims_pdn_bool";
   }
 
@@ -42374,7 +41175,6 @@
     field public static final String KEY_T140_PAYLOAD_TYPE_INT = "imsrtt.t140_payload_type_int";
     field public static final String KEY_TEXT_AS_BANDWIDTH_KBPS_INT = "imsrtt.text_as_bandwidth_kbps_int";
     field public static final String KEY_TEXT_CODEC_CAPABILITY_PAYLOAD_TYPES_BUNDLE = "imsrtt.text_codec_capability_payload_types_bundle";
-    field public static final String KEY_TEXT_INACTIVITY_CALL_END_REASONS_INT_ARRAY = "imsrtt.text_inactivity_call_end_reasons_int_array";
     field public static final String KEY_TEXT_ON_DEFAULT_BEARER_SUPPORTED_BOOL = "imsrtt.text_on_default_bearer_supported_bool";
     field public static final String KEY_TEXT_QOS_PRECONDITION_SUPPORTED_BOOL = "imsrtt.text_qos_precondition_supported_bool";
     field public static final String KEY_TEXT_RR_BANDWIDTH_BPS_INT = "imsrtt.text_rr_bandwidth_bps_int";
@@ -42410,6 +41210,7 @@
     field public static final String KEY_UT_REQUIRES_IMS_REGISTRATION_BOOL = "imsss.ut_requires_ims_registration_bool";
     field public static final String KEY_UT_SERVER_BASED_SERVICES_INT_ARRAY = "imsss.ut_server_based_services_int_array";
     field public static final String KEY_UT_SUPPORTED_WHEN_PS_DATA_OFF_BOOL = "imsss.ut_supported_when_ps_data_off_bool";
+    field public static final String KEY_UT_SUPPORTED_WHEN_ROAMING_BOOL = "imsss.ut_supported_when_roaming_bool";
     field public static final String KEY_UT_TERMINAL_BASED_SERVICES_INT_ARRAY = "imsss.ut_terminal_based_services_int_array";
     field public static final String KEY_UT_TRANSPORT_TYPE_INT = "imsss.ut_transport_type_int";
     field public static final String KEY_XCAP_OVER_UT_SUPPORTED_RATS_INT_ARRAY = "imsss.xcap_over_ut_supported_rats_int_array";
@@ -42509,6 +41310,7 @@
     field public static final String KEY_RINGBACK_TIMER_MILLIS_INT = "imsvoice.ringback_timer_millis_int";
     field public static final String KEY_RINGING_TIMER_MILLIS_INT = "imsvoice.ringing_timer_millis_int";
     field public static final String KEY_SESSION_EXPIRES_TIMER_SEC_INT = "imsvoice.session_expires_timer_sec_int";
+    field public static final String KEY_SESSION_PRIVACY_TYPE_INT = "imsvoice.session_privacy_type_int";
     field public static final String KEY_SESSION_REFRESHER_TYPE_INT = "imsvoice.session_refresher_type_int";
     field public static final String KEY_SESSION_REFRESH_METHOD_INT = "imsvoice.session_refresh_method_int";
     field public static final String KEY_SESSION_TIMER_SUPPORTED_BOOL = "imsvoice.session_timer_supported_bool";
@@ -42518,6 +41320,9 @@
     field public static final int MIDCALL_SRVCC_SUPPORT = 3; // 0x3
     field public static final int OCTET_ALIGNED = 1; // 0x1
     field public static final int PREALERTING_SRVCC_SUPPORT = 2; // 0x2
+    field public static final int SESSION_PRIVACY_TYPE_HEADER = 0; // 0x0
+    field public static final int SESSION_PRIVACY_TYPE_ID = 2; // 0x2
+    field public static final int SESSION_PRIVACY_TYPE_NONE = 1; // 0x1
     field public static final int SESSION_REFRESHER_TYPE_UAC = 1; // 0x1
     field public static final int SESSION_REFRESHER_TYPE_UAS = 2; // 0x2
     field public static final int SESSION_REFRESHER_TYPE_UNKNOWN = 0; // 0x0
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index ee31e13..6c2db43 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -63,8 +63,8 @@
 
   public class DevicePolicyManager {
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void acknowledgeNewUserDisclaimer();
-    method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void clearLogoutUser();
-    method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.os.UserHandle getLogoutUser();
+    method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}) public android.os.UserHandle getLogoutUser();
+    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public int logoutUser();
     field public static final String ACTION_SHOW_NEW_USER_DISCLAIMER = "android.app.action.SHOW_NEW_USER_DISCLAIMER";
   }
 
@@ -93,20 +93,6 @@
 
 }
 
-package android.bluetooth {
-
-  public class BluetoothFrameworkInitializer {
-    method public static void registerServiceWrappers();
-    method public static void setBinderCallsStatsInitializer(@NonNull java.util.function.Consumer<android.content.Context>);
-    method public static void setBluetoothServiceManager(@NonNull android.os.BluetoothServiceManager);
-  }
-
-  public final class BluetoothPan implements android.bluetooth.BluetoothProfile {
-    method @Nullable @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.TETHER_PRIVILEGED}) public android.net.TetheringManager.TetheredInterfaceRequest requestTetheredInterface(@NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.TetheredInterfaceCallback);
-  }
-
-}
-
 package android.content {
 
   public abstract class ContentProvider implements android.content.ComponentCallbacks2 {
@@ -384,6 +370,7 @@
     method public int getRoaming();
     method @NonNull public java.util.Set<java.lang.String> getSubscriberIds();
     method @NonNull public java.util.Set<java.lang.String> getWifiNetworkKeys();
+    method public boolean matches(@NonNull android.net.NetworkIdentity);
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkTemplate> CREATOR;
     field public static final int MATCH_BLUETOOTH = 8; // 0x8
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 5e23229..55a6df2 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -744,6 +744,7 @@
     method public void clearRequireCompatChange();
     method public boolean isPendingIntentBackgroundActivityLaunchAllowed();
     method public static android.app.BroadcastOptions makeBasic();
+    method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void recordResponseEventWhileInBackground(@IntRange(from=0) long);
     method @RequiresPermission(android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND) public void setBackgroundActivityStartsAllowed(boolean);
     method public void setDontSendToRestrictedApps(boolean);
     method public void setPendingIntentBackgroundActivityLaunchAllowed(boolean);
@@ -2257,475 +2258,6 @@
 
 }
 
-package android.bluetooth {
-
-  public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile {
-    method @Nullable @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public android.bluetooth.BufferConstraints getBufferConstraints();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getDynamicBufferSupport();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setBufferLengthMillis(int, int);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
-    field public static final int DYNAMIC_BUFFER_SUPPORT_A2DP_OFFLOAD = 1; // 0x1
-    field public static final int DYNAMIC_BUFFER_SUPPORT_A2DP_SOFTWARE_ENCODING = 2; // 0x2
-    field public static final int DYNAMIC_BUFFER_SUPPORT_NONE = 0; // 0x0
-    field public static final int OPTIONAL_CODECS_NOT_SUPPORTED = 0; // 0x0
-    field public static final int OPTIONAL_CODECS_PREF_DISABLED = 0; // 0x0
-    field public static final int OPTIONAL_CODECS_PREF_ENABLED = 1; // 0x1
-    field public static final int OPTIONAL_CODECS_PREF_UNKNOWN = -1; // 0xffffffff
-    field public static final int OPTIONAL_CODECS_SUPPORTED = 1; // 0x1
-    field public static final int OPTIONAL_CODECS_SUPPORT_UNKNOWN = -1; // 0xffffffff
-  }
-
-  public final class BluetoothA2dpSink implements android.bluetooth.BluetoothProfile {
-    method public void finalize();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean isAudioPlaying(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED";
-  }
-
-  public final class BluetoothActivityEnergyInfo implements android.os.Parcelable {
-    method public int getBluetoothStackState();
-    method public long getControllerEnergyUsed();
-    method public long getControllerIdleTimeMillis();
-    method public long getControllerRxTimeMillis();
-    method public long getControllerTxTimeMillis();
-    method public long getTimestampMillis();
-    method @NonNull public java.util.List<android.bluetooth.UidTraffic> getUidTraffic();
-    method public boolean isValid();
-    field public static final int BT_STACK_STATE_INVALID = 0; // 0x0
-    field public static final int BT_STACK_STATE_STATE_ACTIVE = 1; // 0x1
-    field public static final int BT_STACK_STATE_STATE_IDLE = 3; // 0x3
-    field public static final int BT_STACK_STATE_STATE_SCANNING = 2; // 0x2
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothActivityEnergyInfo> CREATOR;
-  }
-
-  public final class BluetoothAdapter {
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean addOnMetadataChangedListener(@NonNull android.bluetooth.BluetoothDevice, @NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OnMetadataChangedListener);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean disable(boolean);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disableBLE();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean enableBLE();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean enableNoAutoConnect();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void generateLocalOobData(int, @NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OobDataCallback);
-    method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getActiveDevices(int);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public long getDiscoveryEndMillis();
-    method public boolean isBleScanAlwaysAvailable();
-    method public boolean isLeEnabled();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean removeActiveDevice(int);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean removeOnMetadataChangedListener(@NonNull android.bluetooth.BluetoothDevice, @NonNull android.bluetooth.BluetoothAdapter.OnMetadataChangedListener);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean setActiveDevice(@NonNull android.bluetooth.BluetoothDevice, int);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int setDiscoverableTimeout(@NonNull java.time.Duration);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int setScanMode(int);
-    field public static final String ACTION_BLE_STATE_CHANGED = "android.bluetooth.adapter.action.BLE_STATE_CHANGED";
-    field public static final String ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE = "android.bluetooth.adapter.action.REQUEST_BLE_SCAN_ALWAYS_AVAILABLE";
-    field public static final int ACTIVE_DEVICE_ALL = 2; // 0x2
-    field public static final int ACTIVE_DEVICE_AUDIO = 0; // 0x0
-    field public static final int ACTIVE_DEVICE_PHONE_CALL = 1; // 0x1
-  }
-
-  public static interface BluetoothAdapter.OnMetadataChangedListener {
-    method public void onMetadataChanged(@NonNull android.bluetooth.BluetoothDevice, int, @Nullable byte[]);
-  }
-
-  public static interface BluetoothAdapter.OobDataCallback {
-    method public void onError(int);
-    method public void onOobData(int, @NonNull android.bluetooth.OobData);
-  }
-
-  public final class BluetoothClass implements android.os.Parcelable {
-    field public static final int PROFILE_A2DP_SINK = 6; // 0x6
-    field public static final int PROFILE_NAP = 5; // 0x5
-    field public static final int PROFILE_OPP = 2; // 0x2
-    field public static final int PROFILE_PANU = 4; // 0x4
-  }
-
-  public final class BluetoothCsipSetCoordinator implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
-    method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public java.util.List<java.lang.Integer> getAllGroupIds(@Nullable android.os.ParcelUuid);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public int getConnectionPolicy(@Nullable android.bluetooth.BluetoothDevice);
-    method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public java.util.Map getGroupUuidMapByDevice(@Nullable android.bluetooth.BluetoothDevice);
-    method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public java.util.UUID groupLock(int, @Nullable java.util.concurrent.Executor, @Nullable android.bluetooth.BluetoothCsipSetCoordinator.ClientLockCallback);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean groupUnlock(@NonNull java.util.UUID);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setConnectionPolicy(@Nullable android.bluetooth.BluetoothDevice, int);
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public static final String ACTION_CSIS_DEVICE_AVAILABLE = "android.bluetooth.action.CSIS_DEVICE_AVAILABLE";
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public static final String ACTION_CSIS_SET_MEMBER_AVAILABLE = "android.bluetooth.action.CSIS_SET_MEMBER_AVAILABLE";
-  }
-
-  public static interface BluetoothCsipSetCoordinator.ClientLockCallback {
-    method public void onGroupLockSet(int, int, boolean);
-  }
-
-  public final class BluetoothDevice implements android.os.Parcelable {
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean canBondWithoutDialog();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean cancelBondProcess();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public int connect();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean createBond(int);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean createBondOutOfBand(int, @Nullable android.bluetooth.OobData, @Nullable android.bluetooth.OobData);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int disconnect();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean fetchUuidsWithSdp(int);
-    method @Nullable @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public byte[] getMetadata(int);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getSimAccessPermission();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isConnected();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isEncrypted();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean isInSilenceMode();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean removeBond();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setLowLatencyAudioAllowed(boolean);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setMessageAccessPermission(int);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setMetadata(int, @NonNull byte[]);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setPhonebookAccessPermission(int);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setSilenceMode(boolean);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setSimAccessPermission(int);
-    field public static final int ACCESS_ALLOWED = 1; // 0x1
-    field public static final int ACCESS_REJECTED = 2; // 0x2
-    field public static final int ACCESS_UNKNOWN = 0; // 0x0
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_SILENCE_MODE_CHANGED = "android.bluetooth.device.action.SILENCE_MODE_CHANGED";
-    field @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public static final String ACTION_SWITCH_BUFFER_SIZE = "android.bluetooth.device.action.SWITCH_BUFFER_SIZE";
-    field public static final String DEVICE_TYPE_DEFAULT = "Default";
-    field public static final String DEVICE_TYPE_UNTETHERED_HEADSET = "Untethered Headset";
-    field public static final String DEVICE_TYPE_WATCH = "Watch";
-    field public static final String EXTRA_LOW_LATENCY_BUFFER_SIZE = "android.bluetooth.device.extra.LOW_LATENCY_BUFFER_SIZE";
-    field public static final int METADATA_COMPANION_APP = 4; // 0x4
-    field public static final int METADATA_DEVICE_TYPE = 17; // 0x11
-    field public static final int METADATA_ENHANCED_SETTINGS_UI_URI = 16; // 0x10
-    field public static final int METADATA_HARDWARE_VERSION = 3; // 0x3
-    field public static final int METADATA_IS_UNTETHERED_HEADSET = 6; // 0x6
-    field public static final int METADATA_MAIN_BATTERY = 18; // 0x12
-    field public static final int METADATA_MAIN_CHARGING = 19; // 0x13
-    field public static final int METADATA_MAIN_ICON = 5; // 0x5
-    field public static final int METADATA_MAIN_LOW_BATTERY_THRESHOLD = 20; // 0x14
-    field public static final int METADATA_MANUFACTURER_NAME = 0; // 0x0
-    field public static final int METADATA_MAX_LENGTH = 2048; // 0x800
-    field public static final int METADATA_MODEL_NAME = 1; // 0x1
-    field public static final int METADATA_SOFTWARE_VERSION = 2; // 0x2
-    field public static final int METADATA_UNTETHERED_CASE_BATTERY = 12; // 0xc
-    field public static final int METADATA_UNTETHERED_CASE_CHARGING = 15; // 0xf
-    field public static final int METADATA_UNTETHERED_CASE_ICON = 9; // 0x9
-    field public static final int METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD = 23; // 0x17
-    field public static final int METADATA_UNTETHERED_LEFT_BATTERY = 10; // 0xa
-    field public static final int METADATA_UNTETHERED_LEFT_CHARGING = 13; // 0xd
-    field public static final int METADATA_UNTETHERED_LEFT_ICON = 7; // 0x7
-    field public static final int METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD = 21; // 0x15
-    field public static final int METADATA_UNTETHERED_RIGHT_BATTERY = 11; // 0xb
-    field public static final int METADATA_UNTETHERED_RIGHT_CHARGING = 14; // 0xe
-    field public static final int METADATA_UNTETHERED_RIGHT_ICON = 8; // 0x8
-    field public static final int METADATA_UNTETHERED_RIGHT_LOW_BATTERY_THRESHOLD = 22; // 0x16
-  }
-
-  public final class BluetoothHeadset implements android.bluetooth.BluetoothProfile {
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean connect(android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int connectAudio();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disconnect(android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int disconnectAudio();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getAudioState(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean isInbandRingingEnabled();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean startScoUsingVirtualVoiceCall();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean stopScoUsingVirtualVoiceCall();
-  }
-
-  public final class BluetoothHeadsetClient implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
-    method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice);
-    method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
-    field @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.headsetprofile.action.CONNECTION_STATE_CHANGED";
-  }
-
-  public final class BluetoothHearingAid implements android.bluetooth.BluetoothProfile {
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public long getHiSyncId(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
-  }
-
-  public final class BluetoothHidDevice implements android.bluetooth.BluetoothProfile {
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
-  }
-
-  public final class BluetoothHidHost implements android.bluetooth.BluetoothProfile {
-    method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED";
-  }
-
-  public final class BluetoothLeAudio implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getAudioLocation(@NonNull android.bluetooth.BluetoothDevice);
-  }
-
-  public final class BluetoothMap implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
-    method public void close();
-    method protected void finalize();
-    method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED";
-  }
-
-  public final class BluetoothMapClient implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
-    method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice);
-    method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.SEND_SMS}) public boolean sendMessage(@NonNull android.bluetooth.BluetoothDevice, @NonNull java.util.Collection<android.net.Uri>, @NonNull String, @Nullable android.app.PendingIntent, @Nullable android.app.PendingIntent);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
-    field @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.mapmce.profile.action.CONNECTION_STATE_CHANGED";
-  }
-
-  public final class BluetoothPan implements android.bluetooth.BluetoothProfile {
-    method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isTetheringOn();
-    method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.TETHER_PRIVILEGED}) public void setBluetoothTethering(boolean);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED";
-    field public static final String ACTION_TETHERING_STATE_CHANGED = "android.bluetooth.action.TETHERING_STATE_CHANGED";
-    field public static final String EXTRA_LOCAL_ROLE = "android.bluetooth.pan.extra.LOCAL_ROLE";
-    field public static final String EXTRA_TETHERING_STATE = "android.bluetooth.extra.TETHERING_STATE";
-    field public static final int LOCAL_NAP_ROLE = 1; // 0x1
-    field public static final int LOCAL_PANU_ROLE = 2; // 0x2
-    field public static final int PAN_ROLE_NONE = 0; // 0x0
-    field public static final int REMOTE_NAP_ROLE = 1; // 0x1
-    field public static final int REMOTE_PANU_ROLE = 2; // 0x2
-    field public static final int TETHERING_STATE_OFF = 1; // 0x1
-    field public static final int TETHERING_STATE_ON = 2; // 0x2
-  }
-
-  public class BluetoothPbap implements android.bluetooth.BluetoothProfile {
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED";
-  }
-
-  public final class BluetoothPbapClient implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
-    method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice);
-    method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
-    field @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.pbapclient.profile.action.CONNECTION_STATE_CHANGED";
-  }
-
-  public interface BluetoothProfile {
-    field public static final int A2DP_SINK = 11; // 0xb
-    field public static final int AVRCP_CONTROLLER = 12; // 0xc
-    field public static final int CONNECTION_POLICY_ALLOWED = 100; // 0x64
-    field public static final int CONNECTION_POLICY_FORBIDDEN = 0; // 0x0
-    field public static final int CONNECTION_POLICY_UNKNOWN = -1; // 0xffffffff
-    field public static final int HEADSET_CLIENT = 16; // 0x10
-    field public static final int MAP_CLIENT = 18; // 0x12
-    field public static final int PAN = 5; // 0x5
-    field public static final int PBAP_CLIENT = 17; // 0x11
-    field @Deprecated public static final int PRIORITY_OFF = 0; // 0x0
-    field @Deprecated public static final int PRIORITY_ON = 100; // 0x64
-    field public static final int VOLUME_CONTROL = 23; // 0x17
-  }
-
-  public final class BluetoothStatusCodes {
-    field public static final int ERROR_ANOTHER_ACTIVE_OOB_REQUEST = 1000; // 0x3e8
-    field public static final int ERROR_AUDIO_DEVICE_ALREADY_CONNECTED = 1116; // 0x45c
-    field public static final int ERROR_AUDIO_DEVICE_ALREADY_DISCONNECTED = 1117; // 0x45d
-    field public static final int ERROR_AUDIO_ROUTE_BLOCKED = 1118; // 0x45e
-    field public static final int ERROR_CALL_ACTIVE = 1119; // 0x45f
-    field public static final int ERROR_NOT_ACTIVE_DEVICE = 12; // 0xc
-    field public static final int ERROR_NO_ACTIVE_DEVICES = 13; // 0xd
-    field public static final int ERROR_PROFILE_NOT_CONNECTED = 14; // 0xe
-    field public static final int ERROR_TIMEOUT = 15; // 0xf
-  }
-
-  public final class BluetoothUuid {
-    method public static boolean containsAnyUuid(@Nullable android.os.ParcelUuid[], @Nullable android.os.ParcelUuid[]);
-    method @NonNull public static android.os.ParcelUuid parseUuidFrom(@Nullable byte[]);
-    field @NonNull public static final android.os.ParcelUuid A2DP_SINK;
-    field @NonNull public static final android.os.ParcelUuid A2DP_SOURCE;
-    field @NonNull public static final android.os.ParcelUuid ADV_AUDIO_DIST;
-    field @NonNull public static final android.os.ParcelUuid AVRCP_CONTROLLER;
-    field @NonNull public static final android.os.ParcelUuid AVRCP_TARGET;
-    field @NonNull public static final android.os.ParcelUuid BASE_UUID;
-    field @NonNull public static final android.os.ParcelUuid BNEP;
-    field @NonNull public static final android.os.ParcelUuid CAP;
-    field @NonNull public static final android.os.ParcelUuid COORDINATED_SET;
-    field @NonNull public static final android.os.ParcelUuid DIP;
-    field @NonNull public static final android.os.ParcelUuid GENERIC_MEDIA_CONTROL;
-    field @NonNull public static final android.os.ParcelUuid HAS;
-    field @NonNull public static final android.os.ParcelUuid HEARING_AID;
-    field @NonNull public static final android.os.ParcelUuid HFP;
-    field @NonNull public static final android.os.ParcelUuid HFP_AG;
-    field @NonNull public static final android.os.ParcelUuid HID;
-    field @NonNull public static final android.os.ParcelUuid HOGP;
-    field @NonNull public static final android.os.ParcelUuid HSP;
-    field @NonNull public static final android.os.ParcelUuid HSP_AG;
-    field @NonNull public static final android.os.ParcelUuid LE_AUDIO;
-    field @NonNull public static final android.os.ParcelUuid MAP;
-    field @NonNull public static final android.os.ParcelUuid MAS;
-    field @NonNull public static final android.os.ParcelUuid MEDIA_CONTROL;
-    field @NonNull public static final android.os.ParcelUuid MNS;
-    field @NonNull public static final android.os.ParcelUuid NAP;
-    field @NonNull public static final android.os.ParcelUuid OBEX_OBJECT_PUSH;
-    field @NonNull public static final android.os.ParcelUuid PANU;
-    field @NonNull public static final android.os.ParcelUuid PBAP_PCE;
-    field @NonNull public static final android.os.ParcelUuid PBAP_PSE;
-    field @NonNull public static final android.os.ParcelUuid SAP;
-    field public static final int UUID_BYTES_128_BIT = 16; // 0x10
-    field public static final int UUID_BYTES_16_BIT = 2; // 0x2
-    field public static final int UUID_BYTES_32_BIT = 4; // 0x4
-    field @NonNull public static final android.os.ParcelUuid VOLUME_CONTROL;
-  }
-
-  public final class BluetoothVolumeControl implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void close();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) protected void finalize();
-    method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void setVolume(@Nullable android.bluetooth.BluetoothDevice, @IntRange(from=0, to=255) int);
-    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.volume-control.profile.action.CONNECTION_STATE_CHANGED";
-  }
-
-  public final class BufferConstraint implements android.os.Parcelable {
-    ctor public BufferConstraint(int, int, int);
-    method public int describeContents();
-    method public int getDefaultMillis();
-    method public int getMaxMillis();
-    method public int getMinMillis();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BufferConstraint> CREATOR;
-  }
-
-  public final class BufferConstraints implements android.os.Parcelable {
-    ctor public BufferConstraints(@NonNull java.util.List<android.bluetooth.BufferConstraint>);
-    method public int describeContents();
-    method @Nullable public android.bluetooth.BufferConstraint forCodec(int);
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field public static final int BUFFER_CODEC_MAX_NUM = 32; // 0x20
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BufferConstraints> CREATOR;
-  }
-
-  public final class OobData implements android.os.Parcelable {
-    method @NonNull public byte[] getClassOfDevice();
-    method @NonNull public byte[] getClassicLength();
-    method @NonNull public byte[] getConfirmationHash();
-    method @NonNull public byte[] getDeviceAddressWithType();
-    method @Nullable public byte[] getDeviceName();
-    method @Nullable public byte[] getLeAppearance();
-    method @NonNull public int getLeDeviceRole();
-    method @NonNull public int getLeFlags();
-    method @Nullable public byte[] getLeTemporaryKey();
-    method @NonNull public byte[] getRandomizerHash();
-    field public static final int CLASS_OF_DEVICE_OCTETS = 3; // 0x3
-    field public static final int CONFIRMATION_OCTETS = 16; // 0x10
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.OobData> CREATOR;
-    field public static final int DEVICE_ADDRESS_OCTETS = 7; // 0x7
-    field public static final int LE_APPEARANCE_OCTETS = 2; // 0x2
-    field public static final int LE_DEVICE_FLAG_OCTETS = 1; // 0x1
-    field public static final int LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL = 3; // 0x3
-    field public static final int LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL = 2; // 0x2
-    field public static final int LE_DEVICE_ROLE_CENTRAL_ONLY = 1; // 0x1
-    field public static final int LE_DEVICE_ROLE_OCTETS = 1; // 0x1
-    field public static final int LE_DEVICE_ROLE_PERIPHERAL_ONLY = 0; // 0x0
-    field public static final int LE_FLAG_BREDR_NOT_SUPPORTED = 2; // 0x2
-    field public static final int LE_FLAG_GENERAL_DISCOVERY_MODE = 1; // 0x1
-    field public static final int LE_FLAG_LIMITED_DISCOVERY_MODE = 0; // 0x0
-    field public static final int LE_FLAG_SIMULTANEOUS_CONTROLLER = 3; // 0x3
-    field public static final int LE_FLAG_SIMULTANEOUS_HOST = 4; // 0x4
-    field public static final int LE_TK_OCTETS = 16; // 0x10
-    field public static final int OOB_LENGTH_OCTETS = 2; // 0x2
-    field public static final int RANDOMIZER_OCTETS = 16; // 0x10
-  }
-
-  public static final class OobData.ClassicBuilder {
-    ctor public OobData.ClassicBuilder(@NonNull byte[], @NonNull byte[], @NonNull byte[]);
-    method @NonNull public android.bluetooth.OobData build();
-    method @NonNull public android.bluetooth.OobData.ClassicBuilder setClassOfDevice(@NonNull byte[]);
-    method @NonNull public android.bluetooth.OobData.ClassicBuilder setDeviceName(@NonNull byte[]);
-    method @NonNull public android.bluetooth.OobData.ClassicBuilder setRandomizerHash(@NonNull byte[]);
-  }
-
-  public static final class OobData.LeBuilder {
-    ctor public OobData.LeBuilder(@NonNull byte[], @NonNull byte[], int);
-    method @NonNull public android.bluetooth.OobData build();
-    method @NonNull public android.bluetooth.OobData.LeBuilder setDeviceName(@NonNull byte[]);
-    method @NonNull public android.bluetooth.OobData.LeBuilder setLeFlags(int);
-    method @NonNull public android.bluetooth.OobData.LeBuilder setLeTemporaryKey(@NonNull byte[]);
-    method @NonNull public android.bluetooth.OobData.LeBuilder setRandomizerHash(@NonNull byte[]);
-  }
-
-  public final class UidTraffic implements java.lang.Cloneable android.os.Parcelable {
-    method public long getRxBytes();
-    method public long getTxBytes();
-    method public int getUid();
-    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.UidTraffic> CREATOR;
-  }
-
-}
-
-package android.bluetooth.le {
-
-  public final class AdvertiseSettings implements android.os.Parcelable {
-    method public int getOwnAddressType();
-  }
-
-  public static final class AdvertiseSettings.Builder {
-    method @NonNull public android.bluetooth.le.AdvertiseSettings.Builder setOwnAddressType(int);
-  }
-
-  public final class AdvertisingSetParameters implements android.os.Parcelable {
-    method public int getOwnAddressType();
-    field public static final int ADDRESS_TYPE_DEFAULT = -1; // 0xffffffff
-    field public static final int ADDRESS_TYPE_PUBLIC = 0; // 0x0
-    field public static final int ADDRESS_TYPE_RANDOM = 1; // 0x1
-  }
-
-  public static final class AdvertisingSetParameters.Builder {
-    method @NonNull public android.bluetooth.le.AdvertisingSetParameters.Builder setOwnAddressType(int);
-  }
-
-  public final class BluetoothLeScanner {
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.UPDATE_DEVICE_STATS}) public void startScanFromSource(android.os.WorkSource, android.bluetooth.le.ScanCallback);
-    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.UPDATE_DEVICE_STATS}) public void startScanFromSource(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.os.WorkSource, android.bluetooth.le.ScanCallback);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void startTruncatedScan(java.util.List<android.bluetooth.le.TruncatedFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
-  }
-
-  @Deprecated public final class ResultStorageDescriptor implements android.os.Parcelable {
-    ctor @Deprecated public ResultStorageDescriptor(int, int, int);
-    method @Deprecated public int describeContents();
-    method @Deprecated public int getLength();
-    method @Deprecated public int getOffset();
-    method @Deprecated public int getType();
-    method @Deprecated public void writeToParcel(android.os.Parcel, int);
-    field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.ResultStorageDescriptor> CREATOR;
-  }
-
-  public final class ScanFilter implements android.os.Parcelable {
-    method public int getAddressType();
-    method @Nullable public byte[] getIrk();
-  }
-
-  public static final class ScanFilter.Builder {
-    method @NonNull public android.bluetooth.le.ScanFilter.Builder setDeviceAddress(@NonNull String, int);
-    method @NonNull public android.bluetooth.le.ScanFilter.Builder setDeviceAddress(@NonNull String, int, @NonNull byte[]);
-    field public static final int LEN_IRK_OCTETS = 16; // 0x10
-  }
-
-  public final class ScanSettings implements android.os.Parcelable {
-    field public static final int SCAN_MODE_AMBIENT_DISCOVERY = 3; // 0x3
-    field public static final int SCAN_RESULT_TYPE_ABBREVIATED = 1; // 0x1
-    field public static final int SCAN_RESULT_TYPE_FULL = 0; // 0x0
-  }
-
-  public static final class ScanSettings.Builder {
-    method public android.bluetooth.le.ScanSettings.Builder setScanResultType(int);
-  }
-
-  @Deprecated public final class TruncatedFilter {
-    ctor @Deprecated public TruncatedFilter(android.bluetooth.le.ScanFilter, java.util.List<android.bluetooth.le.ResultStorageDescriptor>);
-    method @Deprecated public android.bluetooth.le.ScanFilter getFilter();
-    method @Deprecated public java.util.List<android.bluetooth.le.ResultStorageDescriptor> getStorageDescriptors();
-  }
-
-}
-
 package android.companion {
 
   public final class AssociationInfo implements android.os.Parcelable {
@@ -2768,12 +2300,26 @@
     method @Nullable @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.companion.virtual.VirtualDeviceManager.VirtualDevice createVirtualDevice(int, @NonNull android.companion.virtual.VirtualDeviceParams);
   }
 
+  public static interface VirtualDeviceManager.ActivityListener {
+    method public void onDisplayEmpty(int);
+    method public void onTopActivityChanged(int, @NonNull android.content.ComponentName);
+  }
+
+  public static interface VirtualDeviceManager.LaunchCallback {
+    method public void onLaunchFailed();
+    method public void onLaunchSuccess();
+  }
+
   public static class VirtualDeviceManager.VirtualDevice implements java.lang.AutoCloseable {
+    method public void addActivityListener(@NonNull android.companion.virtual.VirtualDeviceManager.ActivityListener);
+    method public void addActivityListener(@NonNull android.companion.virtual.VirtualDeviceManager.ActivityListener, @NonNull java.util.concurrent.Executor);
     method public void close();
     method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(int, int, int, @Nullable android.view.Surface, int, @Nullable android.os.Handler, @Nullable android.hardware.display.VirtualDisplay.Callback);
     method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualKeyboard createVirtualKeyboard(@NonNull android.hardware.display.VirtualDisplay, @NonNull String, int, int);
     method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualMouse createVirtualMouse(@NonNull android.hardware.display.VirtualDisplay, @NonNull String, int, int);
     method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualTouchscreen createVirtualTouchscreen(@NonNull android.hardware.display.VirtualDisplay, @NonNull String, int, int);
+    method public void launchPendingIntent(int, @NonNull android.app.PendingIntent, @NonNull java.util.concurrent.Executor, @NonNull android.companion.virtual.VirtualDeviceManager.LaunchCallback);
+    method public void removeActivityListener(@NonNull android.companion.virtual.VirtualDeviceManager.ActivityListener);
   }
 
   public final class VirtualDeviceParams implements android.os.Parcelable {
@@ -5245,6 +4791,7 @@
     method @CheckResult @RequiresPermission(android.Manifest.permission.MANAGE_USB) public int enableUsbData(boolean);
     method @CheckResult @RequiresPermission(android.Manifest.permission.MANAGE_USB) public int enableUsbDataWhileDocked();
     method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USB) public android.hardware.usb.UsbPortStatus getStatus();
+    method @CheckResult @RequiresPermission(android.Manifest.permission.MANAGE_USB) public int resetUsbPort();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void setRoles(int, int);
     field public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_INTERNAL = 1; // 0x1
     field public static final int ENABLE_LIMIT_POWER_TRANSFER_ERROR_NOT_SUPPORTED = 2; // 0x2
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index ff26ae8..169346b 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -617,14 +617,6 @@
 
 }
 
-package android.bluetooth {
-
-  public final class BluetoothClass implements android.os.Parcelable {
-    method public int getClassOfDevice();
-  }
-
-}
-
 package android.companion {
 
   public abstract class CompanionDeviceService extends android.app.Service {
@@ -1801,7 +1793,6 @@
     method public static android.os.VibrationEffect get(int, boolean);
     method @Nullable public static android.os.VibrationEffect get(android.net.Uri, android.content.Context);
     method public abstract long getDuration();
-    method @NonNull public static android.os.VibrationEffect.WaveformBuilder startWaveform();
     field public static final int EFFECT_POP = 4; // 0x4
     field public static final int EFFECT_STRENGTH_LIGHT = 0; // 0x0
     field public static final int EFFECT_STRENGTH_MEDIUM = 1; // 0x1
@@ -1819,20 +1810,6 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.os.VibrationEffect.Composed> CREATOR;
   }
 
-  public static final class VibrationEffect.Composition {
-    method @NonNull public android.os.VibrationEffect.Composition addEffect(@NonNull android.os.VibrationEffect);
-    method @NonNull public android.os.VibrationEffect.Composition addEffect(@NonNull android.os.VibrationEffect, @IntRange(from=0) int);
-  }
-
-  public static final class VibrationEffect.WaveformBuilder {
-    method @NonNull public android.os.VibrationEffect.WaveformBuilder addRamp(@FloatRange(from=0.0f, to=1.0f) float, @IntRange(from=0) int);
-    method @NonNull public android.os.VibrationEffect.WaveformBuilder addRamp(@FloatRange(from=0.0f, to=1.0f) float, @FloatRange(from=1.0f) float, @IntRange(from=0) int);
-    method @NonNull public android.os.VibrationEffect.WaveformBuilder addStep(@FloatRange(from=0.0f, to=1.0f) float, @IntRange(from=0) int);
-    method @NonNull public android.os.VibrationEffect.WaveformBuilder addStep(@FloatRange(from=0.0f, to=1.0f) float, @FloatRange(from=1.0f) float, @IntRange(from=0) int);
-    method @NonNull public android.os.VibrationEffect build();
-    method @NonNull public android.os.VibrationEffect build(int);
-  }
-
   public abstract class Vibrator {
     method public int getDefaultVibrationIntensity(int);
     field public static final int VIBRATION_INTENSITY_HIGH = 3; // 0x3
@@ -2507,6 +2484,7 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void refreshUiccProfile();
     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);
+    method @RequiresPermission(android.Manifest.permission.BIND_TELECOM_CONNECTION_SERVICE) public void setVoiceServiceStateOverride(boolean);
     field public static final int UNKNOWN_CARRIER_ID_LIST_VERSION = -1; // 0xffffffff
   }
 
diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java
index 7812aba..e31a566 100644
--- a/core/java/android/app/BroadcastOptions.java
+++ b/core/java/android/app/BroadcastOptions.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -52,6 +53,7 @@
     private String[] mRequireNoneOfPermissions;
     private long mRequireCompatChangeId = CHANGE_INVALID;
     private boolean mRequireCompatChangeEnabled = true;
+    private long mIdForResponseEvent;
 
     /**
      * Change ID which is invalid.
@@ -164,6 +166,12 @@
     public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED =
             PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED;
 
+    /**
+     * Corresponds to {@link #recordResponseEventWhileInBackground(long)}.
+     */
+    private static final String KEY_ID_FOR_RESPONSE_EVENT =
+            "android:broadcast.idForResponseEvent";
+
     public static BroadcastOptions makeBasic() {
         BroadcastOptions opts = new BroadcastOptions();
         return opts;
@@ -198,6 +206,7 @@
         mRequireNoneOfPermissions = opts.getStringArray(KEY_REQUIRE_NONE_OF_PERMISSIONS);
         mRequireCompatChangeId = opts.getLong(KEY_REQUIRE_COMPAT_CHANGE_ID, CHANGE_INVALID);
         mRequireCompatChangeEnabled = opts.getBoolean(KEY_REQUIRE_COMPAT_CHANGE_ENABLED, true);
+        mIdForResponseEvent = opts.getLong(KEY_ID_FOR_RESPONSE_EVENT);
     }
 
     /**
@@ -511,6 +520,28 @@
     }
 
     /**
+     * Sets whether events (such as posting a notification) originating from an app after it
+     * receives the broadcast while in background should be recorded as responses to the broadcast.
+     *
+     * @param id ID to be used for the response events corresponding to this broadcast. If the
+     *           value is {@code 0} (default), then response events will not be recorded. Otherwise,
+     *           they will be recorded with the ID provided.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)
+    public void recordResponseEventWhileInBackground(@IntRange(from = 0) long id) {
+        mIdForResponseEvent = id;
+    }
+
+    /** @hide */
+    @IntRange(from = 0)
+    public long getIdForResponseEvent() {
+        return mIdForResponseEvent;
+    }
+
+    /**
      * Returns the created options as a Bundle, which can be passed to
      * {@link android.content.Context#sendBroadcast(android.content.Intent)
      * Context.sendBroadcast(Intent)} and related methods.
@@ -549,6 +580,9 @@
             b.putLong(KEY_REQUIRE_COMPAT_CHANGE_ID, mRequireCompatChangeId);
             b.putBoolean(KEY_REQUIRE_COMPAT_CHANGE_ENABLED, mRequireCompatChangeEnabled);
         }
+        if (mIdForResponseEvent != 0) {
+            b.putLong(KEY_ID_FOR_RESPONSE_EVENT, mIdForResponseEvent);
+        }
         return b.isEmpty() ? null : b;
     }
 }
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 779552f1..d57c288 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -6712,6 +6712,18 @@
             return;
         }
         boolean isLowRam = ActivityManager.isLowRamDeviceStatic();
+
+        if (mSmallIcon != null
+                // Only bitmap icons can be downscaled.
+                && (mSmallIcon.getType() == Icon.TYPE_BITMAP
+                        || mSmallIcon.getType() == Icon.TYPE_ADAPTIVE_BITMAP)) {
+            Resources resources = context.getResources();
+            int maxSize = resources.getDimensionPixelSize(
+                    isLowRam ? R.dimen.notification_small_icon_size_low_ram
+                            : R.dimen.notification_small_icon_size);
+            mSmallIcon.scaleDownIfNecessary(maxSize, maxSize);
+        }
+
         if (mLargeIcon != null || largeIcon != null) {
             Resources resources = context.getResources();
             Class<? extends Style> style = getNotificationStyle();
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index cbce8ac..3960f4e 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -10091,12 +10091,29 @@
     }
 
     /**
+     * Same as {@link #logoutUser(ComponentName)}, but called by system (like Settings), not admin.
+     *
+     * @hide
+     */
+    @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.CREATE_USERS})
+    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+    public @UserOperationResult int logoutUser() {
+        // TODO(b/214336184): add CTS test
+        try {
+            return mService.logoutUserInternal();
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+    /**
      * Gets the user a {@link #logoutUser(ComponentName)} call would switch to,
      * or {@code null} if the current user is not in a session.
      *
      * @hide
      */
-    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.INTERACT_ACROSS_USERS})
     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
     public @Nullable UserHandle getLogoutUser() {
         // TODO(b/214336184): add CTS test
@@ -10109,24 +10126,6 @@
     }
 
     /**
-     * Clears the user that {@link #logoutUser(ComponentName)} would switch to.
-     *
-     * <p>Typically used by system UI after it logout a session.
-     *
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
-    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
-    public void clearLogoutUser() {
-        // TODO(b/214336184): add CTS test
-        try {
-            mService.clearLogoutUser();
-        } catch (RemoteException re) {
-            throw re.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * Called by a device owner to list all secondary users on the device. Managed profiles are not
      * considered as secondary users.
      * <p> Used for various user management APIs, including {@link #switchUser}, {@link #removeUser}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 7525d54..927ee0c 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -268,8 +268,8 @@
     int startUserInBackground(in ComponentName who, in UserHandle userHandle);
     int stopUser(in ComponentName who, in UserHandle userHandle);
     int logoutUser(in ComponentName who);
+    int logoutUserInternal(); // AIDL doesn't allow overloading name (logoutUser())
     int getLogoutUserId();
-    void clearLogoutUser();
     List<UserHandle> getSecondaryUsers(in ComponentName who);
     void acknowledgeNewUserDisclaimer();
 
diff --git a/core/java/android/companion/virtual/IVirtualDeviceActivityListener.aidl b/core/java/android/companion/virtual/IVirtualDeviceActivityListener.aidl
index 53af4c5..a46dc53 100644
--- a/core/java/android/companion/virtual/IVirtualDeviceActivityListener.aidl
+++ b/core/java/android/companion/virtual/IVirtualDeviceActivityListener.aidl
@@ -23,7 +23,7 @@
  *
  * @hide
  */
-interface IVirtualDeviceActivityListener {
+oneway interface IVirtualDeviceActivityListener {
 
     /**
      * Called when the top activity is changed.
diff --git a/core/java/android/companion/virtual/VirtualDeviceManager.java b/core/java/android/companion/virtual/VirtualDeviceManager.java
index 64f16ac..bb9bb09 100644
--- a/core/java/android/companion/virtual/VirtualDeviceManager.java
+++ b/core/java/android/companion/virtual/VirtualDeviceManager.java
@@ -164,8 +164,6 @@
          * @param executor The executor to run {@code launchCallback} on.
          * @param launchCallback Callback that is called when the pending intent launching is
          *   complete.
-         *
-         * @hide
          */
         public void launchPendingIntent(
                 int displayId,
@@ -196,9 +194,7 @@
 
         /**
          * Creates a virtual display for this virtual device. All displays created on the same
-         * device belongs to the same display group. Requires the ADD_TRUSTED_DISPLAY permission
-         * to create a virtual display which is not in the default DisplayGroup, and to create
-         * trusted displays.
+         * device belongs to the same display group.
          *
          * @param width The width of the virtual display in pixels, must be greater than 0.
          * @param height The height of the virtual display in pixels, must be greater than 0.
@@ -369,9 +365,7 @@
          *
          * @param listener The listener to add.
          * @see #removeActivityListener(ActivityListener)
-         * @hide
          */
-        // TODO(b/194949534): Unhide this API
         public void addActivityListener(@NonNull ActivityListener listener) {
             addActivityListener(listener, mContext.getMainExecutor());
         }
@@ -383,9 +377,7 @@
          * @param listener The listener to add.
          * @param executor The executor where the callback is executed on.
          * @see #removeActivityListener(ActivityListener)
-         * @hide
          */
-        // TODO(b/194949534): Unhide this API
         public void addActivityListener(
                 @NonNull ActivityListener listener, @NonNull Executor executor) {
             mActivityListeners.put(listener, new ActivityListenerDelegate(listener, executor));
@@ -397,9 +389,7 @@
          *
          * @param listener The listener to remove.
          * @see #addActivityListener(ActivityListener, Executor)
-         * @hide
          */
-        // TODO(b/194949534): Unhide this API
         public void removeActivityListener(@NonNull ActivityListener listener) {
             mActivityListeners.remove(listener);
         }
@@ -407,10 +397,7 @@
 
     /**
      * Callback for launching pending intents on the virtual device.
-     *
-     * @hide
      */
-    // TODO(b/194949534): Unhide this API
     public interface LaunchCallback {
         /**
          * Called when the pending intent launched successfully.
@@ -425,10 +412,7 @@
 
     /**
      * Listener for activity changes in this virtual device.
-     *
-     * @hide
      */
-    // TODO(b/194949534): Unhide this API
     public interface ActivityListener {
 
         /**
diff --git a/core/java/android/content/pm/AppSearchShortcutInfo.java b/core/java/android/content/pm/AppSearchShortcutInfo.java
index 8d9ef853..f20d1e6 100644
--- a/core/java/android/content/pm/AppSearchShortcutInfo.java
+++ b/core/java/android/content/pm/AppSearchShortcutInfo.java
@@ -29,6 +29,7 @@
 import android.os.Bundle;
 import android.os.PersistableBundle;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -42,43 +43,125 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.concurrent.TimeUnit;
 
 /**
+ * A {@link GenericDocument} representation of {@link ShortcutInfo} object.
  * @hide
  */
 public class AppSearchShortcutInfo extends GenericDocument {
 
+    /** The TTL (time-to-live) of the shortcut, in milli-second. */
+    public static final long SHORTCUT_TTL = TimeUnit.DAYS.toMillis(90);
+
     /** The name of the schema type for {@link ShortcutInfo} documents.*/
     public static final String SCHEMA_TYPE = "Shortcut";
-    public static final int SCHEMA_VERSION = 2;
 
+    /** @hide */
+    public static final int SCHEMA_VERSION = 3;
+
+    /**
+     * Property name of the activity this {@link ShortcutInfo} is associated with.
+     * See {@link ShortcutInfo#getActivity()}.
+     */
     public static final String KEY_ACTIVITY = "activity";
+
+    /**
+     * Property name of the short description of this {@link ShortcutInfo}.
+     * See {@link ShortcutInfo#getShortLabel()}.
+     */
     public static final String KEY_SHORT_LABEL = "shortLabel";
-    public static final String KEY_SHORT_LABEL_RES_ID = "shortLabelResId";
-    public static final String KEY_SHORT_LABEL_RES_NAME = "shortLabelResName";
+
+    /**
+     * Property name of the long description of this {@link ShortcutInfo}.
+     * See {@link ShortcutInfo#getLongLabel()}.
+     */
     public static final String KEY_LONG_LABEL = "longLabel";
-    public static final String KEY_LONG_LABEL_RES_ID = "longLabelResId";
-    public static final String KEY_LONG_LABEL_RES_NAME = "longLabelResName";
+
+    /**
+     * @hide
+     */
     public static final String KEY_DISABLED_MESSAGE = "disabledMessage";
-    public static final String KEY_DISABLED_MESSAGE_RES_ID = "disabledMessageResId";
-    public static final String KEY_DISABLED_MESSAGE_RES_NAME = "disabledMessageResName";
+
+    /**
+     * Property name of the categories this {@link ShortcutInfo} is associated with.
+     * See {@link ShortcutInfo#getCategories()}.
+     */
     public static final String KEY_CATEGORIES = "categories";
+
+    /**
+     * Property name of the intents this {@link ShortcutInfo} is associated with.
+     * See {@link ShortcutInfo#getIntents()}.
+     */
     public static final String KEY_INTENTS = "intents";
+
+    /**
+     * @hide
+     */
     public static final String KEY_INTENT_PERSISTABLE_EXTRAS = "intentPersistableExtras";
+
+    /**
+     * Property name of {@link Person} objects this {@link ShortcutInfo} is associated with.
+     * See {@link ShortcutInfo#getPersons()}.
+     */
     public static final String KEY_PERSON = "person";
+
+    /**
+     * Property name of {@link LocusId} this {@link ShortcutInfo} is associated with.
+     * See {@link ShortcutInfo#getLocusId()}.
+     */
     public static final String KEY_LOCUS_ID = "locusId";
-    public static final String KEY_RANK = "rank";
-    public static final String KEY_IMPLICIT_RANK = "implicitRank";
+
+    /**
+     * @hide
+     */
     public static final String KEY_EXTRAS = "extras";
+
+    /**
+     * Property name of the states this {@link ShortcutInfo} is currently in.
+     * Possible values are one or more of the following:
+     *     {@link #IS_DYNAMIC}, {@link #NOT_DYNAMIC}, {@link #IS_MANIFEST}, {@link #NOT_MANIFEST},
+     *     {@link #IS_DISABLED}, {@link #NOT_DISABLED}, {@link #IS_IMMUTABLE},
+     *     {@link #NOT_IMMUTABLE}
+     *
+     */
     public static final String KEY_FLAGS = "flags";
+
+    /**
+     * @hide
+     */
     public static final String KEY_ICON_RES_ID = "iconResId";
+
+    /**
+     * @hide
+     */
     public static final String KEY_ICON_RES_NAME = "iconResName";
+
+    /**
+     * @hide
+     */
     public static final String KEY_ICON_URI = "iconUri";
-    public static final String KEY_BITMAP_PATH = "bitmapPath";
+
+    /**
+     * @hide
+     */
     public static final String KEY_DISABLED_REASON = "disabledReason";
 
+    /**
+     * Property name of capability this {@link ShortcutInfo} is associated with.
+     * See {@link ShortcutInfo#hasCapability(String)}.
+     */
+    public static final String KEY_CAPABILITY = "capability";
+
+    /**
+     * Property name of capability binding this {@link ShortcutInfo} is associated with.
+     * See {@link ShortcutInfo#getCapabilityParameters(String, String)}.
+     */
+    public static final String KEY_CAPABILITY_BINDINGS = "capabilityBindings";
+
     public static final AppSearchSchema SCHEMA = new AppSearchSchema.Builder(SCHEMA_TYPE)
             .addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_ACTIVITY)
                     .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
@@ -92,50 +175,18 @@
                     .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_PREFIXES)
                     .build()
 
-            ).addProperty(new AppSearchSchema.LongPropertyConfig.Builder(KEY_SHORT_LABEL_RES_ID)
-                    .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
-                    .build()
-
-            ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_SHORT_LABEL_RES_NAME)
-                    .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
-                    .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_NONE)
-                    .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_NONE)
-                    .build()
-
             ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_LONG_LABEL)
                     .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
                     .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
                     .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_PREFIXES)
                     .build()
 
-            ).addProperty(new AppSearchSchema.LongPropertyConfig.Builder(KEY_LONG_LABEL_RES_ID)
-                    .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
-                    .build()
-
-            ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_LONG_LABEL_RES_NAME)
-                    .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
-                    .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_NONE)
-                    .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_NONE)
-                    .build()
-
             ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_DISABLED_MESSAGE)
                     .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
                     .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_NONE)
                     .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_NONE)
                     .build()
 
-            ).addProperty(new AppSearchSchema.LongPropertyConfig.Builder(
-                    KEY_DISABLED_MESSAGE_RES_ID)
-                    .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
-                    .build()
-
-            ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(
-                    KEY_DISABLED_MESSAGE_RES_NAME)
-                    .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
-                    .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_NONE)
-                    .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_NONE)
-                    .build()
-
             ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_CATEGORIES)
                     .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED)
                     .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
@@ -154,7 +205,7 @@
                     .build()
 
             ).addProperty(new AppSearchSchema.DocumentPropertyConfig.Builder(
-                    KEY_PERSON, AppSearchPerson.SCHEMA_TYPE)
+                    KEY_PERSON, AppSearchShortcutPerson.SCHEMA_TYPE)
                     .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED)
                     .build()
 
@@ -164,16 +215,6 @@
                     .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS)
                     .build()
 
-            ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_RANK)
-                    .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
-                    .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
-                    .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS)
-                    .build()
-
-            ).addProperty(new AppSearchSchema.LongPropertyConfig.Builder(KEY_IMPLICIT_RANK)
-                    .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
-                    .build()
-
             ).addProperty(new AppSearchSchema.BytesPropertyConfig.Builder(KEY_EXTRAS)
                     .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
                     .build()
@@ -200,18 +241,24 @@
                     .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_NONE)
                     .build()
 
-            ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_BITMAP_PATH)
-                    .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
-                    .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_NONE)
-                    .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_NONE)
-                    .build()
-
             ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_DISABLED_REASON)
                     .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_REQUIRED)
                     .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
                     .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS)
                     .build()
 
+            ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_CAPABILITY)
+                    .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED)
+                    .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+                    .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS)
+                    .build()
+
+            ).addProperty(new AppSearchSchema.StringPropertyConfig.Builder(KEY_CAPABILITY_BINDINGS)
+                    .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED)
+                    .setTokenizerType(AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_PLAIN)
+                    .setIndexingType(AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_PREFIXES)
+                    .build()
+
             ).build();
 
     /**
@@ -219,97 +266,62 @@
      * needs to be camelCase since AppSearch's tokenizer will break the word when it sees
      * underscore.
      */
-    private static final String IS_DYNAMIC = "Dyn";
-    private static final String NOT_DYNAMIC = "nDyn";
-    private static final String IS_PINNED = "Pin";
-    private static final String NOT_PINNED = "nPin";
-    private static final String HAS_ICON_RES = "IcR";
-    private static final String NO_ICON_RES = "nIcR";
-    private static final String HAS_ICON_FILE = "IcF";
-    private static final String NO_ICON_FILE = "nIcF";
-    private static final String IS_KEY_FIELD_ONLY = "Key";
-    private static final String NOT_KEY_FIELD_ONLY = "nKey";
-    private static final String IS_MANIFEST = "Man";
-    private static final String NOT_MANIFEST = "nMan";
-    private static final String IS_DISABLED = "Dis";
-    private static final String NOT_DISABLED = "nDis";
-    private static final String ARE_STRINGS_RESOLVED = "Str";
-    private static final String NOT_STRINGS_RESOLVED = "nStr";
-    private static final String IS_IMMUTABLE = "Im";
-    private static final String NOT_IMMUTABLE = "nIm";
-    private static final String HAS_ADAPTIVE_BITMAP = "IcA";
-    private static final String NO_ADAPTIVE_BITMAP = "nIcA";
-    private static final String IS_RETURNED_BY_SERVICE = "Rets";
-    private static final String NOT_RETURNED_BY_SERVICE = "nRets";
-    private static final String HAS_ICON_FILE_PENDING_SAVE = "Pens";
-    private static final String NO_ICON_FILE_PENDING_SAVE = "nPens";
-    private static final String IS_SHADOW = "Sdw";
-    private static final String NOT_SHADOW = "nSdw";
-    private static final String IS_LONG_LIVED = "Liv";
-    private static final String NOT_LONG_LIVED = "nLiv";
-    private static final String HAS_ICON_URI = "IcU";
-    private static final String NO_ICON_URI = "nIcU";
-    private static final String IS_CACHED_NOTIFICATION = "CaN";
-    private static final String NOT_CACHED_NOTIFICATION = "nCaN";
-    private static final String IS_CACHED_BUBBLE = "CaB";
-    private static final String NOT_CACHED_BUBBLE = "nCaB";
-    private static final String IS_CACHED_PEOPLE_TITLE = "CaPT";
-    private static final String NOT_CACHED_PEOPLE_TITLE = "nCaPT";
 
     /**
-     * Following flags are not store within ShortcutInfo, but book-keeping states to reduce search
-     * space when performing queries against AppSearch.
+     * Indicates the {@link ShortcutInfo} is dynamic shortcut.
+     * See {@link #KEY_FLAGS}
+     * See {@link ShortcutInfo#isDynamic()}.
      */
-    private static final String HAS_BITMAP_PATH = "hBiP";
-    private static final String HAS_STRING_RESOURCE = "hStr";
-    private static final String HAS_NON_ZERO_RANK = "hRan";
+    public static final String IS_DYNAMIC = "Dyn";
 
-    public static final String QUERY_IS_DYNAMIC = KEY_FLAGS + ":" + IS_DYNAMIC;
-    public static final String QUERY_IS_NOT_DYNAMIC = KEY_FLAGS + ":" + NOT_DYNAMIC;
-    public static final String QUERY_IS_PINNED = KEY_FLAGS + ":" + IS_PINNED;
-    public static final String QUERY_IS_NOT_PINNED = KEY_FLAGS + ":" + NOT_PINNED;
-    public static final String QUERY_IS_MANIFEST = KEY_FLAGS + ":" + IS_MANIFEST;
-    public static final String QUERY_IS_NOT_MANIFEST = KEY_FLAGS + ":" + NOT_MANIFEST;
-    public static final String QUERY_IS_PINNED_AND_ENABLED =
-            "(" + KEY_FLAGS + ":" + IS_PINNED + " " + KEY_FLAGS + ":" + NOT_DISABLED + ")";
-    public static final String QUERY_IS_CACHED =
-            "(" + KEY_FLAGS + ":" + IS_CACHED_NOTIFICATION + " OR "
-            + KEY_FLAGS + ":" + IS_CACHED_BUBBLE + " OR "
-            + KEY_FLAGS + ":" + IS_CACHED_PEOPLE_TITLE + ")";
-    public static final String QUERY_IS_NOT_CACHED =
-            "(" + KEY_FLAGS + ":" + NOT_CACHED_NOTIFICATION + " "
-                    + KEY_FLAGS + ":" + NOT_CACHED_BUBBLE + " "
-                    + KEY_FLAGS + ":" + NOT_CACHED_PEOPLE_TITLE + ")";
-    public static final String QUERY_IS_FLOATING =
-            "((" + IS_PINNED + " OR " + QUERY_IS_CACHED + ") "
-                    + QUERY_IS_NOT_DYNAMIC + " " + QUERY_IS_NOT_MANIFEST + ")";
-    public static final String QUERY_IS_NOT_FLOATING =
-            "((" + QUERY_IS_NOT_PINNED + " " + QUERY_IS_NOT_CACHED + ") OR "
-                    + QUERY_IS_DYNAMIC + " OR " + QUERY_IS_MANIFEST + ")";
-    public static final String QUERY_IS_VISIBLE_TO_PUBLISHER =
-            "(" + KEY_DISABLED_REASON + ":" + ShortcutInfo.DISABLED_REASON_NOT_DISABLED
-                    + " OR " + KEY_DISABLED_REASON + ":"
-                    + ShortcutInfo.DISABLED_REASON_BY_APP
-                    + " OR " + KEY_DISABLED_REASON + ":"
-                    + ShortcutInfo.DISABLED_REASON_APP_CHANGED
-                    + " OR " + KEY_DISABLED_REASON + ":"
-                    + ShortcutInfo.DISABLED_REASON_UNKNOWN + ")";
-    public static final String QUERY_DISABLED_REASON_VERSION_LOWER =
-            KEY_DISABLED_REASON + ":" + ShortcutInfo.DISABLED_REASON_VERSION_LOWER;
-    public static final String QUERY_IS_NON_MANIFEST_VISIBLE =
-            "(" + QUERY_IS_NOT_MANIFEST + " " + QUERY_IS_VISIBLE_TO_PUBLISHER + " ("
-                    + QUERY_IS_PINNED + " OR " + QUERY_IS_CACHED + " OR " + QUERY_IS_DYNAMIC + "))";
-    public static final String QUERY_IS_VISIBLE_CACHED_OR_PINNED =
-            "(" + QUERY_IS_VISIBLE_TO_PUBLISHER + " " + QUERY_IS_DYNAMIC
-                    + " (" + QUERY_IS_CACHED + " OR " + QUERY_IS_PINNED + "))";
-    public static final String QUERY_IS_VISIBLE_PINNED_ONLY =
-            "(" + QUERY_IS_VISIBLE_TO_PUBLISHER + " " + QUERY_IS_PINNED + " " + QUERY_IS_NOT_CACHED
-            + " " + QUERY_IS_NOT_DYNAMIC + " " + QUERY_IS_NOT_MANIFEST + ")";
-    public static final String QUERY_HAS_BITMAP_PATH = KEY_FLAGS + ":" + HAS_BITMAP_PATH;
-    public static final String QUERY_HAS_STRING_RESOURCE = KEY_FLAGS + ":" + HAS_STRING_RESOURCE;
-    public static final String QUERY_HAS_NON_ZERO_RANK = KEY_FLAGS + ":" + HAS_NON_ZERO_RANK;
-    public static final String QUERY_IS_FLOATING_AND_HAS_RANK =
-            "(" + QUERY_IS_FLOATING + " " + QUERY_HAS_NON_ZERO_RANK + ")";
+    /**
+     * Indicates the {@link ShortcutInfo} is not a dynamic shortcut.
+     * See {@link #KEY_FLAGS}
+     * See {@link ShortcutInfo#isDynamic()}.
+     */
+    public static final String NOT_DYNAMIC = "nDyn";
+
+    /**
+     * Indicates the {@link ShortcutInfo} is manifest shortcut.
+     * See {@link #KEY_FLAGS}
+     * See {@link ShortcutInfo#isDeclaredInManifest()}.
+     */
+    public static final String IS_MANIFEST = "Man";
+
+    /**
+     * Indicates the {@link ShortcutInfo} is manifest shortcut.
+     * See {@link #KEY_FLAGS}
+     * See {@link ShortcutInfo#isDeclaredInManifest()}.
+     */
+    public static final String NOT_MANIFEST = "nMan";
+
+    /**
+     * Indicates the {@link ShortcutInfo} is disabled.
+     * See {@link #KEY_FLAGS}
+     * See {@link ShortcutInfo#isEnabled()}.
+     */
+    public static final String IS_DISABLED = "Dis";
+
+    /**
+     * Indicates the {@link ShortcutInfo} is enabled.
+     * See {@link #KEY_FLAGS}
+     * See {@link ShortcutInfo#isEnabled()}.
+     */
+    public static final String NOT_DISABLED = "nDis";
+
+    /**
+     * Indicates the {@link ShortcutInfo} was originally from manifest, but currently disabled.
+     * See {@link #KEY_FLAGS}
+     * See {@link ShortcutInfo#isOriginallyFromManifest()}.
+     */
+    public static final String IS_IMMUTABLE = "Im";
+
+    /**
+     * Indicates the {@link ShortcutInfo} was not originally from manifest.
+     * See {@link #KEY_FLAGS}
+     * See {@link ShortcutInfo#isOriginallyFromManifest()}.
+     */
+    public static final String NOT_IMMUTABLE = "nIm";
 
     public AppSearchShortcutInfo(@NonNull GenericDocument document) {
         super(document);
@@ -324,34 +336,27 @@
         return new Builder(shortcutInfo.getPackage(), shortcutInfo.getId())
                 .setActivity(shortcutInfo.getActivity())
                 .setShortLabel(shortcutInfo.getShortLabel())
-                .setShortLabelResId(shortcutInfo.getShortLabelResourceId())
-                .setShortLabelResName(shortcutInfo.getTitleResName())
                 .setLongLabel(shortcutInfo.getLongLabel())
-                .setLongLabelResId(shortcutInfo.getLongLabelResourceId())
-                .setLongLabelResName(shortcutInfo.getTextResName())
                 .setDisabledMessage(shortcutInfo.getDisabledMessage())
-                .setDisabledMessageResId(shortcutInfo.getDisabledMessageResourceId())
-                .setDisabledMessageResName(shortcutInfo.getDisabledMessageResName())
                 .setCategories(shortcutInfo.getCategories())
                 .setIntents(shortcutInfo.getIntents())
-                .setRank(shortcutInfo.getRank())
-                .setImplicitRank(shortcutInfo.getImplicitRank()
-                        | (shortcutInfo.isRankChanged() ? ShortcutInfo.RANK_CHANGED_BIT : 0))
                 .setExtras(shortcutInfo.getExtras())
                 .setCreationTimestampMillis(shortcutInfo.getLastChangedTimestamp())
                 .setFlags(shortcutInfo.getFlags())
                 .setIconResId(shortcutInfo.getIconResourceId())
                 .setIconResName(shortcutInfo.getIconResName())
-                .setBitmapPath(shortcutInfo.getBitmapPath())
                 .setIconUri(shortcutInfo.getIconUri())
                 .setDisabledReason(shortcutInfo.getDisabledReason())
                 .setPersons(shortcutInfo.getPersons())
                 .setLocusId(shortcutInfo.getLocusId())
+                .setCapabilityBindings(shortcutInfo.getCapabilityBindings())
+                .setTtlMillis(SHORTCUT_TTL)
                 .build();
     }
 
     /**
-     * @hide
+     * Converts this {@link GenericDocument} object into {@link ShortcutInfo} to read the
+     * information.
      */
     @NonNull
     public ShortcutInfo toShortcutInfo(@UserIdInt int userId) {
@@ -367,14 +372,8 @@
         // LauncherApps#getShortcutIconDrawable instead.
         final Icon icon = null;
         final String shortLabel = getPropertyString(KEY_SHORT_LABEL);
-        final int shortLabelResId = (int) getPropertyLong(KEY_SHORT_LABEL_RES_ID);
-        final String shortLabelResName = getPropertyString(KEY_SHORT_LABEL_RES_NAME);
         final String longLabel = getPropertyString(KEY_LONG_LABEL);
-        final int longLabelResId = (int) getPropertyLong(KEY_LONG_LABEL_RES_ID);
-        final String longLabelResName = getPropertyString(KEY_LONG_LABEL_RES_NAME);
         final String disabledMessage = getPropertyString(KEY_DISABLED_MESSAGE);
-        final int disabledMessageResId = (int) getPropertyLong(KEY_DISABLED_MESSAGE_RES_ID);
-        final String disabledMessageResName = getPropertyString(KEY_DISABLED_MESSAGE_RES_NAME);
         final String[] categories = getPropertyStringArray(KEY_CATEGORIES);
         final Set<String> categoriesSet = categories == null
                 ? null : new ArraySet<>(Arrays.asList(categories));
@@ -408,27 +407,22 @@
         final Person[] persons = parsePerson(getPropertyDocumentArray(KEY_PERSON));
         final String locusIdString = getPropertyString(KEY_LOCUS_ID);
         final LocusId locusId = locusIdString == null ? null : new LocusId(locusIdString);
-        final int rank = Integer.parseInt(getPropertyString(KEY_RANK));
-        final int implicitRank = (int) getPropertyLong(KEY_IMPLICIT_RANK);
         final byte[] extrasByte = getPropertyBytes(KEY_EXTRAS);
         final PersistableBundle extras = transformToPersistableBundle(extrasByte);
         final int flags = parseFlags(getPropertyStringArray(KEY_FLAGS));
         final int iconResId = (int) getPropertyLong(KEY_ICON_RES_ID);
         final String iconResName = getPropertyString(KEY_ICON_RES_NAME);
         final String iconUri = getPropertyString(KEY_ICON_URI);
-        final String bitmapPath = getPropertyString(KEY_BITMAP_PATH);
         final int disabledReason = Integer.parseInt(getPropertyString(KEY_DISABLED_REASON));
-        final ShortcutInfo si = new ShortcutInfo(
-                userId, getId(), packageName, activity, icon, shortLabel, shortLabelResId,
-                shortLabelResName, longLabel, longLabelResId, longLabelResName, disabledMessage,
-                disabledMessageResId, disabledMessageResName, categoriesSet, intents, rank, extras,
-                getCreationTimestampMillis(), flags, iconResId, iconResName, bitmapPath, iconUri,
-                disabledReason, persons, locusId, null, null);
-        si.setImplicitRank(implicitRank);
-        if ((implicitRank & ShortcutInfo.RANK_CHANGED_BIT) != 0) {
-            si.setRankChanged();
-        }
-        return si;
+        final Map<String, Map<String, List<String>>> capabilityBindings =
+                parseCapabilityBindings(getPropertyStringArray(KEY_CAPABILITY_BINDINGS));
+        return new ShortcutInfo(
+                userId, getId(), packageName, activity, icon, shortLabel, 0,
+                null, longLabel, 0, null, disabledMessage,
+                0, null, categoriesSet, intents,
+                ShortcutInfo.RANK_NOT_SET, extras, getCreationTimestampMillis(), flags, iconResId,
+                iconResName, null, iconUri, disabledReason, persons, locusId,
+                null, capabilityBindings);
     }
 
     /**
@@ -449,7 +443,6 @@
     public static class Builder extends GenericDocument.Builder<Builder> {
 
         private List<String> mFlags = new ArrayList<>(1);
-        private boolean mHasStringResource = false;
 
         public Builder(String packageName, String id) {
             super(/*namespace=*/ packageName, id, SCHEMA_TYPE);
@@ -493,28 +486,6 @@
          * @hide
          */
         @NonNull
-        public Builder setShortLabelResId(final int shortLabelResId) {
-            setPropertyLong(KEY_SHORT_LABEL_RES_ID, shortLabelResId);
-            if (shortLabelResId != 0) {
-                mHasStringResource = true;
-            }
-            return this;
-        }
-
-        /**
-         * @hide
-         */
-        public Builder setShortLabelResName(@Nullable final String shortLabelResName) {
-            if (!TextUtils.isEmpty(shortLabelResName)) {
-                setPropertyString(KEY_SHORT_LABEL_RES_NAME, shortLabelResName);
-            }
-            return this;
-        }
-
-        /**
-         * @hide
-         */
-        @NonNull
         public Builder setLongLabel(@Nullable final CharSequence longLabel) {
             if (!TextUtils.isEmpty(longLabel)) {
                 setPropertyString(KEY_LONG_LABEL, Preconditions.checkStringNotEmpty(
@@ -527,28 +498,6 @@
          * @hide
          */
         @NonNull
-        public Builder setLongLabelResId(final int longLabelResId) {
-            setPropertyLong(KEY_LONG_LABEL_RES_ID, longLabelResId);
-            if (longLabelResId != 0) {
-                mHasStringResource = true;
-            }
-            return this;
-        }
-
-        /**
-         * @hide
-         */
-        public Builder setLongLabelResName(@Nullable final String longLabelResName) {
-            if (!TextUtils.isEmpty(longLabelResName)) {
-                setPropertyString(KEY_LONG_LABEL_RES_NAME, longLabelResName);
-            }
-            return this;
-        }
-
-        /**
-         * @hide
-         */
-        @NonNull
         public Builder setDisabledMessage(@Nullable final CharSequence disabledMessage) {
             if (!TextUtils.isEmpty(disabledMessage)) {
                 setPropertyString(KEY_DISABLED_MESSAGE, Preconditions.checkStringNotEmpty(
@@ -561,28 +510,6 @@
          * @hide
          */
         @NonNull
-        public Builder setDisabledMessageResId(final int disabledMessageResId) {
-            setPropertyLong(KEY_DISABLED_MESSAGE_RES_ID, disabledMessageResId);
-            if (disabledMessageResId != 0) {
-                mHasStringResource = true;
-            }
-            return this;
-        }
-
-        /**
-         * @hide
-         */
-        public Builder setDisabledMessageResName(@Nullable final String disabledMessageResName) {
-            if (!TextUtils.isEmpty(disabledMessageResName)) {
-                setPropertyString(KEY_DISABLED_MESSAGE_RES_NAME, disabledMessageResName);
-            }
-            return this;
-        }
-
-        /**
-         * @hide
-         */
-        @NonNull
         public Builder setCategories(@Nullable final Set<String> categories) {
             if (categories != null && !categories.isEmpty()) {
                 setPropertyString(KEY_CATEGORIES, categories.stream().toArray(String[]::new));
@@ -649,8 +576,9 @@
             for (int i = 0; i < persons.length; i++) {
                 final Person person = persons[i];
                 if (person == null) continue;
-                final AppSearchPerson appSearchPerson = AppSearchPerson.instance(person);
-                documents[i] = appSearchPerson;
+                final AppSearchShortcutPerson personEntity =
+                        AppSearchShortcutPerson.instance(person);
+                documents[i] = personEntity;
             }
             setPropertyDocument(KEY_PERSON, documents);
             return this;
@@ -660,28 +588,6 @@
          * @hide
          */
         @NonNull
-        public Builder setRank(final int rank) {
-            Preconditions.checkArgument((0 <= rank), "Rank cannot be negative");
-            setPropertyString(KEY_RANK, String.valueOf(rank));
-            if (rank != 0) {
-                mFlags.add(HAS_NON_ZERO_RANK);
-            }
-            return this;
-        }
-
-        /**
-         * @hide
-         */
-        @NonNull
-        public Builder setImplicitRank(final int rank) {
-            setPropertyLong(KEY_IMPLICIT_RANK, rank);
-            return this;
-        }
-
-        /**
-         * @hide
-         */
-        @NonNull
         public Builder setExtras(@Nullable final PersistableBundle extras) {
             if (extras != null) {
                 setPropertyBytes(KEY_EXTRAS, transformToByteArray(extras));
@@ -722,17 +628,6 @@
         /**
          * @hide
          */
-        public Builder setBitmapPath(@Nullable final String bitmapPath) {
-            if (!TextUtils.isEmpty(bitmapPath)) {
-                setPropertyString(KEY_BITMAP_PATH, bitmapPath);
-                mFlags.add(HAS_BITMAP_PATH);
-            }
-            return this;
-        }
-
-        /**
-         * @hide
-         */
         public Builder setIconUri(@Nullable final String iconUri) {
             if (!TextUtils.isEmpty(iconUri)) {
                 setPropertyString(KEY_ICON_URI, iconUri);
@@ -751,12 +646,33 @@
         /**
          * @hide
          */
+        public Builder setCapabilityBindings(
+                @Nullable final Map<String, Map<String, List<String>>> bindings) {
+            if (bindings != null && !bindings.isEmpty()) {
+                final Set<String> capabilityNames = bindings.keySet();
+                final Set<String> capabilityBindings = new ArraySet<>(1);
+                for (String capabilityName: capabilityNames) {
+                    final Map<String, List<String>> params =
+                            bindings.get(capabilityName);
+                    for (String paramName: params.keySet()) {
+                        params.get(paramName).stream()
+                                .map(v -> capabilityName + "/" + paramName + "/" + v)
+                                .forEach(capabilityBindings::add);
+                    }
+                }
+                setPropertyString(KEY_CAPABILITY, capabilityNames.toArray(new String[0]));
+                setPropertyString(KEY_CAPABILITY_BINDINGS,
+                        capabilityBindings.toArray(new String[0]));
+            }
+            return this;
+        }
+
+        /**
+         * @hide
+         */
         @NonNull
         @Override
         public AppSearchShortcutInfo build() {
-            if (mHasStringResource) {
-                mFlags.add(HAS_STRING_RESOURCE);
-            }
             setPropertyString(KEY_FLAGS, mFlags.toArray(new String[0]));
             return new AppSearchShortcutInfo(super.build());
         }
@@ -827,40 +743,12 @@
         switch (mask) {
             case ShortcutInfo.FLAG_DYNAMIC:
                 return (flags & mask) != 0 ? IS_DYNAMIC : NOT_DYNAMIC;
-            case ShortcutInfo.FLAG_PINNED:
-                return (flags & mask) != 0 ? IS_PINNED : NOT_PINNED;
-            case ShortcutInfo.FLAG_HAS_ICON_RES:
-                return (flags & mask) != 0 ? HAS_ICON_RES : NO_ICON_RES;
-            case ShortcutInfo.FLAG_HAS_ICON_FILE:
-                return (flags & mask) != 0 ? HAS_ICON_FILE : NO_ICON_FILE;
-            case ShortcutInfo.FLAG_KEY_FIELDS_ONLY:
-                return (flags & mask) != 0 ? IS_KEY_FIELD_ONLY : NOT_KEY_FIELD_ONLY;
             case ShortcutInfo.FLAG_MANIFEST:
                 return (flags & mask) != 0 ? IS_MANIFEST : NOT_MANIFEST;
             case ShortcutInfo.FLAG_DISABLED:
                 return (flags & mask) != 0 ? IS_DISABLED : NOT_DISABLED;
-            case ShortcutInfo.FLAG_STRINGS_RESOLVED:
-                return (flags & mask) != 0 ? ARE_STRINGS_RESOLVED : NOT_STRINGS_RESOLVED;
             case ShortcutInfo.FLAG_IMMUTABLE:
                 return (flags & mask) != 0 ? IS_IMMUTABLE : NOT_IMMUTABLE;
-            case ShortcutInfo.FLAG_ADAPTIVE_BITMAP:
-                return (flags & mask) != 0 ? HAS_ADAPTIVE_BITMAP : NO_ADAPTIVE_BITMAP;
-            case ShortcutInfo.FLAG_RETURNED_BY_SERVICE:
-                return (flags & mask) != 0 ? IS_RETURNED_BY_SERVICE : NOT_RETURNED_BY_SERVICE;
-            case ShortcutInfo.FLAG_ICON_FILE_PENDING_SAVE:
-                return (flags & mask) != 0 ? HAS_ICON_FILE_PENDING_SAVE : NO_ICON_FILE_PENDING_SAVE;
-            case ShortcutInfo.FLAG_SHADOW:
-                return (flags & mask) != 0 ? IS_SHADOW : NOT_SHADOW;
-            case ShortcutInfo.FLAG_LONG_LIVED:
-                return (flags & mask) != 0 ? IS_LONG_LIVED : NOT_LONG_LIVED;
-            case ShortcutInfo.FLAG_HAS_ICON_URI:
-                return (flags & mask) != 0 ? HAS_ICON_URI : NO_ICON_URI;
-            case ShortcutInfo.FLAG_CACHED_NOTIFICATIONS:
-                return (flags & mask) != 0 ? IS_CACHED_NOTIFICATION : NOT_CACHED_NOTIFICATION;
-            case ShortcutInfo.FLAG_CACHED_BUBBLES:
-                return (flags & mask) != 0 ? IS_CACHED_BUBBLE : NOT_CACHED_BUBBLE;
-            case ShortcutInfo.FLAG_CACHED_PEOPLE_TILE:
-                return (flags & mask) != 0 ? IS_CACHED_PEOPLE_TITLE : NOT_CACHED_PEOPLE_TITLE;
             default:
                 return null;
         }
@@ -881,40 +769,12 @@
         switch (value) {
             case IS_DYNAMIC:
                 return ShortcutInfo.FLAG_DYNAMIC;
-            case IS_PINNED:
-                return ShortcutInfo.FLAG_PINNED;
-            case HAS_ICON_RES:
-                return ShortcutInfo.FLAG_HAS_ICON_RES;
-            case HAS_ICON_FILE:
-                return ShortcutInfo.FLAG_HAS_ICON_FILE;
-            case IS_KEY_FIELD_ONLY:
-                return ShortcutInfo.FLAG_KEY_FIELDS_ONLY;
             case IS_MANIFEST:
                 return ShortcutInfo.FLAG_MANIFEST;
             case IS_DISABLED:
                 return ShortcutInfo.FLAG_DISABLED;
-            case ARE_STRINGS_RESOLVED:
-                return ShortcutInfo.FLAG_STRINGS_RESOLVED;
             case IS_IMMUTABLE:
                 return ShortcutInfo.FLAG_IMMUTABLE;
-            case HAS_ADAPTIVE_BITMAP:
-                return ShortcutInfo.FLAG_ADAPTIVE_BITMAP;
-            case IS_RETURNED_BY_SERVICE:
-                return ShortcutInfo.FLAG_RETURNED_BY_SERVICE;
-            case HAS_ICON_FILE_PENDING_SAVE:
-                return ShortcutInfo.FLAG_ICON_FILE_PENDING_SAVE;
-            case IS_SHADOW:
-                return ShortcutInfo.FLAG_SHADOW;
-            case IS_LONG_LIVED:
-                return ShortcutInfo.FLAG_LONG_LIVED;
-            case HAS_ICON_URI:
-                return ShortcutInfo.FLAG_HAS_ICON_URI;
-            case IS_CACHED_NOTIFICATION:
-                return ShortcutInfo.FLAG_CACHED_NOTIFICATIONS;
-            case IS_CACHED_BUBBLE:
-                return ShortcutInfo.FLAG_CACHED_BUBBLES;
-            case IS_CACHED_PEOPLE_TITLE:
-                return ShortcutInfo.FLAG_CACHED_PEOPLE_TILE;
             default:
                 return 0;
         }
@@ -927,9 +787,43 @@
         for (int i = 0; i < persons.length; i++) {
             final GenericDocument document = persons[i];
             if (document == null) continue;
-            final AppSearchPerson person = new AppSearchPerson(document);
+            final AppSearchShortcutPerson person = new AppSearchShortcutPerson(document);
             ret[i] = person.toPerson();
         }
         return ret;
     }
+
+    @Nullable
+    private static Map<String, Map<String, List<String>>> parseCapabilityBindings(
+            @Nullable final String[] capabilityBindings) {
+        if (capabilityBindings == null || capabilityBindings.length == 0) {
+            return null;
+        }
+        final Map<String, Map<String, List<String>>> ret = new ArrayMap<>(1);
+        Arrays.stream(capabilityBindings).forEach(binding -> {
+            if (TextUtils.isEmpty(binding)) {
+                return;
+            }
+            final int capabilityStopIndex = binding.indexOf("/");
+            if (capabilityStopIndex == -1 || capabilityStopIndex == binding.length() - 1) {
+                return;
+            }
+            final String capabilityName = binding.substring(0, capabilityStopIndex);
+            final int paramStopIndex = binding.indexOf("/", capabilityStopIndex + 1);
+            if (paramStopIndex == -1 || paramStopIndex == binding.length() - 1) {
+                return;
+            }
+            final String paramName = binding.substring(capabilityStopIndex + 1, paramStopIndex);
+            final String paramValue = binding.substring(paramStopIndex + 1);
+            if (!ret.containsKey(capabilityName)) {
+                ret.put(capabilityName, new ArrayMap<>(1));
+            }
+            final Map<String, List<String>> params = ret.get(capabilityName);
+            if (!params.containsKey(paramName)) {
+                params.put(paramName, new ArrayList<>(1));
+            }
+            params.get(paramName).add(paramValue);
+        });
+        return ret;
+    }
 }
diff --git a/core/java/android/content/pm/AppSearchPerson.java b/core/java/android/content/pm/AppSearchShortcutPerson.java
similarity index 63%
rename from core/java/android/content/pm/AppSearchPerson.java
rename to core/java/android/content/pm/AppSearchShortcutPerson.java
index 98d150b..ff8a3b6 100644
--- a/core/java/android/content/pm/AppSearchPerson.java
+++ b/core/java/android/content/pm/AppSearchShortcutPerson.java
@@ -21,28 +21,38 @@
 import android.app.Person;
 import android.app.appsearch.AppSearchSchema;
 import android.app.appsearch.GenericDocument;
+import android.graphics.drawable.Icon;
 import android.net.UriCodec;
 
 import com.android.internal.annotations.VisibleForTesting;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.util.Objects;
 import java.util.UUID;
 
 /**
+ * A {@link GenericDocument} representation of {@link Person} object.
+ *
  * @hide
  */
-public class AppSearchPerson extends GenericDocument {
+public class AppSearchShortcutPerson extends GenericDocument {
 
-    /** The name of the schema type for {@link Person} documents.*/
-    public static final String SCHEMA_TYPE = "Person";
+    /**
+     * The name of the schema type for {@link Person} documents.
+     * @hide
+     */
+    public static final String SCHEMA_TYPE = "ShortcutPerson";
 
-    public static final String KEY_NAME = "name";
-    public static final String KEY_KEY = "key";
-    public static final String KEY_IS_BOT = "isBot";
-    public static final String KEY_IS_IMPORTANT = "isImportant";
+    private static final String KEY_NAME = "name";
+    private static final String KEY_KEY = "key";
+    private static final String KEY_IS_BOT = "isBot";
+    private static final String KEY_IS_IMPORTANT = "isImportant";
+    private static final String KEY_ICON = "icon";
 
-    public AppSearchPerson(@NonNull GenericDocument document) {
+    public AppSearchShortcutPerson(@NonNull GenericDocument document) {
         super(document);
     }
 
@@ -67,11 +77,15 @@
                     .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_REQUIRED)
                     .build()
 
+            ).addProperty(new AppSearchSchema.BytesPropertyConfig.Builder(KEY_ICON)
+                    .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
+                    .build()
+
             ).build();
 
-    /** hide */
+    /** @hide */
     @NonNull
-    public static AppSearchPerson instance(@NonNull final Person person) {
+    public static AppSearchShortcutPerson instance(@NonNull final Person person) {
         Objects.requireNonNull(person);
         final String id;
         if (person.getUri() != null) {
@@ -82,10 +96,13 @@
         }
         return new Builder(id).setName(person.getName())
                 .setKey(person.getKey()).setIsBot(person.isBot())
-                .setIsImportant(person.isImportant()).build();
+                .setIsImportant(person.isImportant())
+                .setIcon(transformToByteArray(person.getIcon())).build();
     }
 
-    /** hide */
+    /**
+     * Convert this {@link GenericDocument} into {@link Person}.
+     */
     @NonNull
     public Person toPerson() {
         String uri;
@@ -99,7 +116,9 @@
         return new Person.Builder().setName(getPropertyString(KEY_NAME))
                 .setUri(uri).setKey(getPropertyString(KEY_KEY))
                 .setBot(getPropertyBoolean(KEY_IS_BOT))
-                .setImportant(getPropertyBoolean(KEY_IS_IMPORTANT)).build();
+                .setImportant(getPropertyBoolean(KEY_IS_IMPORTANT))
+                .setIcon(transformToIcon(getPropertyBytes(KEY_ICON)))
+                .build();
     }
 
     /** @hide */
@@ -142,10 +161,51 @@
             return this;
         }
 
+        /** @hide */
+        @NonNull
+        public Builder setIcon(@Nullable final byte[] icon) {
+            if (icon != null) {
+                setPropertyBytes(KEY_ICON, icon);
+            }
+            return this;
+        }
+
+        /** @hide */
         @NonNull
         @Override
-        public AppSearchPerson build() {
-            return new AppSearchPerson(super.build());
+        public AppSearchShortcutPerson build() {
+            return new AppSearchShortcutPerson(super.build());
+        }
+    }
+
+    /**
+     * Convert {@link Icon} into byte[].
+     */
+    @Nullable
+    private static byte[] transformToByteArray(@Nullable final Icon icon) {
+        if (icon == null) {
+            return null;
+        }
+        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+            icon.writeToStream(baos);
+            return baos.toByteArray();
+        } catch (IOException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Convert byte[] into {@link Icon}.
+     */
+    @Nullable
+    private Icon transformToIcon(@Nullable final byte[] icon) {
+        if (icon == null) {
+            return null;
+        }
+        try (ByteArrayInputStream bais = new ByteArrayInputStream(icon)) {
+            return Icon.createFromStream(bais);
+        } catch (IOException e) {
+            return null;
         }
     }
 }
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index ab827aa..41dd5bb3 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -24,6 +24,7 @@
 import android.app.Notification;
 import android.app.Person;
 import android.app.TaskStackBuilder;
+import android.app.appsearch.GenericDocument;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
@@ -656,6 +657,28 @@
     }
 
     /**
+     * Convert a {@link GenericDocument} into a ShortcutInfo.
+     *
+     * @param context Client context
+     * @param document An instance of {@link GenericDocument} that represents the shortcut.
+     */
+    @NonNull
+    public static ShortcutInfo createFromGenericDocument(@NonNull final Context context,
+            @NonNull final GenericDocument document) {
+        Objects.requireNonNull(context);
+        Objects.requireNonNull(document);
+        return createFromGenericDocument(context.getUserId(), document);
+    }
+
+    /**
+     * @hide
+     */
+    public static ShortcutInfo createFromGenericDocument(
+            final int userId, @NonNull final GenericDocument document) {
+        return new AppSearchShortcutInfo(document).toShortcutInfo(userId);
+    }
+
+    /**
      * Load a string resource from the publisher app.
      *
      * @param resId resource ID
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl
index 459dab1..b617e05 100644
--- a/core/java/android/hardware/usb/IUsbManager.aidl
+++ b/core/java/android/hardware/usb/IUsbManager.aidl
@@ -136,6 +136,9 @@
     /* Resets the USB gadget. */
     void resetUsbGadget();
 
+    /* Resets the USB port. */
+    boolean resetUsbPort(in String portId, int operationId, in IUsbOperationInternal callback);
+
     /* Set USB data on or off */
     boolean enableUsbData(in String portId, boolean enable, int operationId, in IUsbOperationInternal callback);
 
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index f0e040e..60f5135 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -1324,6 +1324,43 @@
     }
 
     /**
+     * Should only be called by {@link UsbPort#resetUsbPort}.
+     * <p>
+     * Disable and then re-enable USB data signaling.
+     *
+     * Reset USB first port..
+     * It will force to stop and restart USB data signaling.
+     * Call UsbPort API if the device has more than one UsbPort.
+     * </p>
+     *
+     * @param port reset the USB Port
+     * @return true enable or disable USB data successfully
+     *         false if something wrong
+     *
+     * Should only be called by {@link UsbPort#resetUsbPort}.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.MANAGE_USB)
+    boolean resetUsbPort(@NonNull UsbPort port, int operationId,
+            IUsbOperationInternal callback) {
+        Objects.requireNonNull(port, "resetUsbPort: port must not be null. opId:" + operationId);
+        try {
+            return mService.resetUsbPort(port.getId(), operationId, callback);
+        } catch (RemoteException e) {
+            Log.e(TAG, "resetUsbPort: failed. ", e);
+            try {
+                callback.onOperationComplete(UsbOperationInternal.USB_OPERATION_ERROR_INTERNAL);
+            } catch (RemoteException r) {
+                Log.e(TAG, "resetUsbPort: failed to call onOperationComplete. opId:"
+                        + operationId, r);
+            }
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Should only be called by {@link UsbPort#enableUsbData}.
      * <p>
      * Enables or disables USB data on the specific port.
diff --git a/core/java/android/hardware/usb/UsbPort.java b/core/java/android/hardware/usb/UsbPort.java
index bef4dea..a979725 100644
--- a/core/java/android/hardware/usb/UsbPort.java
+++ b/core/java/android/hardware/usb/UsbPort.java
@@ -128,6 +128,9 @@
     @Retention(RetentionPolicy.SOURCE)
     @interface EnableUsbDataStatus{}
 
+    @Retention(RetentionPolicy.SOURCE)
+    @interface ResetUsbPortStatus{}
+
     /**
      * The {@link #enableLimitPowerTransfer} request was successfully completed.
      */
@@ -319,6 +322,43 @@
     }
 
     /**
+     * Reset Usb data on the port.
+     *
+     * @return       {@link #ENABLE_USB_DATA_SUCCESS} when request completes successfully or
+     *               {@link #ENABLE_USB_DATA_ERROR_INTERNAL} when request fails due to internal
+     *               error or
+     *               {@link ENABLE_USB_DATA_ERROR_NOT_SUPPORTED} when not supported or
+     *               {@link ENABLE_USB_DATA_ERROR_PORT_MISMATCH} when request fails due to port id
+     *               mismatch or
+     *               {@link ENABLE_USB_DATA_ERROR_OTHER} when fails due to other reasons.
+     */
+    @CheckResult
+    @RequiresPermission(Manifest.permission.MANAGE_USB)
+    public @ResetUsbPortStatus int resetUsbPort() {
+        // UID is added To minimize operationID overlap between two different packages.
+        int operationId = sUsbOperationCount.incrementAndGet() + Binder.getCallingUid();
+        Log.i(TAG, "resetUsbData opId:" + operationId);
+        UsbOperationInternal opCallback =
+                new UsbOperationInternal(operationId, mId);
+        if (mUsbManager.resetUsbPort(this, operationId, opCallback) == true) {
+            opCallback.waitForOperationComplete();
+        }
+        int result = opCallback.getStatus();
+        switch (result) {
+            case USB_OPERATION_SUCCESS:
+                return ENABLE_USB_DATA_SUCCESS;
+            case USB_OPERATION_ERROR_INTERNAL:
+                return ENABLE_USB_DATA_ERROR_INTERNAL;
+            case USB_OPERATION_ERROR_NOT_SUPPORTED:
+                return ENABLE_USB_DATA_ERROR_NOT_SUPPORTED;
+            case USB_OPERATION_ERROR_PORT_MISMATCH:
+                return ENABLE_USB_DATA_ERROR_PORT_MISMATCH;
+            default:
+                return ENABLE_USB_DATA_ERROR_OTHER;
+        }
+    }
+
+    /**
      * Enables/Disables Usb data on the port.
      *
      * @param enable When true enables USB data if disabled.
diff --git a/core/java/android/inputmethodservice/AbstractInputMethodService.java b/core/java/android/inputmethodservice/AbstractInputMethodService.java
index 75beacf..f16e243 100644
--- a/core/java/android/inputmethodservice/AbstractInputMethodService.java
+++ b/core/java/android/inputmethodservice/AbstractInputMethodService.java
@@ -300,13 +300,6 @@
         return false;
     }
 
-    // TODO(b/149463653): remove it in T. We missed the API deadline in S.
-    /** @hide */
-    @Override
-    public final boolean isUiContext() {
-        return true;
-    }
-
     /** @hide */
     @Override
     public final int getWindowType() {
diff --git a/core/java/android/nfc/INfcTag.aidl b/core/java/android/nfc/INfcTag.aidl
index 539fd4a..e1ccc4f 100644
--- a/core/java/android/nfc/INfcTag.aidl
+++ b/core/java/android/nfc/INfcTag.aidl
@@ -45,4 +45,7 @@
     boolean canMakeReadOnly(int ndefType);
     int getMaxTransceiveLength(int technology);
     boolean getExtendedLengthApdusSupported();
+
+    void setTagUpToDate(long cookie);
+    boolean isTagUpToDate(long cookie);
 }
diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java
index 398ec63a..0ce9c70 100644
--- a/core/java/android/nfc/Tag.java
+++ b/core/java/android/nfc/Tag.java
@@ -34,6 +34,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.RemoteException;
+import android.os.SystemClock;
 
 import java.io.IOException;
 import java.util.Arrays;
@@ -121,6 +122,7 @@
     final INfcTag mTagService; // interface to NFC service, will be null if mock tag
 
     int mConnectedTechnology;
+    long mCookie;
 
     /**
      * Hidden constructor to be used by NFC service and internal classes.
@@ -140,6 +142,13 @@
         mTagService = tagService;
 
         mConnectedTechnology = -1;
+
+        try {
+            mCookie = SystemClock.elapsedRealtime();
+            tagService.setTagUpToDate(mCookie);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
     }
 
     /**
@@ -361,6 +370,18 @@
     /** @hide */
     @UnsupportedAppUsage
     public INfcTag getTagService() {
+        try {
+            if (!mTagService.isTagUpToDate(mCookie)) {
+                String id_str = "";
+                for (int i = 0; i < mId.length; i++) {
+                    id_str = id_str + String.format("%02X ", mId[i]);
+                }
+                String msg = "Permission Denial: Tag ( ID: " + id_str + ") is out of date";
+                throw new SecurityException(msg);
+            }
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
         return mTagService;
     }
 
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 6d4593a..76f857b 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -187,10 +187,13 @@
     public static final int BATTERY_PLUGGED_USB = OsProtoEnums.BATTERY_PLUGGED_USB; // = 2
     /** Power source is wireless. */
     public static final int BATTERY_PLUGGED_WIRELESS = OsProtoEnums.BATTERY_PLUGGED_WIRELESS; // = 4
+    /** Power source is dock. */
+    public static final int BATTERY_PLUGGED_DOCK = OsProtoEnums.BATTERY_PLUGGED_DOCK; // = 8
 
     /** @hide */
     public static final int BATTERY_PLUGGED_ANY =
-            BATTERY_PLUGGED_AC | BATTERY_PLUGGED_USB | BATTERY_PLUGGED_WIRELESS;
+            BATTERY_PLUGGED_AC | BATTERY_PLUGGED_USB | BATTERY_PLUGGED_WIRELESS
+                    | BATTERY_PLUGGED_DOCK;
 
     /**
      * Sent when the device's battery has started charging (or has reached full charge
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 1810904..b754598 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -704,6 +704,21 @@
         public long wakeTime;
         public @WakeReason int wakeReason;
         public long sleepDuration;
+
+        @Override
+        public boolean equals(@Nullable Object o) {
+            if (o instanceof WakeData) {
+                final WakeData other = (WakeData) o;
+                return wakeTime == other.wakeTime && wakeReason == other.wakeReason
+                        && sleepDuration == other.sleepDuration;
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(wakeTime, wakeReason, sleepDuration);
+        }
     }
 
     /**
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index ae37a71..f490587 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -21,7 +21,6 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.SuppressLint;
 import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ContentResolver;
@@ -40,6 +39,7 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.time.Duration;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -196,20 +196,20 @@
     /**
      * Create a waveform vibration.
      *
-     * Waveform vibrations are a potentially repeating series of timing and amplitude pairs. For
+     * <p>Waveform vibrations are a potentially repeating series of timing and amplitude pairs. For
      * each pair, the value in the amplitude array determines the strength of the vibration and the
      * value in the timing array determines how long it vibrates for. An amplitude of 0 implies no
      * vibration (i.e. off), and any pairs with a timing value of 0 will be ignored.
-     * <p>
-     * The amplitude array of the generated waveform will be the same size as the given
+     *
+     * <p>The amplitude array of the generated waveform will be the same size as the given
      * timing array with alternating values of 0 (i.e. off) and {@link #DEFAULT_AMPLITUDE},
      * starting with 0. Therefore the first timing value will be the period to wait before turning
      * the vibrator on, the second value will be how long to vibrate at {@link #DEFAULT_AMPLITUDE}
      * strength, etc.
-     * </p><p>
-     * To cause the pattern to repeat, pass the index into the timings array at which to start the
-     * repetition, or -1 to disable repeating.
-     * </p>
+     *
+     * <p>To cause the pattern to repeat, pass the index into the timings array at which to start
+     * the repetition, or -1 to disable repeating. Repeating effects will be played indefinitely
+     * and should be cancelled via {@link Vibrator#cancel()}.
      *
      * @param timings The pattern of alternating on-off timings, starting with off. Timing values
      *                of 0 will cause the timing / amplitude pair to be ignored.
@@ -229,15 +229,15 @@
     /**
      * Create a waveform vibration.
      *
-     * Waveform vibrations are a potentially repeating series of timing and amplitude pairs. For
+     * <p>Waveform vibrations are a potentially repeating series of timing and amplitude pairs. For
      * each pair, the value in the amplitude array determines the strength of the vibration and the
      * value in the timing array determines how long it vibrates for, in milliseconds. Amplitude
      * values must be between 0 and 255, and an amplitude of 0 implies no vibration (i.e. off). Any
      * pairs with a timing value of 0 will be ignored.
-     * </p><p>
-     * To cause the pattern to repeat, pass the index into the timings array at which to start the
-     * repetition, or -1 to disable repeating.
-     * </p>
+     *
+     * <p>To cause the pattern to repeat, pass the index into the timings array at which to start
+     * the repetition, or -1 to disable repeating. Repeating effects will be played indefinitely
+     * and should be cancelled via {@link Vibrator#cancel()}.
      *
      * @param timings The timing values, in milliseconds, of the timing / amplitude pairs. Timing
      *                values of 0 will cause the pair to be ignored.
@@ -407,20 +407,59 @@
      * Start building a waveform vibration.
      *
      * <p>The waveform builder offers more flexibility for creating waveform vibrations, allowing
-     * control over vibration frequency and ramping up or down the vibration amplitude, frequency or
-     * both.
+     * control over vibration amplitude and frequency via smooth transitions between values.
      *
-     * <p>For simpler waveform patterns see {@link #createWaveform} methods.
+     * <p>The waveform will start the first transition from the vibrator off state, with the
+     * resonant frequency by default. To provide an initial state, use
+     * {@link #startWaveform(VibrationParameter)}.
      *
-     * @hide
-     * @see VibrationEffect.WaveformBuilder
+     * @return The {@link VibrationEffect.WaveformBuilder} started with the initial parameters.
      */
-    @TestApi
     @NonNull
     public static WaveformBuilder startWaveform() {
         return new WaveformBuilder();
     }
 
+    /**
+     * Start building a waveform vibration with an initial state specified by a
+     * {@link VibrationParameter}.
+     *
+     * <p>The waveform builder offers more flexibility for creating waveform vibrations, allowing
+     * control over vibration amplitude and frequency via smooth transitions between values.
+     *
+     * @param initialParameter The initial {@link VibrationParameter} value to be applied at the
+     *                         beginning of the vibration.
+     * @return The {@link VibrationEffect.WaveformBuilder} started with the initial parameters.
+     */
+    @NonNull
+    public static WaveformBuilder startWaveform(@NonNull VibrationParameter initialParameter) {
+        WaveformBuilder builder = startWaveform();
+        builder.addTransition(Duration.ZERO, initialParameter);
+        return builder;
+    }
+
+    /**
+     * Start building a waveform vibration with an initial state specified by two
+     * {@link VibrationParameter VibrationParameters}.
+     *
+     * <p>The waveform builder offers more flexibility for creating waveform vibrations, allowing
+     * control over vibration amplitude and frequency via smooth transitions between values.
+     *
+     * @param initialParameter1 The initial {@link VibrationParameter} value to be applied at the
+     *                          beginning of the vibration.
+     * @param initialParameter2 The initial {@link VibrationParameter} value to be applied at the
+     *                          beginning of the vibration, must be a different type of parameter
+     *                          than the one specified by the first argument.
+     * @return The {@link VibrationEffect.WaveformBuilder} started with the initial parameters.
+     */
+    @NonNull
+    public static WaveformBuilder startWaveform(@NonNull VibrationParameter initialParameter1,
+            @NonNull VibrationParameter initialParameter2) {
+        WaveformBuilder builder = startWaveform();
+        builder.addTransition(Duration.ZERO, initialParameter1, initialParameter2);
+        return builder;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -784,10 +823,23 @@
                 PRIMITIVE_LOW_TICK,
         })
         @Retention(RetentionPolicy.SOURCE)
-        public @interface PrimitiveType {}
+        public @interface PrimitiveType {
+        }
+
+        /**
+         * Exception thrown when adding an element to a {@link Composition} that already ends in an
+         * indefinitely repeating effect.
+         */
+        public static final class UnreachableAfterRepeatingIndefinitelyException
+                extends IllegalStateException {
+            UnreachableAfterRepeatingIndefinitelyException() {
+                super("Compositions ending in an indefinitely repeating effect can't be extended");
+            }
+        }
 
         /**
          * No haptic effect. Used to generate extended delays between primitives.
+         *
          * @hide
          */
         public static final int PRIMITIVE_NOOP = 0;
@@ -837,50 +889,87 @@
         Composition() {}
 
         /**
-         * Add a haptic effect to the end of the current composition.
+         * Adds a time duration to the current composition, during which the vibrator will be
+         * turned off
          *
-         * <p>Similar to {@link #addEffect(VibrationEffect, int)} , but with no delay applied.
+         * @param duration The length of time the vibrator should be off. Value must be non-negative
+         *                 and will be truncated to milliseconds.
+         * @return This {@link Composition} object to enable adding multiple elements in one chain.
          *
-         * @param effect The effect to add to this composition as a primitive
-         * @return The {@link Composition} object to enable adding multiple primitives in one chain.
-         * @hide
+         * @throws UnreachableAfterRepeatingIndefinitelyException if the composition is currently
+         * ending with a repeating effect.
          */
-        @TestApi
         @NonNull
-        public Composition addEffect(@NonNull VibrationEffect effect) {
-            return addEffect(effect, /* delay= */ 0);
+        public Composition addOffDuration(@NonNull Duration duration) {
+            int durationMs = (int) duration.toMillis();
+            Preconditions.checkArgumentNonnegative(durationMs, "Off period must be non-negative");
+            if (durationMs > 0) {
+                // Created a segment sustaining the zero amplitude to represent the delay.
+                addSegment(new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0,
+                        (int) duration.toMillis()));
+            }
+            return this;
         }
 
         /**
          * Add a haptic effect to the end of the current composition.
          *
-         * @param effect The effect to add to this composition as a primitive
-         * @param delay  The amount of time in milliseconds to wait before playing this primitive
-         * @return The {@link Composition} object to enable adding multiple primitives in one chain.
-         * @hide
+         * <p>If this effect is repeating (e.g. created by {@link VibrationEffect#createWaveform}
+         * with a non-negative repeat index, or created by another composition that has effects
+         * repeating indefinitely), then no more effects or primitives will be accepted by this
+         * composition after this method. Such effects should be cancelled via
+         * {@link Vibrator#cancel()}.
+         *
+         * @param effect The effect to add to the end of this composition.
+         * @return This {@link Composition} object to enable adding multiple elements in one chain.
+         *
+         * @throws UnreachableAfterRepeatingIndefinitelyException if the composition is currently
+         * ending with a repeating effect.
          */
-        @TestApi
         @NonNull
-        public Composition addEffect(@NonNull VibrationEffect effect,
-                @IntRange(from = 0) int delay) {
-            Preconditions.checkArgumentNonnegative(delay);
-            if (delay > 0) {
-                // Created a segment sustaining the zero amplitude to represent the delay.
-                addSegment(new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0,
-                        /* duration= */ delay));
-            }
+        public Composition addEffect(@NonNull VibrationEffect effect) {
             return addSegments(effect);
         }
 
         /**
+         * Add a haptic effect to the end of the current composition and play it on repeat,
+         * indefinitely.
+         *
+         * <p>The entire effect will be played on repeat, indefinitely, after all other elements
+         * already added to this composition are played. No more effects or primitives will be
+         * accepted by this composition after this method. Such effects should be cancelled via
+         * {@link Vibrator#cancel()}.
+         *
+         * @param effect The effect to add to the end of this composition, must be finite.
+         * @return This {@link Composition} object to enable adding multiple elements in one chain,
+         * although only {@link #compose()} can follow this call.
+         *
+         * @throws IllegalArgumentException if the given effect is already repeating indefinitely.
+         * @throws UnreachableAfterRepeatingIndefinitelyException if the composition is currently
+         * ending with a repeating effect.
+         */
+        @NonNull
+        public Composition repeatEffectIndefinitely(@NonNull VibrationEffect effect) {
+            Preconditions.checkArgument(effect.getDuration() < Long.MAX_VALUE,
+                    "Can't repeat an indefinitely repeating effect. Consider addEffect instead.");
+            int previousSegmentCount = mSegments.size();
+            addSegments(effect);
+            // Set repeat after segments were added, since addSegments checks this index.
+            mRepeatIndex = previousSegmentCount;
+            return this;
+        }
+
+        /**
          * Add a haptic primitive to the end of the current composition.
          *
          * Similar to {@link #addPrimitive(int, float, int)}, but with no delay and a
          * default scale applied.
          *
          * @param primitiveId The primitive to add
+         * @return This {@link Composition} object to enable adding multiple elements in one chain.
          *
-         * @return The {@link Composition} object to enable adding multiple primitives in one chain.
+         * @throws UnreachableAfterRepeatingIndefinitelyException if the composition is currently
+         * ending with a repeating effect.
          */
         @NonNull
         public Composition addPrimitive(@PrimitiveType int primitiveId) {
@@ -894,8 +983,10 @@
          *
          * @param primitiveId The primitive to add
          * @param scale The scale to apply to the intensity of the primitive.
+         * @return This {@link Composition} object to enable adding multiple elements in one chain.
          *
-         * @return The {@link Composition} object to enable adding multiple primitives in one chain.
+         * @throws UnreachableAfterRepeatingIndefinitelyException if the composition is currently
+         * ending with a repeating effect.
          */
         @NonNull
         public Composition addPrimitive(@PrimitiveType int primitiveId,
@@ -910,7 +1001,10 @@
          * @param scale The scale to apply to the intensity of the primitive.
          * @param delay The amount of time in milliseconds to wait before playing this primitive,
          *              starting at the time the previous element in this composition is finished.
-         * @return The {@link Composition} object to enable adding multiple primitives in one chain.
+         * @return This {@link Composition} object to enable adding multiple elements in one chain.
+         *
+         * @throws UnreachableAfterRepeatingIndefinitelyException if the composition is currently
+         * ending with a repeating effect.
          */
         @NonNull
         public Composition addPrimitive(@PrimitiveType int primitiveId,
@@ -923,9 +1017,7 @@
 
         private Composition addSegment(VibrationEffectSegment segment) {
             if (mRepeatIndex >= 0) {
-                throw new IllegalStateException(
-                        "Composition already have a repeating effect so any new primitive would be"
-                                + " unreachable.");
+                throw new UnreachableAfterRepeatingIndefinitelyException();
             }
             mSegments.add(segment);
             return this;
@@ -933,9 +1025,7 @@
 
         private Composition addSegments(VibrationEffect effect) {
             if (mRepeatIndex >= 0) {
-                throw new IllegalStateException(
-                        "Composition already have a repeating effect so any new primitive would be"
-                                + " unreachable.");
+                throw new UnreachableAfterRepeatingIndefinitelyException();
             }
             Composed composed = (Composed) effect;
             if (composed.getRepeatIndex() >= 0) {
@@ -1001,162 +1091,251 @@
     /**
      * A builder for waveform haptic effects.
      *
-     * <p>Waveform vibrations constitute of one or more timed segments where the vibration
-     * amplitude, frequency or both can linearly ramp to new values.
+     * <p>Waveform vibrations constitute of one or more timed transitions to new sets of vibration
+     * parameters. These parameters can be the vibration amplitude or frequency, for example.
      *
-     * <p>Waveform segments may have zero duration, which represent a jump to new vibration
-     * amplitude and/or frequency values.
+     * <p>Note that physical vibration actuators have different reaction times for changing
+     * amplitude and frequency. Durations specified here represent a timeline for the target
+     * parameters, and quality of effects may be improved if the durations allow time for a
+     * transition to be smoothly applied.
      *
-     * <p>Waveform segments may have the same start and end vibration amplitude and frequency,
-     * which represent a step where the amplitude and frequency are maintained for that duration.
+     * <p>Repeating waveforms can be built by constructing the repeating block separately and adding
+     * it to the end of a composition using
+     * {@link Composition#repeatEffectIndefinitely(VibrationEffect)}.
      *
-     * @hide
-     * @see VibrationEffect#startWaveform()
+     * @see VibrationEffect#startWaveform
      */
-    @TestApi
     public static final class WaveformBuilder {
+        // Epsilon used for float comparison of amplitude and frequency values on transitions.
+        private static final float EPSILON = 1e-5f;
+
         private ArrayList<VibrationEffectSegment> mSegments = new ArrayList<>();
+        private float mLastAmplitude = 0f;
+        private float mLastFrequencyHz = 0f;
 
         WaveformBuilder() {}
 
         /**
-         * Vibrate with given amplitude for the given duration, in millis, keeping the previous
-         * frequency the same.
+         * Add a transition to new vibration parameter value to the end of this waveform.
          *
-         * <p>If the duration is zero the vibrator will jump to new amplitude.
+         * <p>The duration represents how long the vibrator should take to smoothly transition to
+         * the new vibration parameter. If the duration is zero then the vibrator will jump to the
+         * new value as fast as possible.
          *
-         * @param amplitude The amplitude for this step
-         * @param duration  The duration of this step in milliseconds
-         * @return The {@link WaveformBuilder} object to enable adding multiple steps in chain.
+         * <p>Vibration parameter values will be truncated to conform to the device capabilities
+         * according to the {@link android.os.vibrator.VibratorFrequencyProfile}.
+         *
+         * @param duration        The length of time this transition should take. Value must be
+         *                        non-negative and will be truncated to milliseconds.
+         * @param targetParameter The new target {@link VibrationParameter} value to be reached
+         *                        after the given duration.
+         * @return This {@link WaveformBuilder} object to enable adding multiple transitions in
+         * chain.
          */
-        @SuppressLint("MissingGetterMatchingBuilder")
+        @SuppressWarnings("MissingGetterMatchingBuilder") // No getters to segments once created.
         @NonNull
-        public WaveformBuilder addStep(@FloatRange(from = 0f, to = 1f) float amplitude,
-                @IntRange(from = 0) int duration) {
-            mSegments.add(new StepSegment(amplitude, getPreviousFrequencyHz(), duration));
+        public WaveformBuilder addTransition(@NonNull Duration duration,
+                @NonNull VibrationParameter targetParameter) {
+            Preconditions.checkNotNull(duration, "Duration is null");
+            checkVibrationParameter(targetParameter, "targetParameter");
+            float amplitude = extractTargetAmplitude(targetParameter, /* target2= */ null);
+            float frequencyHz = extractTargetFrequency(targetParameter, /* target2= */ null);
+            addTransitionSegment(duration, amplitude, frequencyHz);
             return this;
         }
 
         /**
-         * Vibrate with given amplitude and frequency for the given duration, in millis.
+         * Add a transition to new vibration parameters to the end of this waveform.
          *
-         * <p>If the duration is zero the vibrator will jump to new amplitude.
+         * <p>The duration represents how long the vibrator should take to smoothly transition to
+         * the new vibration parameters. If the duration is zero then the vibrator will jump to the
+         * new values as fast as possible.
          *
-         * @param amplitude The amplitude for this step
-         * @param frequencyHz The frequency for this step, in hertz
-         * @param duration  The duration of this step in milliseconds
-         * @return The {@link WaveformBuilder} object to enable adding multiple steps in chain.
+         * <p>Vibration parameters values will be truncated to conform to the device capabilities
+         * according to the {@link android.os.vibrator.VibratorFrequencyProfile}.
+         *
+         * @param duration         The length of time this transition should take. Value must be
+         *                         non-negative and will be truncated to milliseconds.
+         * @param targetParameter1 The first target {@link VibrationParameter} value to be reached
+         *                         after the given duration.
+         * @param targetParameter2 The second target {@link VibrationParameter} value to be reached
+         *                         after the given duration, must be a different type of parameter
+         *                         than the one specified by the first argument.
+         * @return This {@link WaveformBuilder} object to enable adding multiple transitions in
+         * chain.
          */
-        @SuppressLint("MissingGetterMatchingBuilder")
+        @SuppressWarnings("MissingGetterMatchingBuilder") // No getters to segments once created.
         @NonNull
-        public WaveformBuilder addStep(@FloatRange(from = 0f, to = 1f) float amplitude,
-                @FloatRange(from = 1f) float frequencyHz,
-                @IntRange(from = 0) int duration) {
-            Preconditions.checkArgument(frequencyHz >= 1, "Frequency must be >= 1");
-            mSegments.add(new StepSegment(amplitude, frequencyHz, duration));
+        public WaveformBuilder addTransition(@NonNull Duration duration,
+                @NonNull VibrationParameter targetParameter1,
+                @NonNull VibrationParameter targetParameter2) {
+            Preconditions.checkNotNull(duration, "Duration is null");
+            checkVibrationParameter(targetParameter1, "targetParameter1");
+            checkVibrationParameter(targetParameter2, "targetParameter2");
+            Preconditions.checkArgument(
+                    !Objects.equals(targetParameter1.getClass(), targetParameter2.getClass()),
+                    "Parameter arguments must specify different parameter types");
+            float amplitude = extractTargetAmplitude(targetParameter1, targetParameter2);
+            float frequencyHz = extractTargetFrequency(targetParameter1, targetParameter2);
+            addTransitionSegment(duration, amplitude, frequencyHz);
             return this;
         }
 
         /**
-         * Ramp vibration linearly for the given duration, in millis, from previous amplitude value
-         * to the given one, keeping previous frequency.
+         * Add a duration to sustain the last vibration parameters of this waveform.
          *
-         * <p>If the duration is zero the vibrator will jump to new amplitude.
+         * <p>The duration represents how long the vibrator should sustain the last set of
+         * parameters provided to this builder.
          *
-         * @param amplitude The final amplitude this ramp should reach
-         * @param duration  The duration of this ramp in milliseconds
-         * @return The {@link WaveformBuilder} object to enable adding multiple steps in chain.
+         * @param duration   The length of time the last values should be sustained by the vibrator.
+         *                   Value must be >= 1ms.
+         * @return This {@link WaveformBuilder} object to enable adding multiple transitions in
+         * chain.
          */
-        @SuppressLint("MissingGetterMatchingBuilder")
+        @SuppressWarnings("MissingGetterMatchingBuilder") // No getters to segments once created.
         @NonNull
-        public WaveformBuilder addRamp(@FloatRange(from = 0f, to = 1f) float amplitude,
-                @IntRange(from = 0) int duration) {
-            mSegments.add(new RampSegment(getPreviousAmplitude(), amplitude,
-                    getPreviousFrequencyHz(), getPreviousFrequencyHz(), duration));
+        public WaveformBuilder addSustain(@NonNull Duration duration) {
+            int durationMs = (int) duration.toMillis();
+            Preconditions.checkArgument(durationMs >= 1, "Sustain duration must be >= 1ms");
+            mSegments.add(new StepSegment(mLastAmplitude, mLastFrequencyHz, durationMs));
             return this;
         }
 
         /**
-         * Ramp vibration linearly for the given duration, in millis, from previous amplitude and
-         * frequency values to the given ones.
-         *
-         * <p>If the duration is zero the vibrator will jump to new amplitude and frequency.
-         *
-         * @param amplitude The final amplitude this ramp should reach
-         * @param frequencyHz The final frequency this ramp should reach, in hertz
-         * @param duration  The duration of this ramp in milliseconds
-         * @return The {@link WaveformBuilder} object to enable adding multiple steps in chain.
-         */
-        @SuppressLint("MissingGetterMatchingBuilder")
-        @NonNull
-        public WaveformBuilder addRamp(@FloatRange(from = 0f, to = 1f) float amplitude,
-                @FloatRange(from = 1f) float frequencyHz,
-                @IntRange(from = 0) int duration) {
-            Preconditions.checkArgument(frequencyHz >= 1, "Frequency must be >= 1");
-            mSegments.add(new RampSegment(getPreviousAmplitude(), amplitude,
-                    getPreviousFrequencyHz(), frequencyHz, duration));
-            return this;
-        }
-
-        /**
-         * Compose all the steps together into a single {@link VibrationEffect}.
+         * Build the waveform as a single {@link VibrationEffect}.
          *
          * The {@link WaveformBuilder} object is still valid after this call, so you can
          * continue adding more primitives to it and generating more {@link VibrationEffect}s by
          * calling this method again.
          *
-         * @return The {@link VibrationEffect} resulting from the composition of the steps.
+         * @return The {@link VibrationEffect} resulting from the list of transitions.
          */
         @NonNull
         public VibrationEffect build() {
-            return build(/* repeat= */ -1);
-        }
-
-        /**
-         * Compose all the steps together into a single {@link VibrationEffect}.
-         *
-         * <p>To cause the pattern to repeat, pass the index at which to start the repetition
-         * (starting at 0), or -1 to disable repeating.
-         *
-         * <p>The {@link WaveformBuilder} object is still valid after this call, so you can
-         * continue adding more primitives to it and generating more {@link VibrationEffect}s by
-         * calling this method again.
-         *
-         * @return The {@link VibrationEffect} resulting from the composition of the steps.
-         */
-        @NonNull
-        public VibrationEffect build(int repeat) {
             if (mSegments.isEmpty()) {
                 throw new IllegalStateException(
-                        "WaveformBuilder must have at least one element to build.");
+                        "WaveformBuilder must have at least one transition to build.");
             }
-            VibrationEffect effect = new Composed(mSegments, repeat);
+            VibrationEffect effect = new Composed(mSegments, /* repeatIndex= */ -1);
             effect.validate();
             return effect;
         }
 
-        private float getPreviousFrequencyHz() {
-            if (!mSegments.isEmpty()) {
-                VibrationEffectSegment segment = mSegments.get(mSegments.size() - 1);
-                if (segment instanceof StepSegment) {
-                    return ((StepSegment) segment).getFrequencyHz();
-                } else if (segment instanceof RampSegment) {
-                    return ((RampSegment) segment).getEndFrequencyHz();
-                }
-            }
-            return 0;
+        private void checkVibrationParameter(@NonNull VibrationParameter vibrationParameter,
+                String paramName) {
+            Preconditions.checkNotNull(vibrationParameter, "%s is null", paramName);
+            Preconditions.checkArgument(
+                    (vibrationParameter instanceof AmplitudeVibrationParameter)
+                            || (vibrationParameter instanceof FrequencyVibrationParameter),
+                    "%s is a unknown parameter", paramName);
         }
 
-        private float getPreviousAmplitude() {
-            if (!mSegments.isEmpty()) {
-                VibrationEffectSegment segment = mSegments.get(mSegments.size() - 1);
-                if (segment instanceof StepSegment) {
-                    return ((StepSegment) segment).getAmplitude();
-                } else if (segment instanceof RampSegment) {
-                    return ((RampSegment) segment).getEndAmplitude();
+        private float extractTargetAmplitude(@Nullable VibrationParameter target1,
+                @Nullable VibrationParameter target2) {
+            if (target2 instanceof AmplitudeVibrationParameter) {
+                return ((AmplitudeVibrationParameter) target2).amplitude;
+            }
+            if (target1 instanceof AmplitudeVibrationParameter) {
+                return ((AmplitudeVibrationParameter) target1).amplitude;
+            }
+            return mLastAmplitude;
+        }
+
+        private float extractTargetFrequency(@Nullable VibrationParameter target1,
+                @Nullable VibrationParameter target2) {
+            if (target2 instanceof FrequencyVibrationParameter) {
+                return ((FrequencyVibrationParameter) target2).frequencyHz;
+            }
+            if (target1 instanceof FrequencyVibrationParameter) {
+                return ((FrequencyVibrationParameter) target1).frequencyHz;
+            }
+            return mLastFrequencyHz;
+        }
+
+        private void addTransitionSegment(Duration duration, float targetAmplitude,
+                float targetFrequency) {
+            Preconditions.checkNotNull(duration, "Duration is null");
+            Preconditions.checkArgument(!duration.isNegative(),
+                    "Transition duration must be non-negative");
+            int durationMs = (int) duration.toMillis();
+
+            // Ignore transitions with zero duration, but keep values for next additions.
+            if (durationMs > 0) {
+                if ((Math.abs(mLastAmplitude - targetAmplitude) < EPSILON)
+                        && (Math.abs(mLastFrequencyHz - targetFrequency) < EPSILON)) {
+                    // No value is changing, this can be best represented by a step segment.
+                    mSegments.add(new StepSegment(targetAmplitude, targetFrequency, durationMs));
+                } else {
+                    mSegments.add(new RampSegment(mLastAmplitude, targetAmplitude,
+                            mLastFrequencyHz, targetFrequency, durationMs));
                 }
             }
-            return 0;
+
+            mLastAmplitude = targetAmplitude;
+            mLastFrequencyHz = targetFrequency;
+        }
+    }
+
+    /**
+     * A representation of a single vibration parameter.
+     *
+     * <p>This is to describe a waveform haptic effect, which consists of one or more timed
+     * transitions to a new set of {@link VibrationParameter}s.
+     *
+     * <p>Examples of concrete parameters are the vibration amplitude or frequency.
+     *
+     * @see VibrationEffect.WaveformBuilder
+     */
+    @SuppressWarnings("UserHandleName") // This is not a regular set of parameters, no *Params.
+    public static class VibrationParameter {
+        VibrationParameter() {
+        }
+
+        /**
+         * The target vibration amplitude.
+         *
+         * @param amplitude The amplitude value, between 0 and 1, inclusive, where 0 represents the
+         *                  vibrator turned off and 1 represents the maximum amplitude the vibrator
+         *                  can reach across all supported frequencies.
+         * @return The {@link VibrationParameter} instance that represents given amplitude.
+         */
+        @NonNull
+        public static VibrationParameter targetAmplitude(
+                @FloatRange(from = 0, to = 1) float amplitude) {
+            return new AmplitudeVibrationParameter(amplitude);
+        }
+
+        /**
+         * The target vibration frequency.
+         *
+         * @param frequencyHz The frequency value, in hertz.
+         * @return The {@link VibrationParameter} instance that represents given frequency.
+         */
+        @NonNull
+        public static VibrationParameter targetFrequency(@FloatRange(from = 1) float frequencyHz) {
+            return new FrequencyVibrationParameter(frequencyHz);
+        }
+    }
+
+    /** The vibration amplitude, represented by a value in [0,1]. */
+    private static final class AmplitudeVibrationParameter extends VibrationParameter {
+        public final float amplitude;
+
+        AmplitudeVibrationParameter(float amplitude) {
+            Preconditions.checkArgument((amplitude >= 0) && (amplitude <= 1),
+                    "Amplitude must be within [0,1]");
+            this.amplitude = amplitude;
+        }
+    }
+
+    /** The vibration frequency, in hertz, or zero to represent undefined frequency. */
+    private static final class FrequencyVibrationParameter extends VibrationParameter {
+        public final float frequencyHz;
+
+        FrequencyVibrationParameter(float frequencyHz) {
+            Preconditions.checkArgument(frequencyHz >= 1, "Frequency must be >= 1");
+            Preconditions.checkArgument(Float.isFinite(frequencyHz), "Frequency must be finite");
+            this.frequencyHz = frequencyHz;
         }
     }
 
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 32054b1..ccf1e44 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -298,7 +298,7 @@
     */
     void grantInputChannel(int displayId, in SurfaceControl surface, in IWindow window,
             in IBinder hostInputToken, int flags, int privateFlags, int type,
-            in IBinder focusGrantToken, out InputChannel outInputChannel);
+            out InputChannel outInputChannel);
 
     /**
      * Update the flags on an input channel associated with a particular surface.
diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java
index 22baa69..85a9dbd 100644
--- a/core/java/android/view/SurfaceControlViewHost.java
+++ b/core/java/android/view/SurfaceControlViewHost.java
@@ -274,7 +274,7 @@
     public @Nullable SurfacePackage getSurfacePackage() {
         if (mSurfaceControl != null && mAccessibilityEmbeddedConnection != null) {
             return new SurfacePackage(mSurfaceControl, mAccessibilityEmbeddedConnection,
-                mWm.getFocusGrantToken(), mRemoteInterface);
+                mViewRoot.getInputToken(), mRemoteInterface);
         } else {
             return null;
         }
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 5ec9654..3392edc 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -21,7 +21,6 @@
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.Region;
-import android.os.Binder;
 import android.os.IBinder;
 import android.os.RemoteCallback;
 import android.os.RemoteException;
@@ -76,7 +75,6 @@
     private final Configuration mConfiguration;
     private final IWindowSession mRealWm;
     private final IBinder mHostInputToken;
-    private final IBinder mFocusGrantToken = new Binder();
 
     private int mForceHeight = -1;
     private int mForceWidth = -1;
@@ -93,10 +91,6 @@
         mConfiguration.setTo(configuration);
     }
 
-    IBinder getFocusGrantToken() {
-        return mFocusGrantToken;
-    }
-
     /**
      * Utility API.
      */
@@ -159,10 +153,10 @@
                     mRealWm.grantInputChannel(displayId,
                         new SurfaceControl(sc, "WindowlessWindowManager.addToDisplay"),
                         window, mHostInputToken, attrs.flags, attrs.privateFlags, attrs.type,
-                        mFocusGrantToken, outInputChannel);
+                        outInputChannel);
                 } else {
                     mRealWm.grantInputChannel(displayId, sc, window, mHostInputToken, attrs.flags,
-                        attrs.privateFlags, attrs.type, mFocusGrantToken, outInputChannel);
+                        attrs.privateFlags, attrs.type, outInputChannel);
                 }
             } catch (RemoteException e) {
                 Log.e(TAG, "Failed to grant input to surface: ", e);
@@ -475,7 +469,7 @@
 
     @Override
     public void grantInputChannel(int displayId, SurfaceControl surface, IWindow window,
-            IBinder hostInputToken, int flags, int privateFlags, int type, IBinder focusGrantToken,
+            IBinder hostInputToken, int flags, int privateFlags, int type,
             InputChannel outInputChannel) {
     }
 
diff --git a/core/java/android/window/SplashScreenView.java b/core/java/android/window/SplashScreenView.java
index f04155d..b90e628 100644
--- a/core/java/android/window/SplashScreenView.java
+++ b/core/java/android/window/SplashScreenView.java
@@ -151,6 +151,7 @@
         private Instant mIconAnimationStart;
         private Duration mIconAnimationDuration;
         private Consumer<Runnable> mUiThreadInitTask;
+        private boolean mAllowHandleEmpty = true;
 
         public Builder(@NonNull Context context) {
             mContext = context;
@@ -258,6 +259,15 @@
         }
 
         /**
+         * Sets whether this view can be copied and transferred to the client if the view is
+         * empty style splash screen.
+         */
+        public Builder setAllowHandleEmpty(boolean allowHandleEmpty) {
+            mAllowHandleEmpty = allowHandleEmpty;
+            return this;
+        }
+
+        /**
          * Create SplashScreenWindowView object from materials.
          */
         public SplashScreenView build() {
@@ -303,7 +313,7 @@
                 }
                 view.mIconView = imageView;
             }
-            if (mOverlayDrawable != null || mIconDrawable == null) {
+            if (mOverlayDrawable != null || (view.mIconView == null && !mAllowHandleEmpty)) {
                 view.setNotCopyable();
             }
 
@@ -720,13 +730,15 @@
         private RemoteCallback mClientCallback;
 
         public SplashScreenViewParcelable(SplashScreenView view) {
-            mIconSize = view.mIconView.getWidth();
+            final View iconView = view.getIconView();
+            mIconSize = iconView != null ? iconView.getWidth() : 0;
             mBackgroundColor = view.getInitBackgroundColor();
-            mIconBackground = copyDrawable(view.getIconView().getBackground());
+            mIconBackground = iconView != null ? copyDrawable(iconView.getBackground()) : null;
             mSurfacePackage = view.mSurfacePackageCopy;
             if (mSurfacePackage == null) {
                 // We only need to copy the drawable if we are not using a SurfaceView
-                mIconBitmap = copyDrawable(((ImageView) view.getIconView()).getDrawable());
+                mIconBitmap = iconView != null
+                        ? copyDrawable(((ImageView) view.getIconView()).getDrawable()) : null;
             }
             mBrandingBitmap = copyDrawable(view.getBrandingView().getBackground());
 
diff --git a/core/java/android/window/StartingWindowInfo.java b/core/java/android/window/StartingWindowInfo.java
index aec910b..24899a4 100644
--- a/core/java/android/window/StartingWindowInfo.java
+++ b/core/java/android/window/StartingWindowInfo.java
@@ -116,6 +116,7 @@
             TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT,
             TYPE_PARAMETER_ACTIVITY_CREATED,
             TYPE_PARAMETER_USE_EMPTY_SPLASH_SCREEN,
+            TYPE_PARAMETER_ALLOW_HANDLE_EMPTY_SCREEN,
             TYPE_PARAMETER_LEGACY_SPLASH_SCREEN
     })
     public @interface StartingTypeParams {}
@@ -141,6 +142,11 @@
      */
     public static final int TYPE_PARAMETER_ACTIVITY_DRAWN = 0x00000040;
     /**
+     * Application is allowed to handle empty splash screen.
+     * @hide
+     */
+    public static final int TYPE_PARAMETER_ALLOW_HANDLE_EMPTY_SCREEN = 0x00000080;
+    /**
      * Application is allowed to use the legacy splash screen
      * @hide
      */
@@ -185,6 +191,13 @@
         readFromParcel(source);
     }
 
+    /**
+     * Return whether the application allow to handle the empty style splash screen.
+     */
+    public boolean allowHandleEmptySplashScreen() {
+        return (startingWindowTypeParameter & TYPE_PARAMETER_ALLOW_HANDLE_EMPTY_SCREEN) != 0;
+    }
+
     @Override
     public int describeContents() {
         return 0;
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 8213c86..25ee2d0 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -13223,59 +13223,57 @@
             long totalRxPackets = 0;
             long totalTxPackets = 0;
             if (delta != null) {
-                NetworkStats.Entry entry = new NetworkStats.Entry();
-                final int size = delta.size();
-                for (int i = 0; i < size; i++) {
-                    entry = delta.getValues(i, entry);
-                    if (entry.rxPackets == 0 && entry.txPackets == 0) {
+                for (NetworkStats.Entry entry : delta) {
+                    if (entry.getRxPackets() == 0 && entry.getTxPackets() == 0) {
                         continue;
                     }
 
                     if (DEBUG_ENERGY) {
-                        Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
-                                + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
-                                + " txPackets=" + entry.txPackets);
+                        Slog.d(TAG, "Mobile uid " + entry.getUid() + ": delta rx="
+                                + entry.getRxBytes() + " tx=" + entry.getTxBytes()
+                                + " rxPackets=" + entry.getRxPackets()
+                                + " txPackets=" + entry.getTxPackets());
                     }
 
-                    totalRxPackets += entry.rxPackets;
-                    totalTxPackets += entry.txPackets;
+                    totalRxPackets += entry.getRxPackets();
+                    totalTxPackets += entry.getTxPackets();
 
-                    final Uid u = getUidStatsLocked(mapUid(entry.uid), elapsedRealtimeMs, uptimeMs);
-                    u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
-                            entry.rxPackets);
-                    u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
-                            entry.txPackets);
-                    if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
+                    final Uid u = getUidStatsLocked(
+                            mapUid(entry.getUid()), elapsedRealtimeMs, uptimeMs);
+                    u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.getRxBytes(),
+                            entry.getRxPackets());
+                    u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.getTxBytes(),
+                            entry.getTxPackets());
+                    if (entry.getSet() == NetworkStats.SET_DEFAULT) { // Background transfers
                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA,
-                                entry.rxBytes, entry.rxPackets);
+                                entry.getRxBytes(), entry.getRxPackets());
                         u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_TX_DATA,
-                                entry.txBytes, entry.txPackets);
+                                entry.getTxBytes(), entry.getTxPackets());
                     }
 
                     mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
-                            entry.rxBytes);
+                            entry.getRxBytes());
                     mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
-                            entry.txBytes);
+                            entry.getTxBytes());
                     mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
-                            entry.rxPackets);
+                            entry.getRxPackets());
                     mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
-                            entry.txPackets);
+                            entry.getTxPackets());
                 }
 
                 // Now distribute proportional blame to the apps that did networking.
                 long totalPackets = totalRxPackets + totalTxPackets;
                 if (totalPackets > 0) {
-                    for (int i = 0; i < size; i++) {
-                        entry = delta.getValues(i, entry);
-                        if (entry.rxPackets == 0 && entry.txPackets == 0) {
+                    for (NetworkStats.Entry entry : delta) {
+                        if (entry.getRxPackets() == 0 && entry.getTxPackets() == 0) {
                             continue;
                         }
 
-                        final Uid u = getUidStatsLocked(mapUid(entry.uid),
+                        final Uid u = getUidStatsLocked(mapUid(entry.getUid()),
                                 elapsedRealtimeMs, uptimeMs);
 
                         // Distribute total radio active time in to this app.
-                        final long appPackets = entry.rxPackets + entry.txPackets;
+                        final long appPackets = entry.getRxPackets() + entry.getTxPackets();
                         final long appRadioTimeUs =
                                 (totalAppRadioTimeUs * appPackets) / totalPackets;
                         u.noteMobileRadioActiveTimeLocked(appRadioTimeUs, elapsedRealtimeMs);
@@ -13296,17 +13294,17 @@
                         if (deltaInfo != null) {
                             ControllerActivityCounterImpl activityCounter =
                                     u.getOrCreateModemControllerActivityLocked();
-                            if (totalRxPackets > 0 && entry.rxPackets > 0) {
-                                final long rxMs = (entry.rxPackets
+                            if (totalRxPackets > 0 && entry.getRxPackets() > 0) {
+                                final long rxMs = (entry.getRxPackets()
                                     * deltaInfo.getReceiveTimeMillis()) / totalRxPackets;
                                 activityCounter.getOrCreateRxTimeCounter()
                                         .increment(rxMs, elapsedRealtimeMs);
                             }
 
-                            if (totalTxPackets > 0 && entry.txPackets > 0) {
+                            if (totalTxPackets > 0 && entry.getTxPackets() > 0) {
                                 for (int lvl = 0; lvl < ModemActivityInfo.getNumTxPowerLevels();
                                         lvl++) {
-                                    long txMs = entry.txPackets
+                                    long txMs = entry.getTxPackets()
                                             * deltaInfo.getTransmitDurationMillisAtPowerLevel(lvl);
                                     txMs /= totalTxPackets;
                                     activityCounter.getOrCreateTxTimeCounters()[lvl]
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 1897788..5fee1fa 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4956,6 +4956,9 @@
          Used by ChooserActivity. -->
     <string translatable="false" name="config_defaultNearbySharingComponent"></string>
 
+    <!-- URI used for Nearby Share SliceProvider scanning. -->
+    <string translatable="false" name="config_defaultNearbySharingSliceUri"></string>
+
     <!-- Boolean indicating whether frameworks needs to reset cell broadcast geo-fencing
          check after reboot or airplane mode toggling -->
     <bool translatable="false" name="reset_geo_fencing_check_after_boot_or_apm">false</bool>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 3f08e4b..d374b74 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -755,6 +755,8 @@
     <dimen name="item_touch_helper_swipe_escape_velocity">120dp</dimen>
     <dimen name="item_touch_helper_swipe_escape_max_velocity">800dp</dimen>
 
+    <!-- The maximum size of the small notification icon. -->
+    <dimen name="notification_small_icon_size">48dp</dimen>
     <!-- The maximum height of any image in a remote view. This is applied to all images in custom remoteviews. This value is determined by the maximum notification height -->
     <dimen name="notification_custom_view_max_image_height">284dp</dimen>
     <!-- The maximum height of any image in a remote view. This is applied to all images in custom remoteviews. This value is determined a maximum notification width -->
@@ -779,6 +781,8 @@
     <!-- The alpha of a disabled notification button -->
     <item type="dimen" format="float" name="notification_action_disabled_alpha">0.5</item>
 
+    <!-- The maximum size of the small notification icon on low memory devices. -->
+    <dimen name="notification_small_icon_size_low_ram">@dimen/notification_small_icon_size</dimen>
     <!-- The maximum height of any image in a remote view. This is applied to all images in custom remoteviews. -->
     <dimen name="notification_custom_view_max_image_height_low_ram">208dp</dimen>
     <!-- The maximum height of any image in a remote view. This is applied to all images in custom remoteviews. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 3ce6b6c..6ae2829 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3561,6 +3561,7 @@
   <java-symbol type="style" name="Theme.DeviceDefault.Autofill.Save" />
   <java-symbol type="style" name="Theme.DeviceDefault.Light.Autofill.Save" />
 
+  <java-symbol type="dimen" name="notification_small_icon_size"/>
   <java-symbol type="dimen" name="notification_big_picture_max_height"/>
   <java-symbol type="dimen" name="notification_big_picture_max_width"/>
   <java-symbol type="dimen" name="notification_right_icon_size"/>
@@ -3569,6 +3570,7 @@
   <java-symbol type="dimen" name="notification_custom_view_max_image_height"/>
   <java-symbol type="dimen" name="notification_custom_view_max_image_width"/>
 
+  <java-symbol type="dimen" name="notification_small_icon_size_low_ram"/>
   <java-symbol type="dimen" name="notification_big_picture_max_height_low_ram"/>
   <java-symbol type="dimen" name="notification_big_picture_max_width_low_ram"/>
   <java-symbol type="dimen" name="notification_right_icon_size_low_ram"/>
diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java
index 37cf514..e6d2364 100644
--- a/core/tests/coretests/src/android/app/NotificationTest.java
+++ b/core/tests/coretests/src/android/app/NotificationTest.java
@@ -39,6 +39,7 @@
 import android.content.LocusId;
 import android.content.res.ColorStateList;
 import android.content.res.Configuration;
+import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Color;
 import android.graphics.drawable.Icon;
@@ -504,6 +505,22 @@
     }
 
     @Test
+    public void testBuild_ensureSmallIconIsNotTooBig_resizesIcon() {
+        Icon hugeIcon = Icon.createWithBitmap(
+                Bitmap.createBitmap(3000, 3000, Bitmap.Config.ARGB_8888));
+        Notification notification = new Notification.Builder(mContext, "Channel").setSmallIcon(
+                hugeIcon).build();
+
+        Bitmap smallNotificationIcon = notification.getSmallIcon().getBitmap();
+        assertThat(smallNotificationIcon.getWidth()).isEqualTo(
+                mContext.getResources().getDimensionPixelSize(
+                        R.dimen.notification_small_icon_size));
+        assertThat(smallNotificationIcon.getHeight()).isEqualTo(
+                mContext.getResources().getDimensionPixelSize(
+                        R.dimen.notification_small_icon_size));
+    }
+
+    @Test
     public void testColors_ensureColors_dayMode_producesValidPalette() {
         Notification.Colors c = new Notification.Colors();
         boolean colorized = false;
diff --git a/core/tests/coretests/src/android/content/pm/AppSearchPersonTest.java b/core/tests/coretests/src/android/content/pm/AppSearchShortcutPersonTest.java
similarity index 92%
rename from core/tests/coretests/src/android/content/pm/AppSearchPersonTest.java
rename to core/tests/coretests/src/android/content/pm/AppSearchShortcutPersonTest.java
index 5ba9059..3c49481 100644
--- a/core/tests/coretests/src/android/content/pm/AppSearchPersonTest.java
+++ b/core/tests/coretests/src/android/content/pm/AppSearchShortcutPersonTest.java
@@ -24,7 +24,7 @@
 import org.junit.Test;
 
 @Presubmit
-public class AppSearchPersonTest {
+public class AppSearchShortcutPersonTest {
 
     @Test
     public void testBuildPersonAndGetValue() {
@@ -32,7 +32,7 @@
         final String key = "key";
         final String uri = "name:name";
 
-        final Person person = new AppSearchPerson.Builder(uri)
+        final Person person = new AppSearchShortcutPerson.Builder(uri)
                 .setName(name)
                 .setKey(key)
                 .setIsBot(true)
diff --git a/core/tests/coretests/src/android/os/VibrationEffectTest.java b/core/tests/coretests/src/android/os/VibrationEffectTest.java
index 10cec82..104f077 100644
--- a/core/tests/coretests/src/android/os/VibrationEffectTest.java
+++ b/core/tests/coretests/src/android/os/VibrationEffectTest.java
@@ -16,6 +16,9 @@
 
 package android.os;
 
+import static android.os.VibrationEffect.VibrationParameter.targetAmplitude;
+import static android.os.VibrationEffect.VibrationParameter.targetFrequency;
+
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertNotNull;
@@ -32,6 +35,7 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.net.Uri;
+import android.os.VibrationEffect.Composition.UnreachableAfterRepeatingIndefinitelyException;
 import android.os.vibrator.PrebakedSegment;
 import android.os.vibrator.PrimitiveSegment;
 import android.os.vibrator.StepSegment;
@@ -43,6 +47,8 @@
 import org.junit.runner.RunWith;
 import org.mockito.junit.MockitoJUnitRunner;
 
+import java.time.Duration;
+
 @Presubmit
 @RunWith(MockitoJUnitRunner.class)
 public class VibrationEffectTest {
@@ -122,16 +128,7 @@
         VibrationEffect.createWaveform(TEST_TIMINGS, TEST_AMPLITUDES, -1).validate();
         VibrationEffect.createWaveform(new long[]{10, 10}, new int[] {0, 0}, -1).validate();
         VibrationEffect.createWaveform(TEST_TIMINGS, TEST_AMPLITUDES, 0).validate();
-        VibrationEffect.startWaveform()
-                .addStep(/* amplitude= */ 1, /* duration= */ 10)
-                .addRamp(/* amplitude= */ 0, /* duration= */ 20)
-                .addStep(/* amplitude= */ 1, /* frequencyHz= */ 1, /* duration= */ 100)
-                .addRamp(/* amplitude= */ 0.5f, /* frequencyHz= */ 100, /* duration= */ 50)
-                .build()
-                .validate();
 
-        assertThrows(IllegalStateException.class,
-                () -> VibrationEffect.startWaveform().build().validate());
         assertThrows(IllegalArgumentException.class,
                 () -> VibrationEffect.createWaveform(new long[0], new int[0], -1).validate());
         assertThrows(IllegalArgumentException.class,
@@ -145,27 +142,31 @@
         assertThrows(IllegalArgumentException.class,
                 () -> VibrationEffect.createWaveform(
                         TEST_TIMINGS, TEST_AMPLITUDES, TEST_TIMINGS.length).validate());
+    }
+
+    @Test
+    public void testValidateWaveformBuilder() {
+        VibrationEffect.startWaveform(targetAmplitude(1))
+                .addTransition(Duration.ofSeconds(1), targetAmplitude(0.5f), targetFrequency(100))
+                .addTransition(Duration.ZERO, targetAmplitude(0f), targetFrequency(200))
+                .addSustain(Duration.ofMinutes(2))
+                .addTransition(Duration.ofMillis(10), targetAmplitude(1f), targetFrequency(50))
+                .addSustain(Duration.ofMillis(1))
+                .addTransition(Duration.ZERO, targetFrequency(150))
+                .addSustain(Duration.ofMillis(2))
+                .addTransition(Duration.ofSeconds(15), targetAmplitude(1))
+                .build()
+                .validate();
+
+        assertThrows(IllegalStateException.class,
+                () -> VibrationEffect.startWaveform().build().validate());
+        assertThrows(IllegalArgumentException.class, () -> targetAmplitude(-2));
+        assertThrows(IllegalArgumentException.class, () -> targetFrequency(0));
         assertThrows(IllegalArgumentException.class,
-                () -> VibrationEffect.startWaveform()
-                        .addStep(/* amplitude= */ -2, 10).build().validate());
+                () -> VibrationEffect.startWaveform().addTransition(
+                        Duration.ofMillis(-10), targetAmplitude(1)).build().validate());
         assertThrows(IllegalArgumentException.class,
-                () -> VibrationEffect.startWaveform()
-                        .addStep(1, /* frequencyHz= */ -1f, 10).build().validate());
-        assertThrows(IllegalArgumentException.class,
-                () -> VibrationEffect.startWaveform()
-                        .addStep(1, /* duration= */ -1).build().validate());
-        assertThrows(IllegalArgumentException.class,
-                () -> VibrationEffect.startWaveform()
-                        .addStep(1, 100f, /* duration= */ -1).build().validate());
-        assertThrows(IllegalArgumentException.class,
-                () -> VibrationEffect.startWaveform()
-                        .addRamp(/* amplitude= */ -3, 10).build().validate());
-        assertThrows(IllegalArgumentException.class,
-                () -> VibrationEffect.startWaveform()
-                        .addRamp(1, /* frequencyHz= */ 0, 10).build().validate());
-        assertThrows(IllegalArgumentException.class,
-                () -> VibrationEffect.startWaveform()
-                        .addRamp(1, 10f, /* duration= */ -3).build().validate());
+                () -> VibrationEffect.startWaveform().addSustain(Duration.ZERO).build().validate());
     }
 
     @Test
@@ -174,14 +175,24 @@
                 .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
                 .addEffect(TEST_ONE_SHOT)
                 .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f)
-                .addEffect(TEST_WAVEFORM, 100)
+                .addOffDuration(Duration.ofMillis(100))
                 .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 0.5f, 10)
                 .addEffect(VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
                 .compose()
                 .validate();
 
+        VibrationEffect.startComposition()
+                .repeatEffectIndefinitely(TEST_ONE_SHOT)
+                .compose()
+                .validate();
+
         assertThrows(IllegalStateException.class,
                 () -> VibrationEffect.startComposition().compose().validate());
+        assertThrows(IllegalStateException.class,
+                () -> VibrationEffect.startComposition()
+                        .addOffDuration(Duration.ofSeconds(0))
+                        .compose()
+                        .validate());
         assertThrows(IllegalArgumentException.class,
                 () -> VibrationEffect.startComposition().addPrimitive(-1).compose().validate());
         assertThrows(IllegalArgumentException.class,
@@ -196,12 +207,27 @@
                         .validate());
         assertThrows(IllegalArgumentException.class,
                 () -> VibrationEffect.startComposition()
-                        .addEffect(TEST_ONE_SHOT, /* delay= */ -10)
+                        .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, -1)
                         .compose()
                         .validate());
         assertThrows(IllegalArgumentException.class,
                 () -> VibrationEffect.startComposition()
-                        .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, -1)
+                        .repeatEffectIndefinitely(
+                                // Repeating waveform.
+                                VibrationEffect.createWaveform(
+                                        new long[] { 10 }, new int[] { 100}, 0))
+                        .compose()
+                        .validate());
+        assertThrows(UnreachableAfterRepeatingIndefinitelyException.class,
+                () -> VibrationEffect.startComposition()
+                        .repeatEffectIndefinitely(TEST_WAVEFORM)
+                        .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+                        .compose()
+                        .validate());
+        assertThrows(UnreachableAfterRepeatingIndefinitelyException.class,
+                () -> VibrationEffect.startComposition()
+                        .repeatEffectIndefinitely(TEST_WAVEFORM)
+                        .addEffect(TEST_ONE_SHOT)
                         .compose()
                         .validate());
     }
@@ -354,9 +380,9 @@
         assertFalse(VibrationEffect.createWaveform(
                 new long[]{200, 200, 700}, new int[]{1, 2, 3}, -1).isHapticFeedbackCandidate());
         assertFalse(VibrationEffect.startWaveform()
-                .addRamp(1, 500)
-                .addStep(1, 200)
-                .addRamp(0, 500)
+                .addTransition(Duration.ofMillis(500), targetAmplitude(1))
+                .addTransition(Duration.ofMillis(200), targetAmplitude(0.5f))
+                .addTransition(Duration.ofMillis(500), targetAmplitude(0))
                 .build()
                 .isHapticFeedbackCandidate());
     }
@@ -367,9 +393,9 @@
         assertTrue(VibrationEffect.createWaveform(
                 new long[]{100, 200, 300}, new int[]{1, 2, 3}, -1).isHapticFeedbackCandidate());
         assertTrue(VibrationEffect.startWaveform()
-                .addRamp(1, 300)
-                .addStep(1, 200)
-                .addRamp(0, 300)
+                .addTransition(Duration.ofMillis(300), targetAmplitude(1))
+                .addTransition(Duration.ofMillis(200), targetAmplitude(0.5f))
+                .addTransition(Duration.ofMillis(300), targetAmplitude(0))
                 .build()
                 .isHapticFeedbackCandidate());
     }
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 69ff7c6..cd42a34 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -81,6 +81,7 @@
 import android.os.UserHandle;
 import android.provider.DeviceConfig;
 import android.service.chooser.ChooserTarget;
+import android.util.Log;
 import android.view.View;
 
 import androidx.annotation.CallSuper;
@@ -187,7 +188,7 @@
      * TODO: remove when we no longer want to test the system's on-the-fly evaluation.
      */
     protected boolean shouldTestTogglingAppPredictionServiceAvailabilityAtRuntime() {
-        return true;
+        return false;
     }
 
     /* --------
@@ -762,6 +763,7 @@
 
 
     @Test
+    @Ignore
     public void testNearbyShareLogging() throws Exception {
         Intent sendIntent = createSendTextIntent();
         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
@@ -1327,16 +1329,17 @@
         final ChooserActivity activity =
                 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
         waitForIdle();
-
         if (activity.getPackageManager().getAppPredictionServicePackageName() == null) {
             assertThat(activity.isAppPredictionServiceAvailable(), is(false));
         } else {
-            assertThat(activity.isAppPredictionServiceAvailable(), is(true));
-
             if (!shouldTestTogglingAppPredictionServiceAvailabilityAtRuntime()) {
                 return;
             }
 
+            // This isn't a toggle per-se, but isAppPredictionServiceAvailable only works in
+            // system (see comment in the method).
+            assertThat(activity.isAppPredictionServiceAvailable(), is(true));
+
             ChooserActivityOverrideData.getInstance().resources =
                     Mockito.spy(activity.getResources());
             when(
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 d4f08ba..7f85982 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
@@ -51,6 +51,13 @@
     static final ChooserActivityOverrideData sOverrides = ChooserActivityOverrideData.getInstance();
     private UsageStatsManager mUsm;
 
+    // ResolverActivity (the base class of ChooserActivity) inspects the launched-from UID at
+    // onCreate and needs to see some non-negative value in the test.
+    @Override
+    public int getLaunchedFromUid() {
+        return 1234;
+    }
+
     @Override
     protected AbstractMultiProfilePagerAdapter createMultiProfilePagerAdapter(
             Intent[] initialIntents, List<ResolveInfo> rList, boolean filterLastUsed) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
index 413627d..e255e44 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
@@ -54,6 +54,7 @@
 import android.view.SurfaceControl;
 import android.view.View;
 import android.window.SplashScreenView;
+import android.window.StartingWindowInfo;
 import android.window.StartingWindowInfo.StartingWindowType;
 
 import com.android.internal.R;
@@ -138,8 +139,8 @@
      *                                 executed on splash screen thread. Note that the view can be
      *                                 null if failed.
      */
-    void createContentView(Context context, @StartingWindowType int suggestType, ActivityInfo info,
-            int taskId, Consumer<SplashScreenView> splashScreenViewConsumer,
+    void createContentView(Context context, @StartingWindowType int suggestType,
+            StartingWindowInfo info, Consumer<SplashScreenView> splashScreenViewConsumer,
             Consumer<Runnable> uiThreadInitConsumer) {
         mSplashscreenWorkerHandler.post(() -> {
             SplashScreenView contentView;
@@ -150,7 +151,7 @@
                 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
             } catch (RuntimeException e) {
                 Slog.w(TAG, "failed creating starting window content at taskId: "
-                        + taskId, e);
+                        + info.taskInfo.taskId, e);
                 contentView = null;
             }
             splashScreenViewConsumer.accept(contentView);
@@ -241,7 +242,7 @@
         return null;
     }
 
-    private SplashScreenView makeSplashScreenContentView(Context context, ActivityInfo ai,
+    private SplashScreenView makeSplashScreenContentView(Context context, StartingWindowInfo info,
             @StartingWindowType int suggestType, Consumer<Runnable> uiThreadInitConsumer) {
         updateDensity();
 
@@ -250,6 +251,9 @@
 
         final Drawable legacyDrawable = suggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN
                 ? peekLegacySplashscreenContent(context, mTmpAttrs) : null;
+        final ActivityInfo ai = info.targetActivityInfo != null
+                ? info.targetActivityInfo
+                : info.taskInfo.topActivityInfo;
         final int themeBGColor = legacyDrawable != null
                 ? getBGColorFromCache(ai, () -> estimateWindowBGColor(legacyDrawable))
                 : getBGColorFromCache(ai, () -> peekWindowBGColor(context, mTmpAttrs));
@@ -258,6 +262,7 @@
                 .overlayDrawable(legacyDrawable)
                 .chooseStyle(suggestType)
                 .setUiThreadInitConsumer(uiThreadInitConsumer)
+                .setAllowHandleEmpty(info.allowHandleEmptySplashScreen())
                 .build();
     }
 
@@ -327,6 +332,7 @@
         private Drawable[] mFinalIconDrawables;
         private int mFinalIconSize = mIconSize;
         private Consumer<Runnable> mUiThreadInitTask;
+        private boolean mAllowHandleEmpty;
 
         StartingWindowViewBuilder(@NonNull Context context, @NonNull ActivityInfo aInfo) {
             mContext = context;
@@ -353,6 +359,11 @@
             return this;
         }
 
+        StartingWindowViewBuilder setAllowHandleEmpty(boolean allowHandleEmpty) {
+            mAllowHandleEmpty = allowHandleEmpty;
+            return this;
+        }
+
         SplashScreenView build() {
             Drawable iconDrawable;
             final int animationDuration;
@@ -491,7 +502,8 @@
                     .setIconBackground(background)
                     .setCenterViewDrawable(foreground)
                     .setAnimationDurationMillis(animationDuration)
-                    .setUiThreadInitConsumer(uiThreadInitTask);
+                    .setUiThreadInitConsumer(uiThreadInitTask)
+                    .setAllowHandleEmpty(mAllowHandleEmpty);
 
             if (mSuggestType == STARTING_WINDOW_TYPE_SPLASH_SCREEN
                     && mTmpAttrs.mBrandingImage != null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
index f8902c6..9a966b8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
@@ -328,7 +328,7 @@
         if (mSysuiProxy != null) {
             mSysuiProxy.requestTopUi(true, TAG);
         }
-        mSplashscreenContentDrawer.createContentView(context, suggestType, activityInfo, taskId,
+        mSplashscreenContentDrawer.createContentView(context, suggestType, windowInfo,
                 viewSupplier::setView, viewSupplier::setUiThreadInitTask);
         try {
             if (addWindow(taskId, appToken, rootLayout, display, params, suggestType)) {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt
index f8d14c6..af629cc 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt
@@ -24,9 +24,6 @@
 import com.android.server.wm.flicker.FlickerTestParameter
 import com.android.server.wm.flicker.annotation.Group4
 import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.wm.shell.flicker.helpers.BaseAppHelper
-import org.junit.Assume
-import org.junit.Before
 import org.junit.runner.RunWith
 import org.junit.Test
 import org.junit.runners.Parameterized
@@ -62,12 +59,6 @@
             }
         }
 
-    @Before
-    fun setup() {
-        // This test doesn't work in shell transitions because of b/205288792
-        Assume.assumeFalse(BaseAppHelper.isShellTransitionsEnabled())
-    }
-
     @Presubmit
     @Test
     fun testAppIsAlwaysVisible() {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreen.kt
index c93c5ad..add11c1 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreen.kt
@@ -25,9 +25,6 @@
 import com.android.server.wm.flicker.FlickerTestParameter
 import com.android.server.wm.flicker.annotation.Group4
 import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.wm.shell.flicker.helpers.BaseAppHelper
-import org.junit.Assume
-import org.junit.Before
 import org.junit.runner.RunWith
 import org.junit.Test
 import org.junit.runners.Parameterized
@@ -70,12 +67,6 @@
             }
         }
 
-    @Before
-    fun setup() {
-        // This test doesn't work in shell transitions because of b/205288792
-        Assume.assumeFalse(BaseAppHelper.isShellTransitionsEnabled())
-    }
-
     @Presubmit
     @Test
     fun testAppIsAlwaysVisible() {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
index dee13c1..afe64e3 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
@@ -204,7 +204,6 @@
     @Presubmit
     @Test
     fun testAppPlusPipLayerCoversFullScreenOnEnd() {
-        // This test doesn't work in shell transitions because of b/206669574
         testSpec.assertLayersEnd {
             val pipRegion = visibleRegion(pipApp.component).region
             visibleRegion(testApp.component)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
index c36dfda..1d61ab4 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
@@ -31,6 +31,7 @@
 import com.android.server.wm.traces.common.FlickerComponentName
 import com.android.wm.shell.flicker.helpers.ImeAppHelper
 import org.junit.Assume.assumeFalse
+import org.junit.Assume.assumeTrue
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -82,6 +83,13 @@
         super.statusBarLayerRotatesScales()
     }
 
+    @FlakyTest(bugId = 214452854)
+    @Test
+    fun statusBarLayerRotatesScales_shellTransit() {
+        assumeTrue(isShellTransitionsEnabled)
+        super.statusBarLayerRotatesScales()
+    }
+
     /**
      * Ensure the pip window remains visible throughout any keyboard interactions
      */
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
index df58194..21175a0 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
@@ -92,11 +92,7 @@
     /** {@inheritDoc}  */
     @FlakyTest(bugId = 206753786)
     @Test
-    override fun statusBarLayerRotatesScales() {
-        // This test doesn't work in shell transitions because of b/206753786
-        assumeFalse(com.android.server.wm.flicker.helpers.isShellTransitionsEnabled)
-        super.statusBarLayerRotatesScales()
-    }
+    override fun statusBarLayerRotatesScales() = super.statusBarLayerRotatesScales()
 
     @FlakyTest(bugId = 161435597)
     @Test
diff --git a/libs/hwui/jni/Bitmap.cpp b/libs/hwui/jni/Bitmap.cpp
index 6989ac0..5db0783 100755
--- a/libs/hwui/jni/Bitmap.cpp
+++ b/libs/hwui/jni/Bitmap.cpp
@@ -686,16 +686,14 @@
                                           }
                                           return data->ptr != nullptr;
                                       }));
-        inPlaceCallback(std::move(data.ptr), data.size);
-        return STATUS_OK;
+        return inPlaceCallback(std::move(data.ptr), data.size);
     } else if (type == BlobType::ASHMEM) {
         int rawFd = -1;
         int32_t size = 0;
         ON_ERROR_RETURN(AParcel_readInt32(parcel, &size));
         ON_ERROR_RETURN(AParcel_readParcelFileDescriptor(parcel, &rawFd));
         android::base::unique_fd fd(rawFd);
-        ashmemCallback(std::move(fd), size);
-        return STATUS_OK;
+        return ashmemCallback(std::move(fd), size);
     } else {
         // Although the above if/else was "exhaustive" guard against unknown types
         return STATUS_UNKNOWN_ERROR;
@@ -768,7 +766,7 @@
 // framework, we may need to update this maximum size.
 static constexpr size_t kMaxColorSpaceSerializedBytes = 80;
 
-static constexpr auto RuntimeException = "java/lang/RuntimeException";
+static constexpr auto BadParcelableException = "android/os/BadParcelableException";
 
 static bool validateImageInfo(const SkImageInfo& info, int32_t rowBytes) {
     // TODO: Can we avoid making a SkBitmap for this?
@@ -809,7 +807,7 @@
             kRGB_565_SkColorType != colorType &&
             kARGB_4444_SkColorType != colorType &&
             kAlpha_8_SkColorType != colorType) {
-        jniThrowExceptionFmt(env, RuntimeException,
+        jniThrowExceptionFmt(env, BadParcelableException,
                              "Bitmap_createFromParcel unknown colortype: %d\n", colorType);
         return NULL;
     }
@@ -821,7 +819,7 @@
         return NULL;
     }
     if (!Bitmap::computeAllocationSize(rowBytes, height, &allocationSize)) {
-        jniThrowExceptionFmt(env, RuntimeException,
+        jniThrowExceptionFmt(env, BadParcelableException,
                              "Received bad bitmap size: width=%d, height=%d, rowBytes=%d", width,
                              height, rowBytes);
         return NULL;
@@ -831,13 +829,23 @@
             p.get(),
             // In place callback
             [&](std::unique_ptr<int8_t[]> buffer, int32_t size) {
+                if (allocationSize > size) {
+                    android_errorWriteLog(0x534e4554, "213169612");
+                    return STATUS_BAD_VALUE;
+                }
                 nativeBitmap = Bitmap::allocateHeapBitmap(allocationSize, imageInfo, rowBytes);
                 if (nativeBitmap) {
-                    memcpy(nativeBitmap->pixels(), buffer.get(), size);
+                    memcpy(nativeBitmap->pixels(), buffer.get(), allocationSize);
+                    return STATUS_OK;
                 }
+                return STATUS_NO_MEMORY;
             },
             // Ashmem callback
             [&](android::base::unique_fd fd, int32_t size) {
+                if (allocationSize > size) {
+                    android_errorWriteLog(0x534e4554, "213169612");
+                    return STATUS_BAD_VALUE;
+                }
                 int flags = PROT_READ;
                 if (isMutable) {
                     flags |= PROT_WRITE;
@@ -846,18 +854,21 @@
                 if (addr == MAP_FAILED) {
                     const int err = errno;
                     ALOGW("mmap failed, error %d (%s)", err, strerror(err));
-                    return;
+                    return STATUS_NO_MEMORY;
                 }
                 nativeBitmap =
                         Bitmap::createFrom(imageInfo, rowBytes, fd.release(), addr, size, !isMutable);
+                return STATUS_OK;
             });
-    if (error != STATUS_OK) {
+
+    if (error != STATUS_OK && error != STATUS_NO_MEMORY) {
         // TODO: Stringify the error, see signalExceptionForError in android_util_Binder.cpp
-        jniThrowExceptionFmt(env, RuntimeException, "Failed to read from Parcel, error=%d", error);
+        jniThrowExceptionFmt(env, BadParcelableException, "Failed to read from Parcel, error=%d",
+                             error);
         return nullptr;
     }
-    if (!nativeBitmap) {
-        jniThrowRuntimeException(env, "Could not allocate java pixel ref.");
+    if (error == STATUS_NO_MEMORY || !nativeBitmap) {
+        jniThrowRuntimeException(env, "Could not allocate bitmap data.");
         return nullptr;
     }
 
diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java
index 09d7fbd..e2e48d3 100644
--- a/media/java/android/media/ImageReader.java
+++ b/media/java/android/media/ImageReader.java
@@ -963,7 +963,7 @@
          *
          * @see HardwareBuffer
          */
-        public @NonNull Builder setUsage(long usage) {
+        public @NonNull Builder setUsage(@Usage long usage) {
             mUsage = usage;
             return this;
         }
diff --git a/media/java/android/media/ImageWriter.java b/media/java/android/media/ImageWriter.java
index 6168c22..a1aedf1 100644
--- a/media/java/android/media/ImageWriter.java
+++ b/media/java/android/media/ImageWriter.java
@@ -102,11 +102,10 @@
     private int mWidth;
     private int mHeight;
     private final int mMaxImages;
-    private @Usage long mUsage = HardwareBuffer.USAGE_CPU_WRITE_OFTEN;
+    private long mUsage = HardwareBuffer.USAGE_CPU_WRITE_OFTEN;
     private @HardwareBuffer.Format int mHardwareBufferFormat;
     private @NamedDataSpace long mDataSpace;
     private boolean mUseLegacyImageFormat;
-    private boolean mUseSurfaceImageFormatInfo;
 
     // Field below is used by native code, do not access or modify.
     private int mWriterFormat;
@@ -255,35 +254,38 @@
                 + ", maxImages: " + maxImages);
         }
 
-        mUseSurfaceImageFormatInfo = useSurfaceImageFormatInfo;
         mUseLegacyImageFormat = useLegacyImageFormat;
         // Note that the underlying BufferQueue is working in synchronous mode
         // to avoid dropping any buffers.
         mNativeContext = nativeInit(new WeakReference<>(this), surface, maxImages, width, height,
             useSurfaceImageFormatInfo, hardwareBufferFormat, dataSpace, usage);
 
+        // if useSurfaceImageFormatInfo is true, imageformat should be read from the surface.
         if (useSurfaceImageFormatInfo) {
             // nativeInit internally overrides UNKNOWN format. So does surface format query after
             // nativeInit and before getEstimatedNativeAllocBytes().
             imageFormat = SurfaceUtils.getSurfaceFormat(surface);
-            // Several public formats use the same native HAL_PIXEL_FORMAT_BLOB. The native
-            // allocation estimation sequence depends on the public formats values. To avoid
-            // possible errors, convert where necessary.
-            if (imageFormat == StreamConfigurationMap.HAL_PIXEL_FORMAT_BLOB) {
-                int surfaceDataspace = SurfaceUtils.getSurfaceDataspace(surface);
-                switch (surfaceDataspace) {
-                    case StreamConfigurationMap.HAL_DATASPACE_DEPTH:
-                        imageFormat = ImageFormat.DEPTH_POINT_CLOUD;
-                        break;
-                    case StreamConfigurationMap.HAL_DATASPACE_DYNAMIC_DEPTH:
-                        imageFormat = ImageFormat.DEPTH_JPEG;
-                        break;
-                    case StreamConfigurationMap.HAL_DATASPACE_HEIF:
-                        imageFormat = ImageFormat.HEIC;
-                        break;
-                    default:
-                        imageFormat = ImageFormat.JPEG;
-                }
+            mHardwareBufferFormat = PublicFormatUtils.getHalFormat(imageFormat);
+            mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat);
+        }
+
+        // Several public formats use the same native HAL_PIXEL_FORMAT_BLOB. The native
+        // allocation estimation sequence depends on the public formats values. To avoid
+        // possible errors, convert where necessary.
+        if (imageFormat == StreamConfigurationMap.HAL_PIXEL_FORMAT_BLOB) {
+            int surfaceDataspace = SurfaceUtils.getSurfaceDataspace(surface);
+            switch (surfaceDataspace) {
+                case StreamConfigurationMap.HAL_DATASPACE_DEPTH:
+                    imageFormat = ImageFormat.DEPTH_POINT_CLOUD;
+                    break;
+                case StreamConfigurationMap.HAL_DATASPACE_DYNAMIC_DEPTH:
+                    imageFormat = ImageFormat.DEPTH_JPEG;
+                    break;
+                case StreamConfigurationMap.HAL_DATASPACE_HEIF:
+                    imageFormat = ImageFormat.HEIC;
+                    break;
+                default:
+                    imageFormat = ImageFormat.JPEG;
             }
             mHardwareBufferFormat = PublicFormatUtils.getHalFormat(imageFormat);
             mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat);
@@ -307,7 +309,6 @@
     private ImageWriter(Surface surface, int maxImages, boolean useSurfaceImageFormatInfo,
             int imageFormat, int width, int height) {
         mMaxImages = maxImages;
-        // update hal format and dataspace only if image format is overridden by producer.
         mHardwareBufferFormat = PublicFormatUtils.getHalFormat(imageFormat);
         mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat);
 
@@ -566,6 +567,9 @@
     /**
      * Get the ImageWriter usage flag.
      *
+     * <p>It is not recommended to use this function if {@link Builder#setUsage} is not called.
+     * Invalid usage value will be returned if so.</p>
+     *
      * @return The ImageWriter usage flag.
      */
     public @Usage long getUsage() {
@@ -873,7 +877,7 @@
         private int mHeight = -1;
         private int mMaxImages = 1;
         private int mImageFormat = ImageFormat.UNKNOWN;
-        private @Usage long mUsage = HardwareBuffer.USAGE_CPU_WRITE_OFTEN;
+        private long mUsage = -1;
         private @HardwareBuffer.Format int mHardwareBufferFormat = HardwareBuffer.RGBA_8888;
         private @NamedDataSpace long mDataSpace = DataSpace.DATASPACE_UNKNOWN;
         private boolean mUseSurfaceImageFormatInfo = true;
@@ -885,10 +889,19 @@
         /**
          * Constructs a new builder for {@link ImageWriter}.
          *
+         * <p>Uses {@code surface} input parameter to retrieve image format, hal format
+         * and hal dataspace value for default. </p>
+         *
          * @param surface The destination Surface this writer produces Image data into.
+         *
+         * @throws IllegalArgumentException if the surface is already abandoned.
          */
         public Builder(@NonNull Surface surface) {
             mSurface = surface;
+            // retrieve format from surface
+            mImageFormat = SurfaceUtils.getSurfaceFormat(surface);
+            mDataSpace = SurfaceUtils.getSurfaceDataspace(surface);
+            mHardwareBufferFormat = PublicFormatUtils.getHalFormat(mImageFormat);
         }
 
         /**
@@ -926,6 +939,8 @@
          * @param imageFormat The format of the {@link ImageWriter}. It can be any valid specified
          *                    by {@link ImageFormat} or {@link PixelFormat}.
          * @return the Builder instance with customized image format.
+         *
+         * @throws IllegalArgumentException if {@code imageFormat} is invalid.
          */
         @SuppressLint("MissingGetterMatchingBuilder")
         public @NonNull Builder setImageFormat(@Format int imageFormat) {
@@ -985,12 +1000,16 @@
 
         /**
          * Set the usage flag of this ImageWriter.
-         * Default value is {@link HardwareBuffer#USAGE_CPU_WRITE_OFTEN}.
+         *
+         * <p>If this function is not called, usage bit will be set
+         * to {@link HardwareBuffer#USAGE_CPU_WRITE_OFTEN} if the image format is not
+         * {@link ImageFormat#PRIVATE PRIVATE}.</p>
          *
          * @param usage The intended usage of the images produced by this ImageWriter.
          * @return the Builder instance with customized usage flag.
          *
          * @see HardwareBuffer
+         * @see #getUsage
          */
         public @NonNull Builder setUsage(@Usage long usage) {
             mUsage = usage;
@@ -1022,6 +1041,7 @@
         private int mHeight = -1;
         private int mWidth = -1;
         private int mFormat = -1;
+        private @NamedDataSpace long mDataSpace = DataSpace.DATASPACE_UNKNOWN;
         // When this default timestamp is used, timestamp for the input Image
         // will be generated automatically when queueInputBuffer is called.
         private final long DEFAULT_TIMESTAMP = Long.MIN_VALUE;
@@ -1034,19 +1054,34 @@
             mOwner = writer;
             mWidth = writer.mWidth;
             mHeight = writer.mHeight;
+            mDataSpace = writer.mDataSpace;
 
-            if (!writer.mUseLegacyImageFormat) {
+            if (!mOwner.mUseLegacyImageFormat) {
                 mFormat = PublicFormatUtils.getPublicFormat(
-                        writer.mHardwareBufferFormat, writer.mDataSpace);
+                    mOwner.mHardwareBufferFormat, mDataSpace);
             }
         }
 
         @Override
+        public @NamedDataSpace long getDataSpace() {
+            throwISEIfImageIsInvalid();
+
+            return mDataSpace;
+        }
+
+        @Override
+        public void setDataSpace(@NamedDataSpace long dataSpace) {
+            throwISEIfImageIsInvalid();
+
+            mDataSpace = dataSpace;
+        }
+
+        @Override
         public int getFormat() {
             throwISEIfImageIsInvalid();
 
-            if (mFormat == -1) {
-                mFormat = nativeGetFormat();
+            if (mOwner.mUseLegacyImageFormat && mFormat == -1) {
+                mFormat = nativeGetFormat(mDataSpace);
             }
             return mFormat;
         }
@@ -1114,7 +1149,8 @@
 
             if (mPlanes == null) {
                 int numPlanes = ImageUtils.getNumPlanesForFormat(getFormat());
-                mPlanes = nativeCreatePlanes(numPlanes, getOwner().getFormat());
+                mPlanes = nativeCreatePlanes(numPlanes, getOwner().getFormat(),
+                        getOwner().getDataSpace());
             }
 
             return mPlanes.clone();
@@ -1222,13 +1258,14 @@
         }
 
         // Create the SurfacePlane object and fill the information
-        private synchronized native SurfacePlane[] nativeCreatePlanes(int numPlanes, int writerFmt);
+        private synchronized native SurfacePlane[] nativeCreatePlanes(int numPlanes, int writerFmt,
+                long dataSpace);
 
         private synchronized native int nativeGetWidth();
 
         private synchronized native int nativeGetHeight();
 
-        private synchronized native int nativeGetFormat();
+        private synchronized native int nativeGetFormat(long dataSpace);
 
         private synchronized native HardwareBuffer nativeGetHardwareBuffer();
     }
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index e75df1d..3fd27d5 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -426,10 +426,30 @@
         /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */
         public static final int COLOR_Format24BitABGR6666           = 43;
 
-        /** @hide
-         * P010 is a 4:2:0 YCbCr semiplanar format comprised of a WxH Y plane
-         * followed by a Wx(H/2) CbCr plane. Each sample is represented by a 16-bit
-         * little-endian value, with the lower 6 bits set to zero. */
+        /**
+         * P010 is 10-bit-per component 4:2:0 YCbCr semiplanar format.
+         * <p>
+         * This format uses 24 allocated bits per pixel with 15 bits of
+         * data per pixel. Chroma planes are subsampled by 2 both
+         * horizontally and vertically. Each chroma and luma component
+         * has 16 allocated bits in little-endian configuration with 10
+         * MSB of actual data.
+         *
+         * <pre>
+         *            byte                   byte
+         *  <--------- i --------> | <------ i + 1 ------>
+         * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+         * |     UNUSED      |      Y/Cb/Cr                |
+         * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+         *  0               5 6   7 0                    7
+         * bit
+         * </pre>
+         *
+         * Use this format with {@link Image}. This format corresponds
+         * to {@link android.graphics.ImageFormat#YCBCR_P010}.
+         * <p>
+         */
+        @SuppressLint("AllUpper")
         public static final int COLOR_FormatYUVP010                 = 54;
 
         /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */
@@ -615,6 +635,24 @@
         public static final String FEATURE_EncodingStatistics = "encoding-statistics";
 
         /**
+         * <b>video encoder only</b>: codec supports HDR editing.
+         * <p>
+         * HDR editing support means that the codec accepts 10-bit HDR
+         * input surface, and it is capable of generating any HDR
+         * metadata required from both YUV and RGB input when the
+         * metadata is not present. This feature is only meaningful when
+         * using an HDR capable profile (and 10-bit HDR input).
+         * <p>
+         * This feature implies that the codec is capable of encoding at
+         * least one HDR format, and that it supports RGBA_1010102 as
+         * well as P010, and optionally RGBA_FP16 input formats, and
+         * that the encoder can generate HDR metadata for all supported
+         * HDR input formats.
+         */
+        @SuppressLint("AllUpper")
+        public static final String FEATURE_HdrEditing = "hdr-editing";
+
+        /**
          * Query codec feature capabilities.
          * <p>
          * These features are supported to be used by the codec.  These
@@ -654,6 +692,7 @@
             new Feature(FEATURE_DynamicTimestamp, (1 << 2), false),
             new Feature(FEATURE_QpBounds, (1 << 3), false),
             new Feature(FEATURE_EncodingStatistics, (1 << 4), false),
+            new Feature(FEATURE_HdrEditing, (1 << 5), false),
             // feature to exclude codec from REGULAR codec list
             new Feature(FEATURE_SpecialCodec,     (1 << 30), false, true),
         };
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index ad8fc07..ea26185 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -1078,8 +1078,8 @@
      *
      * @throws IOException When an {@link IOException} is thrown while closing a {@link
      * MediaDataSource} passed to {@link #setDataSource(MediaDataSource)}. This throws clause exists
-     * since API 33, but this method can throw in earlier API versions where the exception is not
-     * declared.
+     * since API {@link android.os.Build.VERSION_CODES#TIRAMISU}, but this method can throw in
+     * earlier API versions where the exception is not declared.
      */
     @Override
     public void close() throws IOException {
@@ -1091,8 +1091,8 @@
      *
      * @throws IOException When an {@link IOException} is thrown while closing a {@link
      * MediaDataSource} passed to {@link #setDataSource(MediaDataSource)}. This throws clause exists
-     * since API 33, but this method can throw in earlier API versions where the exception is not
-     * declared.
+     * since API {@link android.os.Build.VERSION_CODES#TIRAMISU}, but this method can throw in
+     * earlier API versions where the exception is not declared.
      */
     public native void release() throws IOException;
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index a6f244f..2772769 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -1059,7 +1059,8 @@
      * haptic channels or not. As this function doesn't has a context
      * to resolve the uri, the result may be wrong if the uri cannot be
      * resolved correctly.
-     * Use {@link #hasHapticChannels(int)} instead when possible.
+     * Use {@link #hasHapticChannels(int)} or {@link #hasHapticChannels(Context, Uri)}
+     * instead when possible.
      *
      * @param ringtoneUri The {@link Uri} of a sound or ringtone.
      * @return true if the ringtone contains haptic channels.
@@ -1069,6 +1070,17 @@
     }
 
     /**
+     * Returns if the {@link Ringtone} from a given sound URI contains haptics channels or not.
+     *
+     * @param context the {@link android.content.Context} to use when resolving the Uri.
+     * @param ringtoneUri the {@link Uri} of a sound or ringtone.
+     * @return true if the ringtone contains haptic channels.
+     */
+    public static boolean hasHapticChannels(@NonNull Context context, @NonNull Uri ringtoneUri) {
+        return AudioManager.hasHapticChannels(context, ringtoneUri);
+    }
+
+    /**
      * Attempts to create a context for the given user.
      *
      * @return created context, or null if package does not exist
diff --git a/media/java/android/media/tv/AdRequest.java b/media/java/android/media/tv/AdRequest.java
index adcf541..0542c55 100644
--- a/media/java/android/media/tv/AdRequest.java
+++ b/media/java/android/media/tv/AdRequest.java
@@ -29,7 +29,6 @@
 
 /**
  * An advertisement request which can be sent to TV input to request AD operations.
- * @hide
  */
 public final class AdRequest implements Parcelable {
     /** @hide */
diff --git a/media/java/android/media/tv/AdResponse.java b/media/java/android/media/tv/AdResponse.java
index 5dba82c..0c20954 100644
--- a/media/java/android/media/tv/AdResponse.java
+++ b/media/java/android/media/tv/AdResponse.java
@@ -26,7 +26,6 @@
 
 /**
  * An advertisement request which can be sent to TV interactive App service to inform AD status.
- * @hide
  */
 public final class AdResponse implements Parcelable {
     /** @hide */
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index f438d29..cc33a1e 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -394,17 +394,14 @@
 
     /**
      * Signal lost.
-     * @hide
      */
     public static final int SIGNAL_STRENGTH_LOST = 1;
     /**
      * Weak signal.
-     * @hide
      */
     public static final int SIGNAL_STRENGTH_WEAK = 2;
     /**
      * Strong signal.
-     * @hide
      */
     public static final int SIGNAL_STRENGTH_STRONG = 3;
 
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 98d4182..f63f444 100755
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -896,7 +896,6 @@
          *
          * @param response advertisement response.
          * @see android.media.tv.interactive.TvInteractiveAppService.Session#requestAd(AdRequest)
-         * @hide
          */
         public void notifyAdResponse(@NonNull final AdResponse response) {
             executeOrPostRunnableOnMainThread(new Runnable() {
@@ -977,7 +976,6 @@
 
         /**
          * Notifies signal strength.
-         * @hide
          */
         public void notifySignalStrength(@TvInputManager.SignalStrength final int strength) {
             executeOrPostRunnableOnMainThread(new Runnable() {
@@ -1128,7 +1126,6 @@
          * Called when advertisement request is received.
          *
          * @param request advertisement request received
-         * @hide
          */
         public void onRequestAd(@NonNull AdRequest request) {
         }
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index 6c25a70..4d63af7 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -1079,21 +1079,20 @@
 
         /**
          * This is called when signal strength is updated.
+         *
          * @param inputId The ID of the TV input bound to this view.
          * @param strength The current signal strength.
-         *
-         * @hide
          */
-        public void onSignalStrength(String inputId, @TvInputManager.SignalStrength int strength) {
+        public void onSignalStrength(
+                @NonNull String inputId, @TvInputManager.SignalStrength int strength) {
         }
 
         /**
          * This is called when the session has been tuned to the given channel.
          *
          * @param channelUri The URI of a channel.
-         * @hide
          */
-        public void onTuned(String inputId, Uri channelUri) {
+        public void onTuned(@NonNull String inputId, @NonNull Uri channelUri) {
         }
     }
 
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
index f1f0af1..4a99715 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java
@@ -174,18 +174,15 @@
     public @interface TeletextAppState {}
 
     /**
-     * Show state of Teletext app.
-     * @hide
+     * State of Teletext app: show
      */
     public static final int TELETEXT_APP_STATE_SHOW = 1;
     /**
-     * Hide state of Teletext app.
-     * @hide
+     * State of Teletext app: hide
      */
     public static final int TELETEXT_APP_STATE_HIDE = 2;
     /**
-     * Error state of Teletext app.
-     * @hide
+     * State of Teletext app: error
      */
     public static final int TELETEXT_APP_STATE_ERROR = 3;
 
@@ -193,9 +190,7 @@
      * Key for package name in app link.
      * <p>Type: String
      *
-     * @see #registerAppLinkInfo(String, Bundle)
      * @see #sendAppLinkCommand(String, Bundle)
-     * @hide
      */
     public static final String KEY_PACKAGE_NAME = "package_name";
 
@@ -203,45 +198,15 @@
      * Key for class name in app link.
      * <p>Type: String
      *
-     * @see #registerAppLinkInfo(String, Bundle)
      * @see #sendAppLinkCommand(String, Bundle)
-     * @hide
      */
     public static final String KEY_CLASS_NAME = "class_name";
 
     /**
-     * Key for URI scheme in app link.
-     * <p>Type: String
-     *
-     * @see #registerAppLinkInfo(String, Bundle)
-     * @hide
-     */
-    public static final String KEY_URI_SCHEME = "uri_scheme";
-
-    /**
-     * Key for URI host in app link.
-     * <p>Type: String
-     *
-     * @see #registerAppLinkInfo(String, Bundle)
-     * @hide
-     */
-    public static final String KEY_URI_HOST = "uri_host";
-
-    /**
-     * Key for URI prefix in app link.
-     * <p>Type: String
-     *
-     * @see #registerAppLinkInfo(String, Bundle)
-     * @hide
-     */
-    public static final String KEY_URI_PREFIX = "uri_prefix";
-
-    /**
      * Key for command type in app link command.
      * <p>Type: String
      *
      * @see #sendAppLinkCommand(String, Bundle)
-     * @hide
      */
     public static final String KEY_COMMAND_TYPE = "command_type";
 
@@ -250,7 +215,6 @@
      * <p>Type: String
      *
      * @see #sendAppLinkCommand(String, Bundle)
-     * @hide
      */
     public static final String KEY_SERVICE_ID = "service_id";
 
@@ -259,10 +223,68 @@
      * <p>Type: String
      *
      * @see #sendAppLinkCommand(String, Bundle)
-     * @hide
      */
     public static final String KEY_BACK_URI = "back_uri";
 
+    /**
+     * Broadcast intent action to send app command to TV app.
+     *
+     * @see #sendAppLinkCommand(String, Bundle)
+     */
+    public static final String ACTION_APP_LINK_COMMAND =
+            "android.media.tv.interactive.action.APP_LINK_COMMAND";
+
+    /**
+     * Intent key for TV input ID. It's used to send app command to TV app.
+     * <p>Type: String
+     *
+     * @see #sendAppLinkCommand(String, Bundle)
+     * @see #ACTION_APP_LINK_COMMAND
+     */
+    public static final String INTENT_KEY_TV_INPUT_ID = "tv_input_id";
+
+    /**
+     * Intent key for TV interactive app ID. It's used to send app command to TV app.
+     * <p>Type: String
+     *
+     * @see #sendAppLinkCommand(String, Bundle)
+     * @see #ACTION_APP_LINK_COMMAND
+     * @see android.media.tv.interactive.TvInteractiveAppInfo#getId()
+     */
+    public static final String INTENT_KEY_INTERACTIVE_APP_SERVICE_ID = "interactive_app_id";
+
+    /**
+     * Intent key for TV channel URI. It's used to send app command to TV app.
+     * <p>Type: android.net.Uri
+     *
+     * @see #sendAppLinkCommand(String, Bundle)
+     * @see #ACTION_APP_LINK_COMMAND
+     */
+    public static final String INTENT_KEY_CHANNEL_URI = "channel_uri";
+
+    /**
+     * Intent key for broadcast-independent(BI) interactive app type. It's used to send app command
+     * to TV app.
+     * <p>Type: int
+     *
+     * @see #sendAppLinkCommand(String, Bundle)
+     * @see #ACTION_APP_LINK_COMMAND
+     * @see android.media.tv.interactive.TvInteractiveAppInfo#getSupportedTypes()
+     * @see android.media.tv.interactive.TvInteractiveAppView#createBiInteractiveApp(Uri, Bundle)
+     */
+    public static final String INTENT_KEY_BI_INTERACTIVE_APP_TYPE = "bi_interactive_app_type";
+
+    /**
+     * Intent key for broadcast-independent(BI) interactive app URI. It's used to send app command
+     * to TV app.
+     * <p>Type: android.net.Uri
+     *
+     * @see #sendAppLinkCommand(String, Bundle)
+     * @see #ACTION_APP_LINK_COMMAND
+     * @see android.media.tv.interactive.TvInteractiveAppView#createBiInteractiveApp(Uri, Bundle)
+     */
+    public static final String INTENT_KEY_BI_INTERACTIVE_APP_URI = "bi_interactive_app_uri";
+
     private final ITvInteractiveAppManager mService;
     private final int mUserId;
 
@@ -358,7 +380,7 @@
 
             @Override
             public void onCommandRequest(
-                    @TvInteractiveAppService.InteractiveAppServiceCommandType String cmdType,
+                    @TvInteractiveAppService.PlaybackCommandType String cmdType,
                     Bundle parameters,
                     int seq) {
                 synchronized (mSessionCallbackRecordMap) {
@@ -559,7 +581,6 @@
          * that implements {@link TvInteractiveAppService} interface.
          *
          * @param iAppServiceId The ID of the TV Interactive App service.
-         * @hide
          */
         public void onInteractiveAppServiceAdded(@NonNull String iAppServiceId) {
         }
@@ -571,7 +592,6 @@
          * App service package.
          *
          * @param iAppServiceId The ID of the TV Interactive App service.
-         * @hide
          */
         public void onInteractiveAppServiceRemoved(@NonNull String iAppServiceId) {
         }
@@ -583,7 +603,6 @@
          * re-installed or a newer version of the package exists becomes available/unavailable.
          *
          * @param iAppServiceId The ID of the TV Interactive App service.
-         * @hide
          */
         public void onInteractiveAppServiceUpdated(@NonNull String iAppServiceId) {
         }
@@ -730,8 +749,7 @@
     }
 
     /**
-     * Prepares TV Interactive App service for the given type.
-     * @hide
+     * Prepares TV Interactive App service environment for the given type.
      */
     public void prepare(@NonNull String tvIAppServiceId, int type) {
         try {
@@ -773,7 +791,6 @@
      * @param tvIAppServiceId The ID of TV interactive service which the command to be sent to. The
      *                        ID can be found in {@link TvInputInfo#getId()}.
      * @param command The command to be sent.
-     * @hide
      */
     public void sendAppLinkCommand(@NonNull String tvIAppServiceId, @NonNull Bundle command) {
         try {
@@ -1565,7 +1582,7 @@
         }
 
         void postCommandRequest(
-                final @TvInteractiveAppService.InteractiveAppServiceCommandType String cmdType,
+                final @TvInteractiveAppService.PlaybackCommandType String cmdType,
                 final Bundle parameters) {
             mHandler.post(new Runnable() {
                 @Override
@@ -1713,7 +1730,7 @@
          */
         public void onCommandRequest(
                 Session session,
-                @TvInteractiveAppService.InteractiveAppServiceCommandType String cmdType,
+                @TvInteractiveAppService.PlaybackCommandType String cmdType,
                 Bundle parameters) {
         }
 
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppService.java b/media/java/android/media/tv/interactive/TvInteractiveAppService.java
index 4716bed..c9856bf 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppService.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppService.java
@@ -32,6 +32,7 @@
 import android.media.tv.BroadcastInfoRequest;
 import android.media.tv.BroadcastInfoResponse;
 import android.media.tv.TvContentRating;
+import android.media.tv.TvInputInfo;
 import android.media.tv.TvInputManager;
 import android.media.tv.TvTrackInfo;
 import android.media.tv.TvView;
@@ -97,46 +98,82 @@
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
-    @StringDef(prefix = "INTERACTIVE_APP_SERVICE_COMMAND_TYPE_", value = {
-            INTERACTIVE_APP_SERVICE_COMMAND_TYPE_TUNE,
-            INTERACTIVE_APP_SERVICE_COMMAND_TYPE_TUNE_NEXT,
-            INTERACTIVE_APP_SERVICE_COMMAND_TYPE_TUNE_PREV,
-            INTERACTIVE_APP_SERVICE_COMMAND_TYPE_STOP,
-            INTERACTIVE_APP_SERVICE_COMMAND_TYPE_SET_STREAM_VOLUME,
-            INTERACTIVE_APP_SERVICE_COMMAND_TYPE_SELECT_TRACK
+    @StringDef(prefix = "PLAYBACK_COMMAND_TYPE_", value = {
+            PLAYBACK_COMMAND_TYPE_TUNE,
+            PLAYBACK_COMMAND_TYPE_TUNE_NEXT,
+            PLAYBACK_COMMAND_TYPE_TUNE_PREV,
+            PLAYBACK_COMMAND_TYPE_STOP,
+            PLAYBACK_COMMAND_TYPE_SET_STREAM_VOLUME,
+            PLAYBACK_COMMAND_TYPE_SELECT_TRACK
     })
-    public @interface InteractiveAppServiceCommandType {}
+    public @interface PlaybackCommandType {}
 
-    /** @hide */
-    public static final String INTERACTIVE_APP_SERVICE_COMMAND_TYPE_TUNE = "tune";
-    /** @hide */
-    public static final String INTERACTIVE_APP_SERVICE_COMMAND_TYPE_TUNE_NEXT = "tune_next";
-    /** @hide */
-    public static final String INTERACTIVE_APP_SERVICE_COMMAND_TYPE_TUNE_PREV = "tune_previous";
-    /** @hide */
-    public static final String INTERACTIVE_APP_SERVICE_COMMAND_TYPE_STOP = "stop";
-    /** @hide */
-    public static final String INTERACTIVE_APP_SERVICE_COMMAND_TYPE_SET_STREAM_VOLUME =
+    /**
+     * Playback command type: tune to the given channel.
+     * @see #COMMAND_PARAMETER_KEY_CHANNEL_URI
+     */
+    public static final String PLAYBACK_COMMAND_TYPE_TUNE = "tune";
+    /**
+     * Playback command type: tune to the next channel.
+     */
+    public static final String PLAYBACK_COMMAND_TYPE_TUNE_NEXT = "tune_next";
+    /**
+     * Playback command type: tune to the previous channel.
+     */
+    public static final String PLAYBACK_COMMAND_TYPE_TUNE_PREV = "tune_previous";
+    /**
+     * Playback command type: stop the playback.
+     */
+    public static final String PLAYBACK_COMMAND_TYPE_STOP = "stop";
+    /**
+     * Playback command type: set the volume.
+     */
+    public static final String PLAYBACK_COMMAND_TYPE_SET_STREAM_VOLUME =
             "set_stream_volume";
-    /** @hide */
-    public static final String INTERACTIVE_APP_SERVICE_COMMAND_TYPE_SELECT_TRACK = "select_track";
-    /** @hide */
+    /**
+     * Playback command type: select the given track.
+     */
+    public static final String PLAYBACK_COMMAND_TYPE_SELECT_TRACK = "select_track";
+    /**
+     * Playback command parameter: channel URI.
+     * <p>Type: android.net.Uri
+     *
+     * @see #PLAYBACK_COMMAND_TYPE_TUNE
+     */
     public static final String COMMAND_PARAMETER_KEY_CHANNEL_URI = "command_channel_uri";
-    /** @hide */
+    /**
+     * Playback command parameter: TV input ID.
+     * <p>Type: String
+     *
+     * @see TvInputInfo#getId()
+     */
     public static final String COMMAND_PARAMETER_KEY_INPUT_ID = "command_input_id";
-    /** @hide */
+    /**
+     * Playback command parameter: stream volume.
+     * <p>Type: float
+     *
+     * @see #PLAYBACK_COMMAND_TYPE_SET_STREAM_VOLUME
+     */
     public static final String COMMAND_PARAMETER_KEY_VOLUME = "command_volume";
-    /** @hide */
+    /**
+     * Playback command parameter: track type.
+     * <p>Type: int
+     *
+     * @see #PLAYBACK_COMMAND_TYPE_SELECT_TRACK
+     * @see TvTrackInfo#getType()
+     */
     public static final String COMMAND_PARAMETER_KEY_TRACK_TYPE = "command_track_type";
-    /** @hide */
+    /**
+     * Playback command parameter: track ID.
+     * <p>Type: String
+     *
+     * @see #PLAYBACK_COMMAND_TYPE_SELECT_TRACK
+     * @see TvTrackInfo#getId()
+     */
     public static final String COMMAND_PARAMETER_KEY_TRACK_ID = "command_track_id";
-    /** @hide */
-    public static final String COMMAND_PARAMETER_KEY_TRACK_SELECT_MODE =
-            "command_track_select_mode";
     /**
      * Command to quiet channel change. No channel banner or channel info is shown.
      * <p>Refer to HbbTV Spec 2.0.4 chapter A.2.4.3.
-     * @hide
      */
     public static final String COMMAND_PARAMETER_KEY_CHANGE_CHANNEL_QUIETLY =
             "command_change_channel_quietly";
@@ -145,9 +182,9 @@
     private final RemoteCallbackList<ITvInteractiveAppServiceCallback> mCallbacks =
             new RemoteCallbackList<>();
 
-    /** @hide */
     @Override
-    public final IBinder onBind(Intent intent) {
+    @Nullable
+    public final IBinder onBind(@NonNull Intent intent) {
         ITvInteractiveAppService.Stub tvIAppServiceBinder = new ITvInteractiveAppService.Stub() {
             @Override
             public void registerCallback(ITvInteractiveAppServiceCallback cb) {
@@ -210,23 +247,20 @@
      * Registers App link info.
      * @hide
      */
-    public void onRegisterAppLinkInfo(AppLinkInfo appLinkInfo) {
-        // TODO: make it abstract when unhide
+    public void onRegisterAppLinkInfo(@NonNull AppLinkInfo appLinkInfo) {
     }
 
     /**
      * Unregisters App link info.
      * @hide
      */
-    public void onUnregisterAppLinkInfo(AppLinkInfo appLinkInfo) {
-        // TODO: make it abstract when unhide
+    public void onUnregisterAppLinkInfo(@NonNull AppLinkInfo appLinkInfo) {
     }
 
     /**
      * Called when app link command is received.
      *
      * @see android.media.tv.interactive.TvInteractiveAppManager#sendAppLinkCommand(String, Bundle)
-     * @hide
      */
     public void onAppLinkCommand(@NonNull Bundle command) {
     }
@@ -318,7 +352,6 @@
          *
          * @param enable {@code true} if you want to enable the media view. {@code false}
          *            otherwise.
-         * @hide
          */
         public void setMediaViewEnabled(final boolean enable) {
             mHandler.post(new Runnable() {
@@ -353,7 +386,6 @@
 
         /**
          * Resets TvIAppService session.
-         * @hide
          */
         public void onResetInteractiveApp() {
         }
@@ -384,43 +416,37 @@
 
         /**
          * To toggle Digital Teletext Application if there is one in AIT app list.
-         * @param enable
-         * @hide
+         * @param enable {@code true} to enable teletext app; {@code false} otherwise.
          */
         public void onSetTeletextAppEnabled(boolean enable) {
         }
 
         /**
          * Receives current channel URI.
-         * @hide
          */
         public void onCurrentChannelUri(@Nullable Uri channelUri) {
         }
 
         /**
          * Receives logical channel number (LCN) of current channel.
-         * @hide
          */
         public void onCurrentChannelLcn(int lcn) {
         }
 
         /**
-         * Receives stream volume.
-         * @hide
+         * Receives current stream volume.
          */
         public void onStreamVolume(float volume) {
         }
 
         /**
          * Receives track list.
-         * @hide
          */
         public void onTrackInfoList(@NonNull List<TvTrackInfo> tracks) {
         }
 
         /**
          * Receives current TV input ID.
-         * @hide
          */
         public void onCurrentTvInputId(@Nullable String inputId) {
         }
@@ -460,7 +486,6 @@
          *
          * @param width The width of the media view.
          * @param height The height of the media view.
-         * @hide
          */
         public void onMediaViewSizeChanged(int width, int height) {
         }
@@ -470,7 +495,6 @@
          * implementation can override this method and return its own view.
          *
          * @return a view attached to the media window
-         * @hide
          */
         @Nullable
         public View onCreateMediaView() {
@@ -479,10 +503,8 @@
 
         /**
          * Releases TvInteractiveAppService session.
-         * @hide
          */
-        public void onRelease() {
-        }
+        public abstract void onRelease();
 
         /**
          * Called when the corresponding TV input tuned to a channel.
@@ -494,49 +516,42 @@
 
         /**
          * Called when the corresponding TV input selected to a track.
-         * @hide
          */
-        public void onTrackSelected(int type, String trackId) {
+        public void onTrackSelected(@TvTrackInfo.Type int type, @NonNull String trackId) {
         }
 
         /**
          * Called when the tracks are changed.
-         * @hide
          */
-        public void onTracksChanged(List<TvTrackInfo> tracks) {
+        public void onTracksChanged(@NonNull List<TvTrackInfo> tracks) {
         }
 
         /**
          * Called when video is available.
-         * @hide
          */
         public void onVideoAvailable() {
         }
 
         /**
          * Called when video is unavailable.
-         * @hide
          */
-        public void onVideoUnavailable(int reason) {
+        public void onVideoUnavailable(@TvInputManager.VideoUnavailableReason int reason) {
         }
 
         /**
          * Called when content is allowed.
-         * @hide
          */
         public void onContentAllowed() {
         }
 
         /**
          * Called when content is blocked.
-         * @hide
          */
-        public void onContentBlocked(TvContentRating rating) {
+        public void onContentBlocked(@NonNull TvContentRating rating) {
         }
 
         /**
          * Called when signal strength is changed.
-         * @hide
          */
         public void onSignalStrength(@TvInputManager.SignalStrength int strength) {
         }
@@ -550,60 +565,61 @@
 
         /**
          * Called when an advertisement response is received.
-         * @hide
          */
         public void onAdResponse(@NonNull AdResponse response) {
         }
 
-        /**
-         * TODO: JavaDoc of APIs related to input events.
-         * @hide
-         */
         @Override
         public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) {
             return false;
         }
 
-        /**
-         * @hide
-         */
         @Override
         public boolean onKeyLongPress(int keyCode, @NonNull KeyEvent event) {
             return false;
         }
 
-        /**
-         * @hide
-         */
         @Override
         public boolean onKeyMultiple(int keyCode, int count, @NonNull KeyEvent event) {
             return false;
         }
 
-        /**
-         * @hide
-         */
         @Override
         public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
             return false;
         }
 
         /**
-         * @hide
+         * Implement this method to handle touch screen motion events on the current session.
+         *
+         * @param event The motion event being received.
+         * @return If you handled the event, return {@code true}. If you want to allow the event to
+         *         be handled by the next receiver, return {@code false}.
+         * @see View#onTouchEvent
          */
         public boolean onTouchEvent(@NonNull MotionEvent event) {
             return false;
         }
 
         /**
-         * @hide
+         * Implement this method to handle trackball events on the current session.
+         *
+         * @param event The motion event being received.
+         * @return If you handled the event, return {@code true}. If you want to allow the event to
+         *         be handled by the next receiver, return {@code false}.
+         * @see View#onTrackballEvent
          */
         public boolean onTrackballEvent(@NonNull MotionEvent event) {
             return false;
         }
 
         /**
-         * @hide
+         * Implement this method to handle generic motion events on the current session.
+         *
+         * @param event The motion event being received.
+         * @return If you handled the event, return {@code true}. If you want to allow the event to
+         *         be handled by the next receiver, return {@code false}.
+         * @see View#onGenericMotionEvent
          */
         public boolean onGenericMotionEvent(@NonNull MotionEvent event) {
             return false;
@@ -693,13 +709,13 @@
         }
 
         /**
-         * requests a specific command to be processed by the related TV input.
+         * Sends a specific playback command to be processed by the related TV input.
+         *
          * @param cmdType type of the specific command
          * @param parameters parameters of the specific command
-         * @hide
          */
-        public void requestCommand(
-                @InteractiveAppServiceCommandType String cmdType, Bundle parameters) {
+        public void sendPlaybackCommandRequest(
+                @PlaybackCommandType @NonNull String cmdType, @Nullable Bundle parameters) {
             executeOrPostRunnableOnMainThread(new Runnable() {
                 @MainThread
                 @Override
@@ -721,9 +737,8 @@
 
         /**
          * Sets broadcast video bounds.
-         * @hide
          */
-        public void setVideoBounds(Rect rect) {
+        public void setVideoBounds(@NonNull Rect rect) {
             executeOrPostRunnableOnMainThread(new Runnable() {
                 @MainThread
                 @Override
@@ -744,7 +759,6 @@
 
         /**
          * Requests the URI of the current channel.
-         * @hide
          */
         public void requestCurrentChannelUri() {
             executeOrPostRunnableOnMainThread(new Runnable() {
@@ -767,7 +781,6 @@
 
         /**
          * Requests the logic channel number (LCN) of the current channel.
-         * @hide
          */
         public void requestCurrentChannelLcn() {
             executeOrPostRunnableOnMainThread(new Runnable() {
@@ -790,7 +803,6 @@
 
         /**
          * Requests stream volume.
-         * @hide
          */
         public void requestStreamVolume() {
             executeOrPostRunnableOnMainThread(new Runnable() {
@@ -813,7 +825,6 @@
 
         /**
          * Requests the list of {@link TvTrackInfo}.
-         * @hide
          */
         public void requestTrackInfoList() {
             executeOrPostRunnableOnMainThread(new Runnable() {
@@ -838,7 +849,6 @@
          * Requests current TV input ID.
          *
          * @see android.media.tv.TvInputInfo
-         * @hide
          */
         public void requestCurrentTvInputId() {
             executeOrPostRunnableOnMainThread(new Runnable() {
@@ -863,7 +873,6 @@
          * Sends an advertisement request to be processed by the related TV input.
          *
          * @param request The advertisement request
-         * @hide
          */
         public void requestAd(@NonNull final AdRequest request) {
             executeOrPostRunnableOnMainThread(new Runnable() {
@@ -1082,7 +1091,6 @@
         /**
          * Notifies when the digital teletext app state is changed.
          * @param state the current state.
-         * @hide
          */
         public final void notifyTeletextAppStateChanged(
                 @TvInteractiveAppManager.TeletextAppState int state) {
diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppView.java b/media/java/android/media/tv/interactive/TvInteractiveAppView.java
index 2922bae..773e54f 100755
--- a/media/java/android/media/tv/interactive/TvInteractiveAppView.java
+++ b/media/java/android/media/tv/interactive/TvInteractiveAppView.java
@@ -170,23 +170,20 @@
         }
     }
 
-    /** @hide */
     @Override
-    protected void onAttachedToWindow() {
+    public void onAttachedToWindow() {
         super.onAttachedToWindow();
         createSessionMediaView();
     }
 
-    /** @hide */
     @Override
-    protected void onDetachedFromWindow() {
+    public void onDetachedFromWindow() {
         removeSessionMediaView();
         super.onDetachedFromWindow();
     }
 
-    /** @hide */
     @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+    public void onLayout(boolean changed, int left, int top, int right, int bottom) {
         if (DEBUG) {
             Log.d(TAG, "onLayout (left=" + left + ", top=" + top + ", right=" + right
                     + ", bottom=" + bottom + ",)");
@@ -199,9 +196,8 @@
         }
     }
 
-    /** @hide */
     @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         mSurfaceView.measure(widthMeasureSpec, heightMeasureSpec);
         int width = mSurfaceView.getMeasuredWidth();
         int height = mSurfaceView.getMeasuredHeight();
@@ -211,9 +207,8 @@
                         childState << MEASURED_HEIGHT_STATE_SHIFT));
     }
 
-    /** @hide */
     @Override
-    protected void onVisibilityChanged(View changedView, int visibility) {
+    public void onVisibilityChanged(@NonNull View changedView, int visibility) {
         super.onVisibilityChanged(changedView, visibility);
         mSurfaceView.setVisibility(visibility);
         if (visibility == View.VISIBLE) {
@@ -244,7 +239,6 @@
 
     /**
      * Resets this TvInteractiveAppView.
-     * @hide
      */
     public void reset() {
         if (DEBUG) Log.d(TAG, "reset()");
@@ -330,7 +324,11 @@
 
     /**
      * Dispatches an unhandled input event to the next receiver.
-     * @hide
+     *
+     * It gives the host application a chance to dispatch the unhandled input events.
+     *
+     * @param event The input event.
+     * @return {@code true} if the event was handled by the view, {@code false} otherwise.
      */
     public boolean dispatchUnhandledInputEvent(@NonNull InputEvent event) {
         if (mOnUnhandledInputEventListener != null) {
@@ -349,21 +347,28 @@
      * @param event The input event.
      * @return If you handled the event, return {@code true}. If you want to allow the event to be
      *         handled by the next receiver, return {@code false}.
-     * @hide
      */
     public boolean onUnhandledInputEvent(@NonNull InputEvent event) {
         return false;
     }
 
     /**
-     * Registers a callback to be invoked when an input event is not handled
+     * Sets a listener to be invoked when an input event is not handled
      * by the TV Interactive App.
      *
      * @param listener The callback to be invoked when the unhandled input event is received.
-     * @hide
      */
-    public void setOnUnhandledInputEventListener(@NonNull OnUnhandledInputEventListener listener) {
+    public void setOnUnhandledInputEventListener(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull OnUnhandledInputEventListener listener) {
         mOnUnhandledInputEventListener = listener;
+        // TODO: handle CallbackExecutor
+    }
+    /**
+     * Clears the {@link OnUnhandledInputEventListener}.
+     */
+    public void clearOnUnhandledInputEventListener() {
+        mOnUnhandledInputEventListener = null;
     }
 
     @Override
@@ -427,7 +432,6 @@
 
     /**
      * Resets the interactive application.
-     * @hide
      */
     public void resetInteractiveApp() {
         if (DEBUG) {
@@ -440,9 +444,11 @@
 
     /**
      * Sends current channel URI to related TV interactive app.
-     * @hide
+     *
+     * @param channelUri The current channel URI; {@code null} if there is no currently tuned
+     *                   channel.
      */
-    public void sendCurrentChannelUri(Uri channelUri) {
+    public void sendCurrentChannelUri(@Nullable Uri channelUri) {
         if (DEBUG) {
             Log.d(TAG, "sendCurrentChannelUri");
         }
@@ -453,7 +459,6 @@
 
     /**
      * Sends current channel logical channel number (LCN) to related TV interactive app.
-     * @hide
      */
     public void sendCurrentChannelLcn(int lcn) {
         if (DEBUG) {
@@ -466,7 +471,6 @@
 
     /**
      * Sends stream volume to related TV interactive app.
-     * @hide
      */
     public void sendStreamVolume(float volume) {
         if (DEBUG) {
@@ -479,9 +483,8 @@
 
     /**
      * Sends track info list to related TV interactive app.
-     * @hide
      */
-    public void sendTrackInfoList(List<TvTrackInfo> tracks) {
+    public void sendTrackInfoList(@Nullable List<TvTrackInfo> tracks) {
         if (DEBUG) {
             Log.d(TAG, "sendTrackInfoList");
         }
@@ -496,7 +499,6 @@
      * @param inputId The current TV input ID whose channel is tuned. {@code null} if no channel is
      *                tuned.
      * @see android.media.tv.TvInputInfo
-     * @hide
      */
     public void sendCurrentTvInputId(@Nullable String inputId) {
         if (DEBUG) {
@@ -588,8 +590,11 @@
 
     /**
      * To toggle Digital Teletext Application if there is one in AIT app list.
-     * @param enable
-     * @hide
+     *
+     * <p>A Teletext Application is a broadcast-related application to display text and basic
+     * graphics.
+     *
+     * @param enable {@code true} to enable Teletext app; {@code false} to disable it.
      */
     public void setTeletextAppEnabled(boolean enable) {
         if (DEBUG) {
@@ -607,17 +612,17 @@
         // TODO: unhide the following public APIs
 
         /**
-         * This is called when a command is requested to be processed by the related TV input.
+         * This is called when a playback command is requested to be processed by the related TV
+         * input.
          *
          * @param iAppServiceId The ID of the TV interactive app service bound to this view.
          * @param cmdType type of the command
          * @param parameters parameters of the command
-         * @hide
          */
-        public void onCommandRequest(
+        public void onPlaybackCommandRequest(
                 @NonNull String iAppServiceId,
-                @NonNull @TvInteractiveAppService.InteractiveAppServiceCommandType String cmdType,
-                @Nullable Bundle parameters) {
+                @NonNull @TvInteractiveAppService.PlaybackCommandType String cmdType,
+                @NonNull Bundle parameters) {
         }
 
         /**
@@ -656,7 +661,6 @@
          *
          * @param iAppServiceId The ID of the TV interactive app service bound to this view.
          * @param state digital teletext app current state.
-         * @hide
          */
         public void onTeletextAppStateChanged(
                 @NonNull String iAppServiceId,
@@ -664,59 +668,55 @@
         }
 
         /**
-         * This is called when {@link TvInteractiveAppService.Session#SetVideoBounds} is called.
+         * This is called when {@link TvInteractiveAppService.Session#setVideoBounds(Rect)} is
+         * called.
          *
          * @param iAppServiceId The ID of the TV interactive app service bound to this view.
-         * @hide
          */
         public void onSetVideoBounds(@NonNull String iAppServiceId, @NonNull Rect rect) {
         }
 
         /**
-         * This is called when {@link TvInteractiveAppService.Session#RequestCurrentChannelUri} is
+         * This is called when {@link TvInteractiveAppService.Session#requestCurrentChannelUri()} is
          * called.
          *
          * @param iAppServiceId The ID of the TV interactive app service bound to this view.
-         * @hide
          */
         public void onRequestCurrentChannelUri(@NonNull String iAppServiceId) {
         }
 
         /**
-         * This is called when {@link TvInteractiveAppService.Session#RequestCurrentChannelLcn} is
+         * This is called when {@link TvInteractiveAppService.Session#requestCurrentChannelLcn()} is
          * called.
          *
          * @param iAppServiceId The ID of the TV interactive app service bound to this view.
-         * @hide
          */
         public void onRequestCurrentChannelLcn(@NonNull String iAppServiceId) {
         }
 
         /**
-         * This is called when {@link TvInteractiveAppService.Session#RequestStreamVolume} is
+         * This is called when {@link TvInteractiveAppService.Session#requestStreamVolume()} is
          * called.
          *
          * @param iAppServiceId The ID of the TV interactive app service bound to this view.
-         * @hide
          */
         public void onRequestStreamVolume(@NonNull String iAppServiceId) {
         }
 
         /**
-         * This is called when {@link TvInteractiveAppService.Session#RequestTrackInfoList} is
+         * This is called when {@link TvInteractiveAppService.Session#requestTrackInfoList()} is
          * called.
          *
          * @param iAppServiceId The ID of the TV interactive app service bound to this view.
-         * @hide
          */
         public void onRequestTrackInfoList(@NonNull String iAppServiceId) {
         }
 
         /**
-         * This is called when {@link TvIAppService.Session#RequestCurrentTvInputId} is called.
+         * This is called when {@link TvInteractiveAppService.Session#requestCurrentTvInputId()} is
+         * called.
          *
          * @param iAppServiceId The ID of the TV interactive app service bound to this view.
-         * @hide
          */
         public void onRequestCurrentTvInputId(@NonNull String iAppServiceId) {
         }
@@ -725,7 +725,6 @@
 
     /**
      * Interface definition for a callback to be invoked when the unhandled input event is received.
-     * @hide
      */
     public interface OnUnhandledInputEventListener {
         /**
@@ -818,7 +817,7 @@
         @Override
         public void onCommandRequest(
                 Session session,
-                @TvInteractiveAppService.InteractiveAppServiceCommandType String cmdType,
+                @TvInteractiveAppService.PlaybackCommandType String cmdType,
                 Bundle parameters) {
             if (DEBUG) {
                 Log.d(TAG, "onCommandRequest (cmdType=" + cmdType + ", parameters="
@@ -833,7 +832,8 @@
                     mCallbackExecutor.execute(() -> {
                         synchronized (mCallbackLock) {
                             if (mCallback != null) {
-                                mCallback.onCommandRequest(mIAppServiceId, cmdType, parameters);
+                                mCallback.onPlaybackCommandRequest(
+                                        mIAppServiceId, cmdType, parameters);
                             }
                         }
                     });
diff --git a/media/java/android/media/tv/tuner/filter/SharedFilter.java b/media/java/android/media/tv/tuner/filter/SharedFilter.java
index 056c5d5..740ab9c 100644
--- a/media/java/android/media/tv/tuner/filter/SharedFilter.java
+++ b/media/java/android/media/tv/tuner/filter/SharedFilter.java
@@ -92,9 +92,21 @@
                     synchronized (mCallbackLock) {
                         if (mCallback != null) {
                             mCallback.onFilterEvent(this, events);
+                        } else {
+                            for (FilterEvent event : events) {
+                                if (event instanceof MediaEvent) {
+                                    ((MediaEvent)event).release();
+                                }
+                            }
                         }
                     }
                 });
+            } else {
+                for (FilterEvent event : events) {
+                    if (event instanceof MediaEvent) {
+                        ((MediaEvent)event).release();
+                    }
+                }
             }
         }
     }
@@ -187,6 +199,8 @@
             if (mIsClosed) {
                 return;
             }
+            mCallback = null;
+            mExecutor = null;
             nativeSharedClose();
             mIsClosed = true;
          }
diff --git a/media/jni/android_media_ImageWriter.cpp b/media/jni/android_media_ImageWriter.cpp
index 2e419a6..eca26dc 100644
--- a/media/jni/android_media_ImageWriter.cpp
+++ b/media/jni/android_media_ImageWriter.cpp
@@ -460,8 +460,6 @@
     } else {
         // Set consumer buffer format to user specified format
         android_dataspace nativeDataspace = static_cast<android_dataspace>(dataSpace);
-        int userFormat = static_cast<int>(mapHalFormatDataspaceToPublicFormat(
-            hardwareBufferFormat, nativeDataspace));
         res = native_window_set_buffers_format(anw.get(), hardwareBufferFormat);
         if (res != OK) {
             ALOGE("%s: Unable to configure consumer native buffer format to %#x",
@@ -478,20 +476,29 @@
             return 0;
         }
         ctx->setBufferDataSpace(nativeDataspace);
-        surfaceFormat = userFormat;
+        surfaceFormat = static_cast<int32_t>(mapHalFormatDataspaceToPublicFormat(
+            hardwareBufferFormat, nativeDataspace));
     }
 
     ctx->setBufferFormat(surfaceFormat);
     env->SetIntField(thiz,
             gImageWriterClassInfo.mWriterFormat, reinterpret_cast<jint>(surfaceFormat));
 
-    res = native_window_set_usage(anw.get(), ndkUsage);
-    if (res != OK) {
-        ALOGE("%s: Configure usage %08x for format %08x failed: %s (%d)",
-              __FUNCTION__, static_cast<unsigned int>(ndkUsage),
-              surfaceFormat, strerror(-res), res);
-        jniThrowRuntimeException(env, "Failed to SW_WRITE_OFTEN configure usage");
-        return 0;
+    // ndkUsage == -1 means setUsage in ImageWriter class is not called.
+    // skip usage setting if setUsage in ImageWriter is not called and imageformat is opaque.
+    if (!(ndkUsage == -1 && isFormatOpaque(surfaceFormat))) {
+        if (ndkUsage == -1) {
+            ndkUsage = GRALLOC_USAGE_SW_WRITE_OFTEN;
+        }
+        res = native_window_set_usage(anw.get(), ndkUsage);
+        if (res != OK) {
+            ALOGE("%s: Configure usage %08x for format %08x failed: %s (%d)",
+                  __FUNCTION__, static_cast<unsigned int>(ndkUsage),
+                  surfaceFormat, strerror(-res), res);
+            jniThrowRuntimeException(env,
+                                     "Failed to SW_WRITE_OFTEN configure usage");
+            return 0;
+        }
     }
 
     int minUndequeuedBufferCount = 0;
@@ -952,7 +959,7 @@
     return buffer->getHeight();
 }
 
-static jint Image_getFormat(JNIEnv* env, jobject thiz) {
+static jint Image_getFormat(JNIEnv* env, jobject thiz, jlong dataSpace) {
     ALOGV("%s", __FUNCTION__);
     GraphicBuffer* buffer;
     Image_getNativeContext(env, thiz, &buffer, NULL);
@@ -962,9 +969,9 @@
         return 0;
     }
 
-    // ImageWriter doesn't support data space yet, assuming it is unknown.
     PublicFormat publicFmt = mapHalFormatDataspaceToPublicFormat(buffer->getPixelFormat(),
-                                                                 HAL_DATASPACE_UNKNOWN);
+        static_cast<android_dataspace>(dataSpace));
+
     return static_cast<jint>(publicFmt);
 }
 
@@ -1031,14 +1038,14 @@
 }
 
 static jobjectArray Image_createSurfacePlanes(JNIEnv* env, jobject thiz,
-        int numPlanes, int writerFormat) {
+        int numPlanes, int writerFormat, long dataSpace) {
     ALOGV("%s: create SurfacePlane array with size %d", __FUNCTION__, numPlanes);
     int rowStride, pixelStride;
     uint8_t *pData;
     uint32_t dataSize;
     jobject byteBuffer;
 
-    int format = Image_getFormat(env, thiz);
+    int format = Image_getFormat(env, thiz, dataSpace);
     if (isFormatOpaque(format) && numPlanes > 0) {
         String8 msg;
         msg.appendFormat("Format 0x%x is opaque, thus not writable, the number of planes (%d)"
@@ -1108,11 +1115,11 @@
 };
 
 static JNINativeMethod gImageMethods[] = {
-    {"nativeCreatePlanes",      "(II)[Landroid/media/ImageWriter$WriterSurfaceImage$SurfacePlane;",
+    {"nativeCreatePlanes",      "(IIJ)[Landroid/media/ImageWriter$WriterSurfaceImage$SurfacePlane;",
                                                                (void*)Image_createSurfacePlanes },
     {"nativeGetWidth",          "()I",                         (void*)Image_getWidth },
     {"nativeGetHeight",         "()I",                         (void*)Image_getHeight },
-    {"nativeGetFormat",         "()I",                         (void*)Image_getFormat },
+    {"nativeGetFormat",         "(J)I",                        (void*)Image_getFormat },
     {"nativeGetHardwareBuffer", "()Landroid/hardware/HardwareBuffer;",
                                                                (void*)Image_getHardwareBuffer },
 };
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 68dd8d0..9ed1ac0 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -4147,6 +4147,7 @@
 
     Result r = filterClient->close();
     filterClient->decStrong(filter);
+    filterClient = nullptr;
     if (shared) {
         env->SetLongField(filter, gFields.sharedFilterContext, 0);
     } else {
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java
index d3d5a08..77fc171 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java
@@ -434,7 +434,8 @@
         @NonNull
         public Builder setRatType(@Annotation.NetworkType int ratType) {
             if (!CollectionUtils.contains(TelephonyManager.getAllNetworkTypes(), ratType)
-                    && ratType != TelephonyManager.NETWORK_TYPE_UNKNOWN) {
+                    && ratType != TelephonyManager.NETWORK_TYPE_UNKNOWN
+                    && ratType != NetworkTemplate.NETWORK_TYPE_5G_NSA) {
                 throw new IllegalArgumentException("Invalid ratType " + ratType);
             }
             mRatType = ratType;
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java
index cad8075..dba3991 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java
@@ -652,7 +652,9 @@
      *
      * @hide
      */
-    public boolean matches(NetworkIdentity ident) {
+    @SystemApi(client = MODULE_LIBRARIES)
+    public boolean matches(@NonNull NetworkIdentity ident) {
+        Objects.requireNonNull(ident);
         if (!matchesMetered(ident)) return false;
         if (!matchesRoaming(ident)) return false;
         if (!matchesDefaultNetwork(ident)) return false;
diff --git a/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java b/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java
index f5aa652..b4e84dd 100644
--- a/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java
+++ b/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java
@@ -27,9 +27,7 @@
 import android.net.NetworkPolicy;
 import android.net.NetworkPolicyManager;
 import android.net.NetworkTemplate;
-import android.net.wifi.WifiInfo;
 import android.os.AsyncTask;
-import android.text.TextUtils;
 import android.util.RecurrenceRule;
 
 import com.google.android.collect.Lists;
@@ -124,7 +122,7 @@
         if (policy != null) {
             return policy;
         } else {
-            return getPolicy(buildUnquotedNetworkTemplate(template));
+            return getPolicy(template);
         }
     }
 
@@ -207,21 +205,4 @@
         policy.clearSnooze();
         writeAsync();
     }
-
-    /**
-     * Build a revised {@link NetworkTemplate} that matches the same rule, but
-     * with an unquoted {@link NetworkTemplate#getNetworkId()}. Used to work
-     * around legacy bugs.
-     */
-    private static NetworkTemplate buildUnquotedNetworkTemplate(NetworkTemplate template) {
-        if (template == null) return null;
-        final String networkId = template.getNetworkId();
-        final String strippedNetworkId = WifiInfo.sanitizeSsid(networkId);
-        if (!TextUtils.equals(strippedNetworkId, networkId)) {
-            return new NetworkTemplate(
-                    template.getMatchRule(), template.getSubscriberId(), strippedNetworkId);
-        } else {
-            return null;
-        }
-    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java
index b56ae38..4939e04 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java
@@ -88,14 +88,15 @@
     }
 
     /**
-     * Determine whether the device is plugged in (USB, power, or wireless).
+     * Determine whether the device is plugged in (USB, power, wireless or dock).
      *
      * @return true if the device is plugged in.
      */
     public boolean isPluggedIn() {
         return plugged == BatteryManager.BATTERY_PLUGGED_AC
                 || plugged == BatteryManager.BATTERY_PLUGGED_USB
-                || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
+                || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS
+                || plugged == BatteryManager.BATTERY_PLUGGED_DOCK;
     }
 
     /**
@@ -118,6 +119,15 @@
     }
 
     /**
+     * Determine whether the device is plugged in dock.
+     *
+     * @return true if the device is plugged in dock
+     */
+    public boolean isPluggedInDock() {
+        return plugged == BatteryManager.BATTERY_PLUGGED_DOCK;
+    }
+
+    /**
      * Whether or not the device is charged. Note that some devices never return 100% for
      * battery level, so this allows either battery level or status to determine if the
      * battery is charged.
diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/OWNERS b/packages/SettingsLib/src/com/android/settingslib/mobile/OWNERS
new file mode 100644
index 0000000..ab9b5dc
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/mobile/OWNERS
@@ -0,0 +1,4 @@
+# Default reviewers for this and subdirectories.
+bonianchen@google.com
+
+# Emergency approvers in case the above are not available
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
index cff45c6..30c6645 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
@@ -16,7 +16,6 @@
 
 package com.android.settingslib.net;
 
-import static android.net.TrafficStats.MB_IN_BYTES;
 import static android.telephony.TelephonyManager.SIM_STATE_READY;
 import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
 import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
@@ -49,6 +48,7 @@
     private static final StringBuilder PERIOD_BUILDER = new StringBuilder(50);
     private static final java.util.Formatter PERIOD_FORMATTER = new java.util.Formatter(
             PERIOD_BUILDER, Locale.getDefault());
+    private static final long MB_IN_BYTES = 1024 * 1024;
 
     private final Context mContext;
     private final NetworkPolicyManager mPolicyManager;
@@ -237,10 +237,8 @@
         final int matchRule = networkTemplate.getMatchRule();
         switch (matchRule) {
             case NetworkTemplate.MATCH_MOBILE:
-            case NetworkTemplate.MATCH_MOBILE_WILDCARD:
                 return ConnectivityManager.TYPE_MOBILE;
             case NetworkTemplate.MATCH_WIFI:
-            case NetworkTemplate.MATCH_WIFI_WILDCARD:
                 return  ConnectivityManager.TYPE_WIFI;
             case NetworkTemplate.MATCH_ETHERNET:
                 return  ConnectivityManager.TYPE_ETHERNET;
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
index afd44d5..386a47a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
@@ -63,14 +63,32 @@
     private static NetworkTemplate getNormalizedMobileTemplate(
             TelephonyManager telephonyManager, int subId) {
         final NetworkTemplate mobileTemplate = getMobileTemplateForSubId(telephonyManager, subId);
-        final String[] mergedSubscriberIds = telephonyManager
-                .createForSubscriptionId(subId).getMergedImsisFromGroup();
+        final Set<String> mergedSubscriberIds = Set.of(telephonyManager
+                .createForSubscriptionId(subId).getMergedImsisFromGroup());
         if (ArrayUtils.isEmpty(mergedSubscriberIds)) {
             Log.i(TAG, "mergedSubscriberIds is null.");
             return mobileTemplate;
         }
 
-        return NetworkTemplate.normalize(mobileTemplate, mergedSubscriberIds);
+        return normalizeMobileTemplate(mobileTemplate, mergedSubscriberIds);
+    }
+
+    private static NetworkTemplate normalizeMobileTemplate(
+            NetworkTemplate template, Set<String> mergedSet) {
+        if (template.getSubscriberIds().isEmpty()) return template;
+        // The input template should have at most 1 subscriberId.
+        final String subscriberId = template.getSubscriberIds().iterator().next();
+
+        if (mergedSet.contains(subscriberId)) {
+            // Requested template subscriber is part of the merge group; return
+            // a template that matches all merged subscribers.
+            return new NetworkTemplate.Builder(template.getMatchRule())
+                    .setSubscriberIds(mergedSet)
+                    .setWifiNetworkKeys(template.getWifiNetworkKeys())
+                    .setMeteredness(NetworkStats.METERED_YES).build();
+        }
+
+        return template;
     }
 
     private static NetworkTemplate getMobileTemplateForSubId(
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java
index 43c05b8..504390c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java
@@ -53,8 +53,9 @@
             long totalUsage = 0L;
             long totalForeground = 0L;
             for (int uid : mUids) {
-                final NetworkStats stats = mNetworkStatsManager.queryDetailsForUid(
-                        mNetworkTemplate, start, end, uid);
+                final NetworkStats stats = mNetworkStatsManager.queryDetailsForUidTagState(
+                        mNetworkTemplate, start, end, uid, NetworkStats.Bucket.TAG_NONE,
+                        NetworkStats.Bucket.STATE_ALL);
                 final long usage = getTotalUsage(stats);
                 if (usage > 0L) {
                     totalUsage += usage;
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/OWNERS b/packages/SettingsLib/src/com/android/settingslib/net/OWNERS
new file mode 100644
index 0000000..ab9b5dc
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/net/OWNERS
@@ -0,0 +1,4 @@
+# Default reviewers for this and subdirectories.
+bonianchen@google.com
+
+# Emergency approvers in case the above are not available
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java b/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
index 02326ea..623eb33 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
@@ -17,6 +17,7 @@
 package com.android.settingslib.net;
 
 import android.app.AppGlobals;
+import android.app.usage.NetworkStats;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
@@ -116,13 +117,13 @@
                 detail.label = res.getString(R.string.process_kernel_label);
                 detail.icon = pm.getDefaultActivityIcon();
                 return detail;
-            case TrafficStats.UID_REMOVED:
+            case NetworkStats.Bucket.UID_REMOVED:
                 detail.label = res.getString(UserManager.supportsMultipleUsers()
                         ? R.string.data_usage_uninstalled_apps_users
                         : R.string.data_usage_uninstalled_apps);
                 detail.icon = pm.getDefaultActivityIcon();
                 return detail;
-            case TrafficStats.UID_TETHERING:
+            case NetworkStats.Bucket.UID_TETHERING:
                 final TetheringManager tm = mContext.getSystemService(TetheringManager.class);
                 detail.label = res.getString(Utils.getTetheringLabel(tm));
                 detail.icon = pm.getDefaultActivityIcon();
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index 1601043..8e9e02a 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -37,6 +37,9 @@
     <!-- When the lock screen is showing and the phone plugged in, and the battery is not fully charged, say that it's wirelessly charging. [CHAR LIMIT=50]  -->
     <string name="keyguard_plugged_in_wireless"><xliff:g id="percentage" example="20%">%s</xliff:g> • Charging wirelessly</string>
 
+    <!-- When the lock screen is showing and the phone plugged in, and the battery is not fully charged, say that it's dock charging. [CHAR LIMIT=50]  -->
+    <string name="keyguard_plugged_in_dock"><xliff:g id="percentage" example="20%">%s</xliff:g> • Charging Dock</string>
+
     <!-- When the lock screen is showing and the phone plugged in, and the battery
          is not fully charged, say that it's charging.  -->
     <string name="keyguard_plugged_in"><xliff:g id="percentage">%s</xliff:g> • Charging</string>
diff --git a/packages/SystemUI/res/drawable/ic_list.xml b/packages/SystemUI/res/drawable/ic_list.xml
deleted file mode 100644
index 7ef5299..0000000
--- a/packages/SystemUI/res/drawable/ic_list.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    Copyright (C) 2021 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.
--->
-
-<!-- Remove when Fgs manager tile is removed -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="48dp"
-    android:height="48dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
-    <path
-        android:pathData="M2,4h4v4h-4z"
-        android:fillColor="#000000"/>
-    <path
-        android:pathData="M8,4h14v4h-14z"
-        android:fillColor="#000000"/>
-    <path
-        android:pathData="M2,10h4v4h-4z"
-        android:fillColor="#000000"/>
-    <path
-        android:pathData="M8,10h14v4h-14z"
-        android:fillColor="#000000"/>
-    <path
-        android:pathData="M2,16h4v4h-4z"
-        android:fillColor="#000000"/>
-    <path
-        android:pathData="M8,16h14v4h-14z"
-        android:fillColor="#000000"/>
-</vector>
diff --git a/packages/SystemUI/res/layout/controls_detail_dialog.xml b/packages/SystemUI/res/layout/controls_detail_dialog.xml
index 28fc863..4d2317c 100644
--- a/packages/SystemUI/res/layout/controls_detail_dialog.xml
+++ b/packages/SystemUI/res/layout/controls_detail_dialog.xml
@@ -15,47 +15,52 @@
      limitations under the License.
 -->
 
-<LinearLayout
+<FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/control_detail_root"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical"
-    android:background="@android:color/black">
+    android:layout_height="match_parent">
   <LinearLayout
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="horizontal"
-    android:layout_marginBottom="4dp">
-    <ImageView
-        android:id="@+id/control_detail_close"
-        android:contentDescription="@string/accessibility_desc_close"
-        android:src="@drawable/ic_arrow_back"
-        android:background="?android:attr/selectableItemBackgroundBorderless"
-        android:tint="@color/control_primary_text"
-        android:layout_width="48dp"
-        android:layout_height="48dp"
-        android:padding="12dp" />
-    <Space
-        android:layout_width="0dp"
-        android:layout_weight="1"
-        android:layout_height="1dp" />
-    <ImageView
-        android:id="@+id/control_detail_open_in_app"
-        android:contentDescription="@string/controls_open_app"
-        android:src="@drawable/ic_open_in_new"
-        android:background="?android:attr/selectableItemBackgroundBorderless"
-        android:tint="@color/control_primary_text"
-        android:layout_width="48dp"
-        android:layout_height="48dp"
-        android:padding="12dp" />
-  </LinearLayout>
-
-  <FrameLayout
-      android:id="@+id/controls_activity_view"
+      android:id="@+id/control_task_view_container"
       android:layout_width="match_parent"
-      android:layout_height="0dp"
-      android:layout_weight="1"
-      android:orientation="vertical" />
-</LinearLayout>
+      android:layout_height="match_parent"
+      android:layout_gravity="right|top"
+      android:layout_marginRight="@dimen/controls_task_view_right_margin"
+      android:orientation="vertical">
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        android:layout_marginBottom="4dp">
+      <ImageView
+          android:id="@+id/control_detail_close"
+          android:contentDescription="@string/accessibility_desc_close"
+          android:src="@drawable/ic_close"
+          android:background="?android:attr/selectableItemBackgroundBorderless"
+          android:tint="@color/control_primary_text"
+          android:layout_width="48dp"
+          android:layout_height="48dp"
+          android:padding="12dp" />
+      <Space
+          android:layout_width="0dp"
+          android:layout_weight="1"
+          android:layout_height="1dp" />
+      <ImageView
+          android:id="@+id/control_detail_open_in_app"
+          android:contentDescription="@string/controls_open_app"
+          android:src="@drawable/ic_open_in_new"
+          android:background="?android:attr/selectableItemBackgroundBorderless"
+          android:tint="@color/control_primary_text"
+          android:layout_width="48dp"
+          android:layout_height="48dp"
+          android:padding="12dp" />
+    </LinearLayout>
+
+    <FrameLayout
+        android:id="@+id/controls_activity_view"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1" />
+  </LinearLayout>
+</FrameLayout>
 
diff --git a/packages/SystemUI/res/values-sw600dp-land/dimens.xml b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
index 3cfe056..89d046b 100644
--- a/packages/SystemUI/res/values-sw600dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
@@ -25,4 +25,8 @@
     <!-- margin from keyguard status bar to clock. For split shade it should be
          keyguard_split_shade_top_margin - status_bar_header_height_keyguard = 8dp -->
     <dimen name="keyguard_clock_top_margin">8dp</dimen>
+
+    <!-- Limit the TaskView to this percentage of the overall screen width (0.0 - 1.0) -->
+    <item name="controls_task_view_width_percentage" translatable="false" format="float" type="dimen">0.45</item>
+    <dimen name="controls_task_view_right_margin">8dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 461a598..81e3e04 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -194,6 +194,7 @@
     <color name="control_enabled_cool_foreground">@color/GM2_blue_300</color>
     <color name="control_thumbnail_tint">#33000000</color>
     <color name="control_thumbnail_shadow_color">@*android:color/black</color>
+    <color name="controls_task_view_bg">#CC191C1D</color>
 
     <!-- Docked misalignment message -->
     <color name="misalignment_text_color">#F28B82</color>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index fc2756e..9d7cf1a 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -82,7 +82,7 @@
 
     <!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" -->
     <string name="quick_settings_tiles_stock" translatable="false">
-        internet,bt,flashlight,dnd,alarm,airplane,controls,wallet,rotation,battery,cast,screenrecord,mictoggle,cameratoggle,location,hotspot,inversion,saver,dark,work,night,reverse,reduce_brightness,qr_code_scanner,onehanded,fgsmanager,color_correction
+        internet,bt,flashlight,dnd,alarm,airplane,controls,wallet,rotation,battery,cast,screenrecord,mictoggle,cameratoggle,location,hotspot,inversion,saver,dark,work,night,reverse,reduce_brightness,qr_code_scanner,onehanded,color_correction
     </string>
 
     <!-- The tiles to display in QuickSettings -->
@@ -581,6 +581,9 @@
     <!-- Whether to use the split 2-column notification shade -->
     <bool name="config_use_split_notification_shade">false</bool>
 
+    <!-- Whether notification header should never show section headers. -->
+    <bool name="config_notification_never_show_section_headers">false</bool>
+
     <!-- Default udfps icon. Same path as ic_fingerprint.xml -->
     <string name="config_udfpsIcon" translatable="false">
         M25.5,16.3283C28.47,14.8433 31.9167,14 35.5834,14C39.2501,14 42.6968,14.8433 45.6668,16.3283
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 67d5b2f..af7ef53 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1052,6 +1052,9 @@
     <dimen name="controls_setup_subtitle">14sp</dimen>
     <dimen name="controls_setup_vertical_padding">52dp</dimen>
     <dimen name="controls_detail_dialog_header_height">52dp</dimen>
+    <!-- Limit the TaskView to this percentage of the overall screen width (0.0 - 1.0) -->
+    <item name="controls_task_view_width_percentage" translatable="false" format="float" type="dimen">1.0</item>
+    <dimen name="controls_task_view_right_margin">0dp</dimen>
 
     <!-- Home Controls activity view detail panel-->
     <dimen name="controls_activity_view_corner_radius">@*android:dimen/config_bottomDialogCornerRadius</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 7384ccc..6eab2b2 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -796,6 +796,9 @@
     <!-- Indication on the keyguard that is shown when the device is charging slowly. Should match keyguard_plugged_in_charging_slowly [CHAR LIMIT=50]-->
     <string name="keyguard_indication_charging_time_slowly"><xliff:g id="percentage">%2$s</xliff:g> • Charging slowly • Full in <xliff:g id="charging_time_left" example="4 hr, 2 min">%1$s</xliff:g></string>
 
+    <!-- Indication on the keyguard that is shown when the device is dock charging. [CHAR LIMIT=80]-->
+    <string name="keyguard_indication_charging_time_dock"><xliff:g id="percentage" example="20%">%2$s</xliff:g> • Charging Dock • Full in <xliff:g id="charging_time_left" example="4 hr, 2 min">%1$s</xliff:g></string>
+
     <!-- Related to user switcher --><skip/>
 
     <!-- Accessibility label for the button that opens the user switcher. -->
@@ -2355,6 +2358,11 @@
     <!-- Title for User Switch dialog. [CHAR LIMIT=20] -->
     <string name="qs_user_switch_dialog_title">Select user</string>
 
+    <!-- Label for the entry point to open the dialog which shows currently running applications [CHAR LIMIT=NONE]-->
+    <plurals name="fgs_manager_footer_label">
+        <item quantity="one"><xliff:g id="count" example="1">%s</xliff:g> app running in the background</item>
+        <item quantity="other"><xliff:g id="count" example="2">%s</xliff:g> apps running in the background</item>
+    </plurals>
     <!-- Title for dialog listing applications currently running in the backing [CHAR LIMIT=NONE]-->
     <string name="fgs_manager_dialog_title">Apps running in the background</string>
     <!-- Label of the button to stop the app from running in the background [CHAR LIMIT=12]-->
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index ff5699b..ac98739 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -746,7 +746,7 @@
      <style name="Theme.SystemUI.Dialog.Control.DetailPanel" parent="@android:style/Theme.DeviceDefault.Dialog.NoActionBar">
       <item name="android:windowFullscreen">false</item>
       <item name="android:windowIsFloating">false</item>
-      <item name="android:windowBackground">@android:color/black</item>
+      <item name="android:windowBackground">@color/controls_task_view_bg</item>
       <item name="android:backgroundDimEnabled">false</item>
       <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
     </style>
diff --git a/packages/SystemUI/res/values/tiles_states_strings.xml b/packages/SystemUI/res/values/tiles_states_strings.xml
index a610caa..e273416 100644
--- a/packages/SystemUI/res/values/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values/tiles_states_strings.xml
@@ -308,14 +308,4 @@
         <item>Off</item>
         <item>On</item>
     </string-array>
-
-    <!-- State names for fgsmanager tile: unavailable, off, on.
-         This subtitle is shown when the tile is in that particular state but does not set its own
-         subtitle, so some of these may never appear on screen. They should still be translated as
-         if they could appear.[CHAR LIMIT=32] -->
-    <string-array name="tile_states_fgsmanager">
-        <item>Unavailable</item>
-        <item>Off</item>
-        <item>On</item>
-    </string-array>
 </resources>
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java b/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java
index 710980a..e6d5719 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java
@@ -58,7 +58,7 @@
 
     LayoutInflater mInflater;
 
-    private MetricsLogger mMetricsLogger;
+    private final MetricsLogger mMetricsLogger;
 
     private String[] mPackages;
     private PackageItemAdapter mAdapter;
@@ -75,16 +75,15 @@
             };
 
     @Inject
-    ForegroundServicesDialog() {
+    ForegroundServicesDialog(MetricsLogger metricsLogger) {
         super();
+        mMetricsLogger = metricsLogger;
     }
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        mMetricsLogger = Dependency.get(MetricsLogger.class);
-
         mInflater = LayoutInflater.from(this);
 
         mAdapter = new PackageItemAdapter(this);
diff --git a/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java b/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java
index 3f5c2c8..aedaf96 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java
@@ -28,7 +28,6 @@
 import androidx.annotation.Nullable;
 
 import com.android.systemui.BootCompleteCache;
-import com.android.systemui.Dependency;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -78,10 +77,11 @@
 
     @Inject
     PhoneStateMonitor(Context context, BroadcastDispatcher broadcastDispatcher,
-            Lazy<Optional<StatusBar>> statusBarOptionalLazy, BootCompleteCache bootCompleteCache) {
+            Lazy<Optional<StatusBar>> statusBarOptionalLazy, BootCompleteCache bootCompleteCache,
+            StatusBarStateController statusBarStateController) {
         mContext = context;
         mStatusBarOptionalLazy = statusBarOptionalLazy;
-        mStatusBarStateController = Dependency.get(StatusBarStateController.class);
+        mStatusBarStateController = statusBarStateController;
 
         mDefaultHome = getCurrentDefaultHome();
         bootCompleteCache.addListener(() -> mDefaultHome = getCurrentDefaultHome());
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java b/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
index 5732145..1c98099 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
@@ -35,7 +35,6 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.assist.AssistLogger;
 import com.android.systemui.assist.AssistManager;
@@ -46,6 +45,8 @@
 
 import javax.inject.Inject;
 
+import dagger.Lazy;
+
 /**
  * Default UiController implementation. Shows white edge lights along the bottom of the phone,
  * expanding from the corners to meet in the center.
@@ -65,6 +66,8 @@
     protected final AssistLogger mAssistLogger;
 
     private final WindowManager mWindowManager;
+    private final MetricsLogger mMetricsLogger;
+    private final Lazy<AssistManager> mAssistManagerLazy;
     private final WindowManager.LayoutParams mLayoutParams;
     private final PathInterpolator mProgressInterpolator = new PathInterpolator(.83f, 0, .84f, 1);
 
@@ -75,10 +78,14 @@
     private ValueAnimator mInvocationAnimator = new ValueAnimator();
 
     @Inject
-    public DefaultUiController(Context context, AssistLogger assistLogger) {
+    public DefaultUiController(Context context, AssistLogger assistLogger,
+            WindowManager windowManager, MetricsLogger metricsLogger,
+            Lazy<AssistManager> assistManagerLazy) {
         mAssistLogger = assistLogger;
         mRoot = new FrameLayout(context);
-        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+        mWindowManager = windowManager;
+        mMetricsLogger = metricsLogger;
+        mAssistManagerLazy = assistManagerLazy;
 
         mLayoutParams = new WindowManager.LayoutParams(
                 WindowManager.LayoutParams.MATCH_PARENT,
@@ -152,9 +159,9 @@
                     /* isInvocationComplete = */ false,
                     /* assistantComponent = */ null,
                     /* legacyDeviceState = */ null);
-            MetricsLogger.action(new LogMaker(MetricsEvent.ASSISTANT)
+            mMetricsLogger.write(new LogMaker(MetricsEvent.ASSISTANT)
                     .setType(MetricsEvent.TYPE_ACTION)
-                    .setSubtype(Dependency.get(AssistManager.class).toLoggingSubType(type)));
+                    .setSubtype(mAssistManagerLazy.get().toLoggingSubType(type)));
         }
         // Logs assistant invocation cancelled.
         if ((mInvocationAnimator == null || !mInvocationAnimator.isRunning())
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index fd37b35..21edb24 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -52,7 +52,6 @@
 import android.widget.ScrollView;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.animation.Interpolators;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
@@ -106,7 +105,7 @@
 
     private final float mTranslationY;
 
-    @VisibleForTesting final WakefulnessLifecycle mWakefulnessLifecycle;
+    private final WakefulnessLifecycle mWakefulnessLifecycle;
 
     @VisibleForTesting @ContainerState int mContainerState = STATE_UNKNOWN;
 
@@ -187,10 +186,12 @@
 
         public AuthContainerView build(int[] sensorIds, boolean credentialAllowed,
                 @Nullable List<FingerprintSensorPropertiesInternal> fpProps,
-                @Nullable List<FaceSensorPropertiesInternal> faceProps) {
+                @Nullable List<FaceSensorPropertiesInternal> faceProps,
+                WakefulnessLifecycle wakefulnessLifecycle) {
             mConfig.mSensorIds = sensorIds;
             mConfig.mCredentialAllowed = credentialAllowed;
-            return new AuthContainerView(mConfig, new Injector(), fpProps, faceProps);
+            return new AuthContainerView(
+                    mConfig, new Injector(), fpProps, faceProps, wakefulnessLifecycle);
         }
     }
 
@@ -276,7 +277,8 @@
     @VisibleForTesting
     AuthContainerView(Config config, Injector injector,
             @Nullable List<FingerprintSensorPropertiesInternal> fpProps,
-            @Nullable List<FaceSensorPropertiesInternal> faceProps) {
+            @Nullable List<FaceSensorPropertiesInternal> faceProps,
+            WakefulnessLifecycle wakefulnessLifecycle) {
         super(config.mContext);
 
         mConfig = config;
@@ -289,7 +291,7 @@
 
         mHandler = new Handler(Looper.getMainLooper());
         mWindowManager = mContext.getSystemService(WindowManager.class);
-        mWakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class);
+        mWakefulnessLifecycle = wakefulnessLifecycle;
 
         mTranslationY = getResources()
                 .getDimension(R.dimen.biometric_dialog_animation_translation_offset);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 2b12f67..f833c2a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -63,6 +63,7 @@
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.doze.DozeReceiver;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.util.concurrency.Execution;
 
@@ -130,6 +131,7 @@
 
     @NonNull private final SparseBooleanArray mUdfpsEnrolledForUser;
     private SensorPrivacyManager mSensorPrivacyManager;
+    private final WakefulnessLifecycle mWakefulnessLifecycle;
 
     private class BiometricTaskStackListener extends TaskStackListener {
         @Override
@@ -479,9 +481,11 @@
             Provider<UdfpsController> udfpsControllerFactory,
             Provider<SidefpsController> sidefpsControllerFactory,
             @NonNull DisplayManager displayManager,
+            WakefulnessLifecycle wakefulnessLifecycle,
             @Main Handler handler) {
         super(context);
         mExecution = execution;
+        mWakefulnessLifecycle = wakefulnessLifecycle;
         mHandler = handler;
         mCommandQueue = commandQueue;
         mActivityTaskManager = activityTaskManager;
@@ -788,7 +792,8 @@
                 skipAnimation,
                 operationId,
                 requestId,
-                multiSensorConfig);
+                multiSensorConfig,
+                mWakefulnessLifecycle);
 
         if (newDialog == null) {
             Log.e(TAG, "Unsupported type configuration");
@@ -868,7 +873,8 @@
     protected AuthDialog buildDialog(PromptInfo promptInfo, boolean requireConfirmation,
             int userId, int[] sensorIds, boolean credentialAllowed, String opPackageName,
             boolean skipIntro, long operationId, long requestId,
-            @BiometricMultiSensorMode int multiSensorConfig) {
+            @BiometricMultiSensorMode int multiSensorConfig,
+            WakefulnessLifecycle wakefulnessLifecycle) {
         return new AuthContainerView.Builder(mContext)
                 .setCallback(this)
                 .setPromptInfo(promptInfo)
@@ -879,7 +885,7 @@
                 .setOperationId(operationId)
                 .setRequestId(requestId)
                 .setMultiSensorConfig(multiSensorConfig)
-                .build(sensorIds, credentialAllowed, mFpProps, mFaceProps);
+                .build(sensorIds, credentialAllowed, mFpProps, mFaceProps, wakefulnessLifecycle);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 6581490..5ddfd75 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -28,6 +28,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.graphics.Point;
 import android.graphics.RectF;
 import android.hardware.biometrics.SensorLocationInternal;
 import android.hardware.display.DisplayManager;
@@ -45,6 +46,7 @@
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
+import android.view.Surface;
 import android.view.VelocityTracker;
 import android.view.View;
 import android.view.WindowManager;
@@ -414,8 +416,33 @@
                         final long sinceLastLog = mSystemClock.elapsedRealtime() - mTouchLogTime;
                         if (!isIlluminationRequested && !mGoodCaptureReceived &&
                                 !exceedsVelocityThreshold) {
-                            onFingerDown((int) event.getRawX(), (int) event.getRawY(), minor,
-                                    major);
+                            final int rawX = (int) event.getRawX();
+                            final int rawY = (int) event.getRawY();
+                            // Default coordinates assume portrait mode.
+                            int x = rawX;
+                            int y = rawY;
+
+                            // Gets the size based on the current rotation of the display.
+                            Point p = new Point();
+                            mContext.getDisplay().getRealSize(p);
+
+                            // Transform x, y to portrait mode if the device is in landscape mode.
+                            switch (mContext.getDisplay().getRotation()) {
+                                case Surface.ROTATION_90:
+                                    x = p.y - rawY;
+                                    y = rawX;
+                                    break;
+
+                                case Surface.ROTATION_270:
+                                    x = rawY;
+                                    y = p.x - rawX;
+                                    break;
+
+                                default:
+                                    // Do nothing to stay in portrait mode.
+                            }
+
+                            onFingerDown(x, y, minor, major);
                             Log.v(TAG, "onTouch | finger down: " + touchInfo);
                             mTouchLogTime = mSystemClock.elapsedRealtime();
                             mPowerManager.userActivity(mSystemClock.uptimeMillis(),
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
index 4758ab0..dc3d1b5 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
@@ -41,12 +41,12 @@
  * The activity being launched is specified by {@link android.service.controls.Control#getAppIntent}.
  */
 class DetailDialog(
-    val activityContext: Context?,
+    val activityContext: Context,
     val taskView: TaskView,
     val pendingIntent: PendingIntent,
     val cvh: ControlViewHolder
 ) : Dialog(
-    activityContext ?: cvh.context,
+    activityContext,
     R.style.Theme_SystemUI_Dialog_Control_DetailPanel
 ) {
     companion object {
@@ -58,6 +58,10 @@
     }
 
     var detailTaskId = INVALID_TASK_ID
+    private lateinit var taskViewContainer: View
+    private val taskWidthPercentWidth = activityContext.resources.getFloat(
+        R.dimen.controls_task_view_width_percentage
+    )
 
     private val fillInIntent = Intent().apply {
         putExtra(EXTRA_USE_PANEL, true)
@@ -75,13 +79,18 @@
 
     val stateCallback = object : TaskView.Listener {
         override fun onInitialized() {
-            val options = activityContext?.let {
-                ActivityOptions.makeCustomAnimation(
-                    it,
-                    0 /* enterResId */,
-                    0 /* exitResId */
-                )
-            } ?: ActivityOptions.makeBasic()
+            taskViewContainer.apply {
+                // For some devices, limit the overall width of the taskView
+                val lp = getLayoutParams()
+                lp.width = (getWidth() * taskWidthPercentWidth).toInt()
+                setLayoutParams(lp)
+            }
+
+            val options = ActivityOptions.makeCustomAnimation(
+                activityContext,
+                0 /* enterResId */,
+                0 /* exitResId */
+            )
             taskView.startActivity(
                 pendingIntent,
                 fillInIntent,
@@ -112,16 +121,14 @@
     }
 
     init {
-        if (activityContext == null) {
-            window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY)
-        }
-
         // To pass touches to the task inside TaskView.
         window.addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL)
         window.addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY)
 
         setContentView(R.layout.controls_detail_dialog)
 
+        taskViewContainer = requireViewById<ViewGroup>(R.id.control_task_view_container)
+
         requireViewById<ViewGroup>(R.id.controls_activity_view).apply {
             addView(taskView)
             setAlpha(0f)
@@ -130,6 +137,9 @@
         requireViewById<ImageView>(R.id.control_detail_close).apply {
             setOnClickListener { _: View -> dismiss() }
         }
+        requireViewById<View>(R.id.control_detail_root).apply {
+            setOnClickListener { _: View -> dismiss() }
+        }
 
         requireViewById<ImageView>(R.id.control_detail_open_in_app).apply {
             setOnClickListener { v: View ->
@@ -145,17 +155,10 @@
         // consume all insets to achieve slide under effect
         window.getDecorView().setOnApplyWindowInsetsListener {
             v: View, insets: WindowInsets ->
-                taskView.apply {
-                    val l = getPaddingLeft()
-                    val t = getPaddingTop()
-                    val r = getPaddingRight()
-                    setPadding(l, t, r, insets.getInsets(Type.systemBars()).bottom)
-                }
-
                 val l = v.getPaddingLeft()
-                val b = v.getPaddingBottom()
                 val r = v.getPaddingRight()
-                v.setPadding(l, insets.getInsets(Type.systemBars()).top, r, b)
+                val insets = insets.getInsets(Type.systemBars())
+                v.setPadding(l, insets.top, r, insets.bottom)
 
                 WindowInsets.CONSUMED
         }
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
index e465ae4..85c9644 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
@@ -77,6 +77,10 @@
 
     @Override
     public int getItemCount() {
+        if (mController.isZeroMode()) {
+            // Add extra one for "pair new" or dynamic group
+            return mController.getMediaDevices().size() + 1;
+        }
         return mController.getMediaDevices().size();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index ad4a2f4..dbd641b 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -58,7 +58,6 @@
 import com.android.settingslib.Utils;
 import com.android.settingslib.fuelgauge.BatterySaverUtils;
 import com.android.settingslib.utils.PowerUtil;
-import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.SystemUIApplication;
 import com.android.systemui.dagger.SysUISingleton;
@@ -421,7 +420,7 @@
                                     new Intent(Intent.ACTION_VIEW)
                                             .setData(Uri.parse(url))
                                             .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                            Dependency.get(ActivityStarter.class).startActivity(helpIntent,
+                            mActivityStarter.startActivity(helpIntent,
                                     true /* dismissShade */, resultCode -> {
                                         mHighTempDialog = null;
                                     });
@@ -456,7 +455,7 @@
                                     new Intent(Intent.ACTION_VIEW)
                                             .setData(Uri.parse(url))
                                             .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                            Dependency.get(ActivityStarter.class).startActivity(helpIntent,
+                            mActivityStarter.startActivity(helpIntent,
                                     true /* dismissShade */, resultCode -> {
                                         mThermalShutdownDialog = null;
                                     });
@@ -516,7 +515,7 @@
                     helpIntent.setClassName("com.android.settings",
                             "com.android.settings.HelpTrampoline");
                     helpIntent.putExtra(Intent.EXTRA_TEXT, contextString);
-                    Dependency.get(ActivityStarter.class).startActivity(helpIntent,
+                    mActivityStarter.startActivity(helpIntent,
                             true /* dismissShade */, resultCode -> {
                                 mUsbHighTempDialog = null;
                             });
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index 37a0f59..642af59 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -43,7 +43,6 @@
 import com.android.settingslib.fuelgauge.Estimate;
 import com.android.settingslib.utils.ThreadUtils;
 import com.android.systemui.CoreStartable;
-import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.SysUISingleton;
@@ -80,13 +79,13 @@
     @VisibleForTesting
     final Receiver mReceiver = new Receiver();
 
-    private PowerManager mPowerManager;
-    private WarningsUI mWarnings;
+    private final PowerManager mPowerManager;
+    private final WarningsUI mWarnings;
     private InattentiveSleepWarningView mOverlayView;
     private final Configuration mLastConfiguration = new Configuration();
     private int mPlugType = 0;
     private int mInvalidCharger = 0;
-    private EnhancedEstimates mEnhancedEstimates;
+    private final EnhancedEstimates mEnhancedEstimates;
     private Future mLastShowWarningTask;
     private boolean mEnableSkinTemperatureWarning;
     private boolean mEnableUsbTemperatureAlarm;
@@ -113,18 +112,20 @@
 
     @Inject
     public PowerUI(Context context, BroadcastDispatcher broadcastDispatcher,
-            CommandQueue commandQueue, Lazy<Optional<StatusBar>> statusBarOptionalLazy) {
+            CommandQueue commandQueue, Lazy<Optional<StatusBar>> statusBarOptionalLazy,
+            WarningsUI warningsUI, EnhancedEstimates enhancedEstimates,
+            PowerManager powerManager) {
         super(context);
         mBroadcastDispatcher = broadcastDispatcher;
         mCommandQueue = commandQueue;
         mStatusBarOptionalLazy = statusBarOptionalLazy;
+        mWarnings = warningsUI;
+        mEnhancedEstimates = enhancedEstimates;
+        mPowerManager = powerManager;
     }
 
     public void start() {
-        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mScreenOffTime = mPowerManager.isScreenOn() ? -1 : SystemClock.elapsedRealtime();
-        mWarnings = Dependency.get(WarningsUI.class);
-        mEnhancedEstimates = Dependency.get(EnhancedEstimates.class);
         mLastConfiguration.setTo(mContext.getResources().getConfiguration());
 
         ContentObserver obs = new ContentObserver(mHandler) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 1dba536..ded6ae0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -85,6 +85,7 @@
     private final QSPanelController mQsPanelController;
     private final QuickQSPanelController mQuickQSPanelController;
     private final QuickStatusBarHeader mQuickStatusBarHeader;
+    private final QSFgsManagerFooter mFgsManagerFooter;
     private final QSSecurityFooter mSecurityFooter;
     private final QS mQs;
     private final View mQSFooterActions;
@@ -151,7 +152,8 @@
     public QSAnimator(QS qs, QuickQSPanel quickPanel, QuickStatusBarHeader quickStatusBarHeader,
             QSPanelController qsPanelController,
             QuickQSPanelController quickQSPanelController, QSTileHost qsTileHost,
-            QSSecurityFooter securityFooter, @Main Executor executor, TunerService tunerService,
+            QSFgsManagerFooter fgsManagerFooter, QSSecurityFooter securityFooter,
+            @Main Executor executor, TunerService tunerService,
             QSExpansionPathInterpolator qsExpansionPathInterpolator,
             @Named(QS_FOOTER) FooterActionsView qsFooterActionsView,
             @Named(QQS_FOOTER) FooterActionsView qqsFooterActionsView) {
@@ -162,6 +164,7 @@
         mQuickStatusBarHeader = quickStatusBarHeader;
         mQQSFooterActions = qqsFooterActionsView;
         mQSFooterActions = qsFooterActionsView;
+        mFgsManagerFooter = fgsManagerFooter;
         mSecurityFooter = securityFooter;
         mHost = qsTileHost;
         mExecutor = executor;
@@ -481,6 +484,7 @@
 
             // Fade in the security footer and the divider as we reach the final position
             Builder builder = new Builder().setStartDelay(EXPANDED_TILE_DELAY);
+            builder.addFloat(mFgsManagerFooter.getView(), "alpha", 0, 1);
             builder.addFloat(mSecurityFooter.getView(), "alpha", 0, 1);
             if (mQsPanelController.shouldUseHorizontalLayout()
                     && mQsPanelController.mMediaHost.hostView != null) {
@@ -490,6 +494,7 @@
                 mQsPanelController.mMediaHost.hostView.setAlpha(1.0f);
             }
             mAllPagesDelayedAnimator = builder.build();
+            mAllViews.add(mFgsManagerFooter.getView());
             mAllViews.add(mSecurityFooter.getView());
             translationYBuilder.setInterpolator(mQSExpansionPathInterpolator.getYInterpolator());
             qqsTranslationYBuilder.setInterpolator(mQSExpansionPathInterpolator.getYInterpolator());
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFgsManagerFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFgsManagerFooter.java
new file mode 100644
index 0000000..082de16
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFgsManagerFooter.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2022 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.qs;
+
+import static android.provider.DeviceConfig.NAMESPACE_SYSTEMUI;
+
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_ENABLED;
+import static com.android.systemui.qs.dagger.QSFragmentModule.QS_FGS_MANAGER_FOOTER_VIEW;
+
+import android.content.Context;
+import android.provider.DeviceConfig;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.fgsmanager.FgsManagerDialogFactory;
+import com.android.systemui.statusbar.policy.RunningFgsController;
+
+import java.util.concurrent.Executor;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+/**
+ * Footer entry point for the foreground service manager
+ */
+public class QSFgsManagerFooter implements View.OnClickListener {
+
+    private final View mRootView;
+    private final TextView mFooterText;
+    private final Context mContext;
+    private final Executor mMainExecutor;
+    private final Executor mExecutor;
+    private final RunningFgsController mRunningFgsController;
+    private final FgsManagerDialogFactory mFgsManagerDialogFactory;
+
+    private boolean mIsInitialized = false;
+    private boolean mIsAvailable = false;
+
+    @Inject
+    QSFgsManagerFooter(@Named(QS_FGS_MANAGER_FOOTER_VIEW) View rootView,
+            @Main Executor mainExecutor, RunningFgsController runningFgsController,
+            @Background Executor executor,
+            FgsManagerDialogFactory fgsManagerDialogFactory) {
+        mRootView = rootView;
+        mFooterText = mRootView.findViewById(R.id.footer_text);
+        ImageView icon = mRootView.findViewById(R.id.primary_footer_icon);
+        icon.setImageResource(R.drawable.ic_info_outline);
+        mContext = rootView.getContext();
+        mMainExecutor = mainExecutor;
+        mExecutor = executor;
+        mRunningFgsController = runningFgsController;
+        mFgsManagerDialogFactory = fgsManagerDialogFactory;
+    }
+
+    public void init() {
+        if (mIsInitialized) {
+            return;
+        }
+
+        mRootView.setOnClickListener(this);
+
+        mRunningFgsController.addCallback(packages -> refreshState());
+
+        DeviceConfig.addOnPropertiesChangedListener(NAMESPACE_SYSTEMUI, mExecutor,
+                (DeviceConfig.OnPropertiesChangedListener) properties -> {
+                    mIsAvailable = properties.getBoolean(TASK_MANAGER_ENABLED, mIsAvailable);
+                });
+        mIsAvailable = DeviceConfig.getBoolean(NAMESPACE_SYSTEMUI, TASK_MANAGER_ENABLED, false);
+
+        mIsInitialized = true;
+    }
+
+    @Override
+    public void onClick(View view) {
+        mFgsManagerDialogFactory.create(mRootView);
+    }
+
+    public void refreshState() {
+        mExecutor.execute(this::handleRefreshState);
+    }
+
+    public View getView() {
+        return mRootView;
+    }
+
+    private boolean isAvailable() {
+        return mIsAvailable;
+    }
+
+    public void handleRefreshState() {
+        int numPackages = mRunningFgsController.getPackagesWithFgs().size();
+        mMainExecutor.execute(() -> {
+            mFooterText.setText(mContext.getResources().getQuantityString(
+                    R.plurals.fgs_manager_footer_label, numPackages, numPackages));
+            mRootView.setVisibility(numPackages > 0 && isAvailable() ? View.VISIBLE : View.GONE);
+        });
+    }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 38061a8..6b515c8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -86,6 +86,8 @@
             new ArrayList<>();
 
     @Nullable
+    protected View mFgsManagerFooter;
+    @Nullable
     protected View mSecurityFooter;
 
     @Nullable
@@ -448,7 +450,12 @@
             switchToParent(mSecurityFooter, mHeaderContainer, 0);
         } else {
             // Add after the footer
-            int index = indexOfChild(mFooter);
+            int index;
+            if (mFgsManagerFooter != null) {
+                index = indexOfChild(mFgsManagerFooter);
+            } else {
+                index = indexOfChild(mFooter);
+            }
             switchToParent(mSecurityFooter, this, index + 1);
         }
     }
@@ -722,6 +729,17 @@
         switchSecurityFooter(shouldUseSplitNotificationShade);
     }
 
+    /**
+     * Set the fgs manager footer view and switch it into the right place
+     * @param view the view in question
+     */
+    public void setFgsManagerFooter(View view) {
+        mFgsManagerFooter = view;
+        // Add after the footer
+        int index = indexOfChild(mFooter);
+        switchToParent(mFgsManagerFooter, this, index + 1);
+    }
+
     protected void setPageMargin(int pageMargin) {
         if (mTileLayout instanceof PagedTileLayout) {
             ((PagedTileLayout) mTileLayout).setPageMargin(pageMargin);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
index 001c740e..cbfe944 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
@@ -57,6 +57,7 @@
 public class QSPanelController extends QSPanelControllerBase<QSPanel> {
     public static final String QS_REMOVE_LABELS = "sysui_remove_labels";
 
+    private final QSFgsManagerFooter mQSFgsManagerFooter;
     private final QSSecurityFooter mQsSecurityFooter;
     private final TunerService mTunerService;
     private final QSCustomizerController mQsCustomizerController;
@@ -94,7 +95,8 @@
     };
 
     @Inject
-    QSPanelController(QSPanel view, QSSecurityFooter qsSecurityFooter, TunerService tunerService,
+    QSPanelController(QSPanel view, QSFgsManagerFooter qsFgsManagerFooter,
+            QSSecurityFooter qsSecurityFooter, TunerService tunerService,
             QSTileHost qstileHost, QSCustomizerController qsCustomizerController,
             @Named(QS_USING_MEDIA_PLAYER) boolean usingMediaPlayer,
             @Named(QS_PANEL) MediaHost mediaHost,
@@ -105,6 +107,7 @@
             FalsingManager falsingManager, CommandQueue commandQueue) {
         super(view, qstileHost, qsCustomizerController, usingMediaPlayer, mediaHost,
                 metricsLogger, uiEventLogger, qsLogger, dumpManager);
+        mQSFgsManagerFooter = qsFgsManagerFooter;
         mQsSecurityFooter = qsSecurityFooter;
         mTunerService = tunerService;
         mQsCustomizerController = qsCustomizerController;
@@ -128,6 +131,7 @@
         mMediaHost.init(MediaHierarchyManager.LOCATION_QS);
         mQsCustomizerController.init();
         mBrightnessSliderController.init();
+        mQSFgsManagerFooter.init();
     }
 
     private void updateMediaExpansion() {
@@ -146,6 +150,7 @@
             refreshAllTiles();
         }
         mView.addOnConfigurationChangedListener(mOnConfigurationChangedListener);
+        mView.setFgsManagerFooter(mQSFgsManagerFooter.getView());
         mView.setSecurityFooter(mQsSecurityFooter.getView(), mShouldUseSplitNotificationShade);
         switchTileLayout(true);
         mBrightnessMirrorHandler.onQsPanelAttached();
@@ -230,6 +235,7 @@
     public void refreshAllTiles() {
         mBrightnessController.checkRestrictionAndSetEnabled();
         super.refreshAllTiles();
+        mQSFgsManagerFooter.refreshState();
         mQsSecurityFooter.refreshState();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index d3bad16..90cf92a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -181,6 +181,7 @@
     }
 
     private void clearAccessibilityState() {
+        mNeedsFocus = false;
         if (mAccessibilityAction == ACTION_ADD) {
             // Remove blank tile from last spot
             mTiles.remove(--mEditIndex);
@@ -415,9 +416,6 @@
                         int oldLeft, int oldTop, int oldRight, int oldBottom) {
                     holder.mTileView.removeOnLayoutChangeListener(this);
                     holder.mTileView.requestAccessibilityFocus();
-                    if (mAccessibilityAction == ACTION_NONE) {
-                        holder.mTileView.clearAccessibilityFocus();
-                    }
                 }
             });
             mNeedsFocus = false;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
index 11e5b6e..1958caf 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
@@ -53,6 +53,7 @@
  */
 @Module
 public interface QSFragmentModule {
+    String QS_FGS_MANAGER_FOOTER_VIEW = "qs_fgs_manager_footer";
     String QS_SECURITY_FOOTER_VIEW = "qs_security_footer";
     String QQS_FOOTER = "qqs_footer";
     String QS_FOOTER = "qs_footer";
@@ -205,4 +206,15 @@
     static StatusIconContainer providesStatusIconContainer(QuickStatusBarHeader qsHeader) {
         return qsHeader.findViewById(R.id.statusIcons);
     }
+
+    /** */
+    @Provides
+    @QSScope
+    @Named(QS_FGS_MANAGER_FOOTER_VIEW)
+    static View providesQSFgsManagerFooterView(
+            @QSThemedContext LayoutInflater layoutInflater,
+            QSPanel qsPanel
+    ) {
+        return layoutInflater.inflate(R.layout.quick_settings_security_footer, qsPanel, false);
+    }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index 5e68f61..86fc4de 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -39,7 +39,6 @@
 import com.android.systemui.qs.tiles.DataSaverTile;
 import com.android.systemui.qs.tiles.DeviceControlsTile;
 import com.android.systemui.qs.tiles.DndTile;
-import com.android.systemui.qs.tiles.FgsManagerTile;
 import com.android.systemui.qs.tiles.FlashlightTile;
 import com.android.systemui.qs.tiles.HotspotTile;
 import com.android.systemui.qs.tiles.InternetTile;
@@ -99,7 +98,6 @@
     private final Provider<QuickAccessWalletTile> mQuickAccessWalletTileProvider;
     private final Provider<QRCodeScannerTile> mQRCodeScannerTileProvider;
     private final Provider<OneHandedModeTile> mOneHandedModeTileProvider;
-    private final Provider<FgsManagerTile> mFgsManagerTileProvider;
 
     private final Lazy<QSHost> mQsHostLazy;
     private final Provider<CustomTile.Builder> mCustomTileBuilderProvider;
@@ -137,7 +135,6 @@
             Provider<QuickAccessWalletTile> quickAccessWalletTileProvider,
             Provider<QRCodeScannerTile> qrCodeScannerTileProvider,
             Provider<OneHandedModeTile> oneHandedModeTileProvider,
-            Provider<FgsManagerTile> fgsManagerTileProvider,
             Provider<ColorCorrectionTile> colorCorrectionTileProvider) {
         mQsHostLazy = qsHostLazy;
         mCustomTileBuilderProvider = customTileBuilderProvider;
@@ -171,7 +168,6 @@
         mQuickAccessWalletTileProvider = quickAccessWalletTileProvider;
         mQRCodeScannerTileProvider = qrCodeScannerTileProvider;
         mOneHandedModeTileProvider = oneHandedModeTileProvider;
-        mFgsManagerTileProvider = fgsManagerTileProvider;
         mColorCorrectionTileProvider = colorCorrectionTileProvider;
     }
 
@@ -246,8 +242,6 @@
                 return mQRCodeScannerTileProvider.get();
             case "onehanded":
                 return mOneHandedModeTileProvider.get();
-            case "fgsmanager":
-                return mFgsManagerTileProvider.get();
             case "color_correction":
                 return mColorCorrectionTileProvider.get();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
index 7efb983..821dfa5f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
@@ -653,7 +653,6 @@
         "qr_code_scanner" to R.array.tile_states_qr_code_scanner,
         "alarm" to R.array.tile_states_alarm,
         "onehanded" to R.array.tile_states_onehanded,
-        "fgsmanager" to R.array.tile_states_fgsmanager,
         "color_correction" to R.array.tile_states_color_correction
     )
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FgsManagerTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/FgsManagerTile.kt
deleted file mode 100644
index 939a297..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FgsManagerTile.kt
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2021 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.qs.tiles
-
-import android.content.Intent
-import android.os.Handler
-import android.os.Looper
-import android.provider.DeviceConfig
-import android.view.View
-import com.android.internal.config.sysui.SystemUiDeviceConfigFlags
-import com.android.internal.logging.MetricsLogger
-import com.android.systemui.DejankUtils
-import com.android.systemui.R
-import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.fgsmanager.FgsManagerDialogFactory
-import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.plugins.FalsingManager
-import com.android.systemui.plugins.qs.QSTile
-import com.android.systemui.plugins.statusbar.StatusBarStateController
-import com.android.systemui.qs.QSHost
-import com.android.systemui.qs.logging.QSLogger
-import com.android.systemui.qs.tileimpl.QSTileImpl
-import com.android.systemui.statusbar.policy.RunningFgsController
-import com.android.systemui.statusbar.policy.RunningFgsController.UserPackageTime
-import java.util.concurrent.Executor
-import javax.inject.Inject
-
-/**
- * Quicksettings tile for the foreground services manager (task manager)
- */
-class FgsManagerTile @Inject constructor(
-    host: QSHost?,
-    @Background backgroundLooper: Looper?,
-    @Background private val backgroundExecutor: Executor?,
-    @Main mainHandler: Handler?,
-    falsingManager: FalsingManager?,
-    metricsLogger: MetricsLogger?,
-    statusBarStateController: StatusBarStateController?,
-    activityStarter: ActivityStarter?,
-    qsLogger: QSLogger?,
-    private val fgsManagerDialogFactory: FgsManagerDialogFactory,
-    private val runningFgsController: RunningFgsController
-) : QSTileImpl<QSTile.State>(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
-        statusBarStateController, activityStarter, qsLogger), RunningFgsController.Callback {
-
-    override fun handleInitialize() {
-        super.handleInitialize()
-        mUiHandler.post { runningFgsController.observe(lifecycle, this) }
-    }
-
-    override fun isAvailable(): Boolean {
-        return DejankUtils.whitelistIpcs<Boolean> {
-            DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
-                    SystemUiDeviceConfigFlags.TASK_MANAGER_ENABLED, false)
-        }
-    }
-
-    override fun newTileState(): QSTile.State {
-        return QSTile.State()
-    }
-
-    override fun handleClick(view: View?) {
-        mUiHandler.post { fgsManagerDialogFactory.create(view) }
-    }
-
-    override fun handleUpdateState(state: QSTile.State?, arg: Any?) {
-        state?.label = tileLabel
-        state?.secondaryLabel = runningFgsController.getPackagesWithFgs().size.toString()
-        state?.handlesLongClick = false
-        state?.icon = ResourceIcon.get(R.drawable.ic_list)
-    }
-
-    override fun getMetricsCategory(): Int = 0
-
-    override fun getLongClickIntent(): Intent? = null
-
-    // Inline the string so we don't waste translator time since this isn't used in the mocks.
-    // TODO If mocks change need to remember to move this to strings.xml
-    override fun getTileLabel(): CharSequence = "Active apps"
-
-    override fun onFgsPackagesChanged(packages: List<UserPackageTime>) = refreshState()
-}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
index d7d1de0..991a68f 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
@@ -398,6 +398,11 @@
             min = mBrightnessMin;
             max = mBrightnessMax;
         }
+
+        // Ensure the slider is in a fixed position first, then check if we should animate.
+        if (mSliderAnimator != null && mSliderAnimator.isStarted()) {
+            mSliderAnimator.cancel();
+        }
         // convertGammaToLinearFloat returns 0-1
         if (BrightnessSynchronizer.floatEquals(brightnessValue,
                 convertGammaToLinearFloat(mControl.getValue(), min, max))) {
@@ -420,9 +425,6 @@
             mControl.setValue(target);
             mControlValueInitialized = true;
         }
-        if (mSliderAnimator != null && mSliderAnimator.isStarted()) {
-            mSliderAnimator.cancel();
-        }
         mSliderAnimator = ValueAnimator.ofInt(mControl.getValue(), target);
         mSliderAnimator.addUpdateListener((ValueAnimator animation) -> {
             mExternalChange = true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 963a0d7..6335f88 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -151,6 +151,7 @@
     private boolean mPowerPluggedIn;
     private boolean mPowerPluggedInWired;
     private boolean mPowerPluggedInWireless;
+    private boolean mPowerPluggedInDock;
     private boolean mPowerCharged;
     private boolean mBatteryOverheated;
     private boolean mEnableBatteryDefender;
@@ -786,6 +787,10 @@
             chargingId = hasChargingTime
                     ? R.string.keyguard_indication_charging_time_wireless
                     : R.string.keyguard_plugged_in_wireless;
+        } else if (mPowerPluggedInDock) {
+            chargingId = hasChargingTime
+                    ? R.string.keyguard_indication_charging_time_dock
+                    : R.string.keyguard_plugged_in_dock;
         } else {
             chargingId = hasChargingTime
                     ? R.string.keyguard_indication_charging_time
@@ -911,6 +916,7 @@
             boolean wasPluggedIn = mPowerPluggedIn;
             mPowerPluggedInWired = status.isPluggedInWired() && isChargingOrFull;
             mPowerPluggedInWireless = status.isPluggedInWireless() && isChargingOrFull;
+            mPowerPluggedInDock = status.isPluggedInDock() && isChargingOrFull;
             mPowerPluggedIn = status.isPluggedIn() && isChargingOrFull;
             mPowerCharged = status.isCharged();
             mChargingWattage = status.maxChargingWattage;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/SectionHeaderVisibilityProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/SectionHeaderVisibilityProvider.kt
index 03b978e..68bdd18 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/SectionHeaderVisibilityProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/SectionHeaderVisibilityProvider.kt
@@ -16,7 +16,9 @@
 
 package com.android.systemui.statusbar.notification
 
+import android.content.Context
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.R
 import javax.inject.Inject
 
 /**
@@ -29,6 +31,10 @@
  * visibility when it invalidates, and we just store that state here.)
  */
 @SysUISingleton
-class SectionHeaderVisibilityProvider @Inject constructor() {
+class SectionHeaderVisibilityProvider @Inject constructor(
+    context: Context
+) {
+    var neverShowSectionHeaders = context.resources.getBoolean(R.bool.config_notification_never_show_section_headers)
+        private set
     var sectionHeadersVisible = true
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
index 733be9c..0ce07cb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
@@ -220,8 +220,10 @@
     }
 
     private void invalidateListFromFilter(String reason) {
-        mSectionHeaderVisibilityProvider.setSectionHeadersVisible(
-                mStatusBarStateController.getState() != StatusBarState.KEYGUARD);
+        boolean onKeyguard = mStatusBarStateController.getState() == StatusBarState.KEYGUARD;
+        boolean neverShowSections = mSectionHeaderVisibilityProvider.getNeverShowSectionHeaders();
+        boolean showSections = !onKeyguard && !neverShowSections;
+        mSectionHeaderVisibilityProvider.setSectionHeadersVisible(showSections);
         mNotifFilter.invalidateList();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 769f689..e59c99a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -3928,6 +3928,15 @@
         mKeyguardStatusViewController.animateFoldToAod();
     }
 
+    /**
+     * Cancels fold to AOD transition and resets view state
+     */
+    public void cancelFoldToAodAnimation() {
+        cancelAnimation();
+        resetAlpha();
+        resetTranslation();
+    }
+
     /** */
     public void setImportantForAccessibility(int mode) {
         mView.setImportantForAccessibility(mode);
@@ -4046,6 +4055,10 @@
         mView.setTranslationX(0f);
     }
 
+    public void resetAlpha() {
+        mView.setAlpha(1f);
+    }
+
     public ViewPropertyAnimator fadeOut(long startDelayMs, long durationMs, Runnable endAction) {
         return mView.animate().alpha(0).setStartDelay(startDelayMs).setDuration(
                 durationMs).setInterpolator(Interpolators.ALPHA_OUT).withLayer().withEndAction(
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 455ffdc..d3f2794 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -2998,7 +2998,7 @@
     }
 
     private void onLaunchTransitionFadingEnded() {
-        mNotificationPanelViewController.setAlpha(1.0f);
+        mNotificationPanelViewController.resetAlpha();
         mNotificationPanelViewController.onAffordanceLaunchEnded();
         releaseGestureWakeLock();
         runLaunchTransitionEndRunnable();
@@ -3029,7 +3029,7 @@
             }
             updateScrimController();
             mPresenter.updateMediaMetaData(false, true);
-            mNotificationPanelViewController.setAlpha(1);
+            mNotificationPanelViewController.resetAlpha();
             mNotificationPanelViewController.fadeOut(
                     FADE_KEYGUARD_START_DELAY, FADE_KEYGUARD_DURATION,
                     this::onLaunchTransitionFadingEnded);
@@ -3130,7 +3130,7 @@
         releaseGestureWakeLock();
         mNotificationPanelViewController.onAffordanceLaunchEnded();
         mNotificationPanelViewController.cancelAnimation();
-        mNotificationPanelViewController.setAlpha(1f);
+        mNotificationPanelViewController.resetAlpha();
         mNotificationPanelViewController.resetTranslation();
         mNotificationPanelViewController.resetViewGroupFade();
         updateDozingState();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
index 59969c0..5e91a25 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
@@ -30,6 +30,7 @@
 import android.content.PermissionChecker;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
+import android.database.ContentObserver;
 import android.location.LocationManager;
 import android.os.Handler;
 import android.os.Looper;
@@ -43,6 +44,8 @@
 import androidx.annotation.VisibleForTesting;
 
 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
+import com.android.internal.logging.UiEvent;
+import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.BootCompleteCache;
 import com.android.systemui.appops.AppOpItem;
 import com.android.systemui.appops.AppOpsController;
@@ -53,6 +56,7 @@
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.util.DeviceConfigProxy;
 import com.android.systemui.util.Utils;
+import com.android.systemui.util.settings.SecureSettings;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -71,30 +75,48 @@
     private final DeviceConfigProxy mDeviceConfigProxy;
     private final BootCompleteCache mBootCompleteCache;
     private final UserTracker mUserTracker;
+    private final UiEventLogger mUiEventLogger;
     private final H mHandler;
     private final Handler mBackgroundHandler;
     private final PackageManager mPackageManager;
+    private final ContentObserver mContentObserver;
+    private final SecureSettings mSecureSettings;
 
     private boolean mAreActiveLocationRequests;
     private boolean mShouldDisplayAllAccesses;
-    private boolean mShowSystemAccesses;
+    private boolean mShowSystemAccessesFlag;
+    private boolean mShowSystemAccessesSetting;
 
     @Inject
     public LocationControllerImpl(Context context, AppOpsController appOpsController,
             DeviceConfigProxy deviceConfigProxy,
             @Main Looper mainLooper, @Background Handler backgroundHandler,
             BroadcastDispatcher broadcastDispatcher, BootCompleteCache bootCompleteCache,
-            UserTracker userTracker, PackageManager packageManager) {
+            UserTracker userTracker, PackageManager packageManager, UiEventLogger uiEventLogger,
+            SecureSettings secureSettings) {
         mContext = context;
         mAppOpsController = appOpsController;
         mDeviceConfigProxy = deviceConfigProxy;
         mBootCompleteCache = bootCompleteCache;
         mHandler = new H(mainLooper);
         mUserTracker = userTracker;
+        mUiEventLogger = uiEventLogger;
+        mSecureSettings = secureSettings;
         mBackgroundHandler = backgroundHandler;
         mPackageManager = packageManager;
         mShouldDisplayAllAccesses = getAllAccessesSetting();
-        mShowSystemAccesses = getShowSystemSetting();
+        mShowSystemAccessesFlag = getShowSystemFlag();
+        mShowSystemAccessesSetting = getShowSystemSetting();
+        mContentObserver = new ContentObserver(mBackgroundHandler) {
+            @Override
+            public void onChange(boolean selfChange) {
+                mShowSystemAccessesSetting = getShowSystemSetting();
+            }
+        };
+
+        // Register to listen for changes in Settings.Secure settings.
+        mSecureSettings.registerContentObserver(
+                Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, mContentObserver);
 
         // Register to listen for changes in DeviceConfig settings.
         mDeviceConfigProxy.addOnPropertiesChangedListener(
@@ -102,7 +124,7 @@
                 backgroundHandler::post,
                 properties -> {
                     mShouldDisplayAllAccesses = getAllAccessesSetting();
-                    mShowSystemAccesses = getShowSystemSetting();
+                    mShowSystemAccessesFlag = getShowSystemSetting();
                     updateActiveLocationRequests();
                 });
 
@@ -191,10 +213,15 @@
                 SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED, false);
     }
 
-    private boolean getShowSystemSetting() {
+    private boolean getShowSystemFlag() {
         return mDeviceConfigProxy.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
                 SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SHOW_SYSTEM, false);
     }
+
+    private boolean getShowSystemSetting() {
+        return mSecureSettings.getInt(Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 0) == 1;
+    }
+
     /**
      * Returns true if there currently exist active high power location requests.
      */
@@ -222,6 +249,10 @@
         }
         boolean hadActiveLocationRequests = mAreActiveLocationRequests;
         boolean shouldDisplay = false;
+        boolean showSystem = mShowSystemAccessesFlag || mShowSystemAccessesSetting;
+        boolean systemAppOp = false;
+        boolean nonSystemAppOp = false;
+        boolean isSystemApp;
 
         List<AppOpItem> appOpsItems = mAppOpsController.getActiveAppOps();
         final List<UserInfo> profiles = mUserTracker.getUserProfiles();
@@ -229,18 +260,38 @@
         for (int i = 0; i < numItems; i++) {
             if (appOpsItems.get(i).getCode() == OP_FINE_LOCATION
                     || appOpsItems.get(i).getCode() == OP_COARSE_LOCATION) {
-                if (mShowSystemAccesses) {
-                    shouldDisplay = true;
+                isSystemApp = isSystemApp(profiles, appOpsItems.get(i));
+                if (isSystemApp) {
+                    systemAppOp = true;
                 } else {
-                    shouldDisplay |= !isSystemApp(profiles, appOpsItems.get(i));
+                    nonSystemAppOp = true;
                 }
+
+                shouldDisplay = showSystem || shouldDisplay || !isSystemApp;
             }
         }
 
-        mAreActiveLocationRequests = areActiveHighPowerLocationRequests() || shouldDisplay;
+        boolean highPowerOp = areActiveHighPowerLocationRequests();
+        mAreActiveLocationRequests = highPowerOp || shouldDisplay;
         if (mAreActiveLocationRequests != hadActiveLocationRequests) {
             mHandler.sendEmptyMessage(H.MSG_LOCATION_ACTIVE_CHANGED);
         }
+
+        // Log each of the types of location access that would cause the location indicator to be
+        // shown, regardless of device's setting state. This is used to understand how often a
+        // user would see the location indicator based on any settings state the device could be in.
+        if (!hadActiveLocationRequests && (highPowerOp || systemAppOp || nonSystemAppOp)) {
+            if (highPowerOp) {
+                mUiEventLogger.log(
+                        LocationIndicatorEvent.LOCATION_INDICATOR_MONITOR_HIGH_POWER);
+            }
+            if (systemAppOp) {
+                mUiEventLogger.log(LocationIndicatorEvent.LOCATION_INDICATOR_SYSTEM_APP);
+            }
+            if (nonSystemAppOp) {
+                mUiEventLogger.log(LocationIndicatorEvent.LOCATION_INDICATOR_NON_SYSTEM_APP);
+            }
+        }
     }
 
     private boolean isSystemApp(List<UserInfo> profiles, AppOpItem item) {
@@ -283,6 +334,11 @@
             mAreActiveLocationRequests = areActiveHighPowerLocationRequests();
             if (mAreActiveLocationRequests != hadActiveLocationRequests) {
                 mHandler.sendEmptyMessage(H.MSG_LOCATION_ACTIVE_CHANGED);
+                if (mAreActiveLocationRequests) {
+                    // Log that the indicator was shown for a high power op.
+                    mUiEventLogger.log(
+                            LocationIndicatorEvent.LOCATION_INDICATOR_MONITOR_HIGH_POWER);
+                }
             }
         }
     }
@@ -341,4 +397,24 @@
                     cb -> cb.onLocationSettingsChanged(isEnabled));
         }
     }
-}
+
+    /**
+     * Enum for events which prompt the location indicator to appear.
+     */
+    enum LocationIndicatorEvent implements UiEventLogger.UiEventEnum {
+        @UiEvent(doc = "Location indicator shown for high power access")
+        LOCATION_INDICATOR_MONITOR_HIGH_POWER(935),
+        @UiEvent(doc = "Location indicator shown for system app access")
+        LOCATION_INDICATOR_SYSTEM_APP(936),
+        @UiEvent(doc = "Location indicator shown for non system app access")
+        LOCATION_INDICATOR_NON_SYSTEM_APP(937);
+
+        private final int mId;
+        LocationIndicatorEvent(int id) {
+            mId = id;
+        }
+        @Override public int getId() {
+            return mId;
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/VpnStatusObserver.kt b/packages/SystemUI/src/com/android/systemui/statusbar/tv/VpnStatusObserver.kt
index e25a105..c199744 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/VpnStatusObserver.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/VpnStatusObserver.kt
@@ -25,7 +25,6 @@
 import com.android.internal.messages.nano.SystemMessageProto
 import com.android.internal.net.VpnConfig
 import com.android.systemui.CoreStartable
-import com.android.systemui.Dependency
 import com.android.systemui.R
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.statusbar.policy.SecurityController
@@ -35,12 +34,13 @@
  * Observes if a vpn connection is active and displays a notification to the user
  */
 @SysUISingleton
-class VpnStatusObserver @Inject constructor(context: Context) : CoreStartable(context),
+class VpnStatusObserver @Inject constructor(
+    context: Context,
+    private val securityController: SecurityController
+) : CoreStartable(context),
         SecurityController.SecurityControllerCallback {
 
     private var vpnConnected = false
-    private val securityController: SecurityController =
-            Dependency.get(SecurityController::class.java)
     private val notificationManager = NotificationManager.from(context)
     private val notificationChannel = createNotificationChannel()
     private val vpnConnectedNotificationBuilder = createVpnConnectedNotificationBuilder()
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt b/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt
index aaf35af..c481fc9 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt
@@ -16,8 +16,10 @@
 
 package com.android.systemui.unfold
 
+import android.os.Handler
 import android.os.PowerManager
 import android.provider.Settings
+import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.keyguard.KeyguardViewMediator
 import com.android.systemui.keyguard.WakefulnessLifecycle
 import com.android.systemui.statusbar.LightRevealScrim
@@ -37,6 +39,7 @@
 class FoldAodAnimationController
 @Inject
 constructor(
+    @Main private val handler: Handler,
     private val keyguardViewMediatorLazy: Lazy<KeyguardViewMediator>,
     private val wakefulnessLifecycle: WakefulnessLifecycle,
     private val globalSettings: GlobalSettings
@@ -50,6 +53,14 @@
     private var shouldPlayAnimation = false
     private val statusListeners = arrayListOf<FoldAodAnimationStatus>()
 
+    private val startAnimationRunnable = Runnable {
+        statusBar.notificationPanelViewController.startFoldToAodAnimation {
+            // End action
+            isAnimationPlaying = false
+            keyguardViewMediatorLazy.get().maybeHandlePendingLock()
+        }
+    }
+
     private var isAnimationPlaying = false
 
     override fun initialize(statusBar: StatusBar, lightRevealScrim: LightRevealScrim) {
@@ -79,6 +90,11 @@
         }
 
     override fun onStartedWakingUp() {
+        if (isAnimationPlaying) {
+            handler.removeCallbacks(startAnimationRunnable)
+            statusBar.notificationPanelViewController.cancelFoldToAodAnimation();
+        }
+
         shouldPlayAnimation = false
         isAnimationPlaying = false
     }
@@ -115,11 +131,10 @@
 
     fun onScreenTurnedOn() {
         if (shouldPlayAnimation) {
-            statusBar.notificationPanelViewController.startFoldToAodAnimation {
-                // End action
-                isAnimationPlaying = false
-                keyguardViewMediatorLazy.get().maybeHandlePendingLock()
-            }
+            handler.removeCallbacks(startAnimationRunnable)
+
+            // Post starting the animation to the next frame to avoid junk due to inset changes
+            handler.post(startAnimationRunnable)
             shouldPlayAnimation = false
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java b/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java
index be5e0a0..089650c 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java
@@ -26,8 +26,6 @@
 
 import androidx.core.content.FileProvider;
 
-import com.android.systemui.Dependency;
-
 import java.io.BufferedInputStream;
 import java.io.File;
 import java.io.FileInputStream;
@@ -35,7 +33,6 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipOutputStream;
@@ -53,12 +50,14 @@
     private static final int BUFSIZ = 1024 * 1024; // 1MB
 
     private final Context context;
+    private GarbageMonitor mGarbageMonitor;
     private Uri hprofUri;
     private long rss;
     final StringBuilder body = new StringBuilder();
 
-    public DumpTruck(Context context) {
+    public DumpTruck(Context context, GarbageMonitor garbageMonitor) {
         this.context = context;
+        mGarbageMonitor = garbageMonitor;
     }
 
     /**
@@ -68,8 +67,6 @@
      * @return this, for chaining
      */
     public DumpTruck captureHeaps(List<Long> pids) {
-        final GarbageMonitor gm = Dependency.get(GarbageMonitor.class);
-
         final File dumpDir = new File(context.getCacheDir(), FILEPROVIDER_PATH);
         dumpDir.mkdirs();
         hprofUri = null;
@@ -83,16 +80,14 @@
         for (Long pidL : pids) {
             final int pid = pidL.intValue();
             body.append("  pid ").append(pid);
-            if (gm != null) {
-                GarbageMonitor.ProcessMemInfo info = gm.getMemInfo(pid);
-                if (info != null) {
-                    body.append(":")
-                            .append(" up=")
-                            .append(info.getUptime())
-                            .append(" rss=")
-                            .append(info.currentRss);
-                    rss = info.currentRss;
-                }
+            GarbageMonitor.ProcessMemInfo info = mGarbageMonitor.getMemInfo(pid);
+            if (info != null) {
+                body.append(":")
+                        .append(" up=")
+                        .append(info.getUptime())
+                        .append(" rss=")
+                        .append(info.currentRss);
+                rss = info.currentRss;
             }
             if (pid == myPid) {
                 final String path =
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
index 612b7cb..9fed158 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
@@ -150,7 +150,7 @@
         mTrackedGarbage = leakDetector.getTrackedGarbage();
         mLeakReporter = leakReporter;
 
-        mDumpTruck = new DumpTruck(mContext);
+        mDumpTruck = new DumpTruck(mContext, this);
 
         dumpManager.registerDumpable(getClass().getSimpleName(), this);
 
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
index 31b17f8..6fefce2 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -41,7 +41,6 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.systemui.CoreStartable;
-import com.android.systemui.Dependency;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.WMComponent;
 import com.android.systemui.dagger.qualifiers.Main;
@@ -125,6 +124,7 @@
     private final SysUiState mSysUiState;
     private final WakefulnessLifecycle mWakefulnessLifecycle;
     private final ProtoTracer mProtoTracer;
+    private final UserInfoController mUserInfoController;
     private final Executor mSysUiMainExecutor;
 
     private boolean mIsSysUiStateValid;
@@ -153,6 +153,7 @@
             SysUiState sysUiState,
             ProtoTracer protoTracer,
             WakefulnessLifecycle wakefulnessLifecycle,
+            UserInfoController userInfoController,
             @Main Executor sysUiMainExecutor) {
         super(context);
         mCommandQueue = commandQueue;
@@ -171,6 +172,7 @@
         mShellCommandHandler = shellCommandHandler;
         mCompatUIOptional = sizeCompatUIOptional;
         mDragAndDropOptional = dragAndDropOptional;
+        mUserInfoController = userInfoController;
         mSysUiMainExecutor = sysUiMainExecutor;
     }
 
@@ -231,8 +233,7 @@
         });
 
         // The media session listener needs to be re-registered when switching users
-        UserInfoController userInfoController = Dependency.get(UserInfoController.class);
-        userInfoController.addCallback((String name, Drawable picture, String userAccount) ->
+        mUserInfoController.addCallback((String name, Drawable picture, String userAccount) ->
                 pip.registerSessionListenerForCurrentUser());
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java
index 0b399cf..ae1268d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java
@@ -56,6 +56,7 @@
 import android.widget.ScrollView;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -75,6 +76,7 @@
 
     private @Mock AuthDialogCallback mCallback;
     private @Mock UserManager mUserManager;
+    private @Mock WakefulnessLifecycle mWakefulnessLifecycle;
 
     @Before
     public void setup() {
@@ -263,15 +265,17 @@
                 componentInfo,
                 FingerprintSensorProperties.TYPE_REAR,
                 false /* resetLockoutRequiresHardwareAuthToken */));
-        mAuthContainer = new TestableAuthContainer(config, fpProps, null /* faceProps */);
+        mAuthContainer = new TestableAuthContainer(config, fpProps, null /* faceProps */,
+                mWakefulnessLifecycle);
     }
 
     private class TestableAuthContainer extends AuthContainerView {
         TestableAuthContainer(AuthContainerView.Config config,
                 @Nullable List<FingerprintSensorPropertiesInternal> fpProps,
-                @Nullable List<FaceSensorPropertiesInternal> faceProps) {
+                @Nullable List<FaceSensorPropertiesInternal> faceProps,
+                WakefulnessLifecycle wakefulnessLifecycle) {
 
-            super(config, new MockInjector(), fpProps, faceProps);
+            super(config, new MockInjector(), fpProps, faceProps, wakefulnessLifecycle);
         }
 
         @Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
index 08c7714..786f547 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -69,6 +69,7 @@
 
 import com.android.internal.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.util.concurrency.Execution;
 import com.android.systemui.util.concurrency.FakeExecution;
@@ -117,6 +118,8 @@
     private SidefpsController mSidefpsController;
     @Mock
     private DisplayManager mDisplayManager;
+    @Mock
+    private WakefulnessLifecycle mWakefulnessLifecycle;
     @Captor
     ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mAuthenticatorsRegisteredCaptor;
     @Captor
@@ -677,14 +680,15 @@
                 Provider<SidefpsController> sidefpsControllerFactory) {
             super(context, execution, commandQueue, activityTaskManager, windowManager,
                     fingerprintManager, faceManager, udfpsControllerFactory,
-                    sidefpsControllerFactory, mDisplayManager, mHandler);
+                    sidefpsControllerFactory, mDisplayManager, mWakefulnessLifecycle, mHandler);
         }
 
         @Override
         protected AuthDialog buildDialog(PromptInfo promptInfo,
                 boolean requireConfirmation, int userId, int[] sensorIds, boolean credentialAllowed,
                 String opPackageName, boolean skipIntro, long operationId, long requestId,
-                @BiometricManager.BiometricMultiSensorMode int multiSensorConfig) {
+                @BiometricManager.BiometricMultiSensorMode int multiSensorConfig,
+                WakefulnessLifecycle wakefulnessLifecycle) {
 
             mLastBiometricPromptInfo = promptInfo;
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
index 89c0712..421ae03 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
@@ -100,7 +100,7 @@
     public void getItemCount_zeroMode_containExtraOneForPairNew() {
         when(mMediaOutputController.isZeroMode()).thenReturn(true);
 
-        assertThat(mMediaOutputAdapter.getItemCount()).isEqualTo(mMediaDevices.size());
+        assertThat(mMediaOutputAdapter.getItemCount()).isEqualTo(mMediaDevices.size() + 1);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
index e73e5ff..721809c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
@@ -28,7 +28,6 @@
 import static org.mockito.Mockito.when;
 
 import android.content.BroadcastReceiver;
-import android.content.Context;
 import android.content.IntentFilter;
 import android.os.BatteryManager;
 import android.os.Handler;
@@ -81,9 +80,9 @@
     private static final int OLD_BATTERY_LEVEL_10 = 10;
     private static final long VERY_BELOW_SEVERE_HYBRID_THRESHOLD = TimeUnit.MINUTES.toMillis(15);
     public static final int BATTERY_LEVEL_10 = 10;
-    private WarningsUI mMockWarnings;
+    @Mock private WarningsUI mMockWarnings;
     private PowerUI mPowerUI;
-    private EnhancedEstimates mEnhancedEstimates;
+    @Mock private EnhancedEstimates mEnhancedEstimates;
     @Mock private PowerManager mPowerManager;
     @Mock private IThermalService mThermalServiceMock;
     private IThermalEventListener mUsbThermalEventListener;
@@ -96,13 +95,9 @@
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
-        mMockWarnings = mDependency.injectMockDependency(WarningsUI.class);
-        mEnhancedEstimates = mDependency.injectMockDependency(EnhancedEstimates.class);
 
         when(mStatusBarOptionalLazy.get()).thenReturn(Optional.of(mStatusBar));
 
-        mContext.addMockSystemService(Context.POWER_SERVICE, mPowerManager);
-
         createPowerUi();
         mSkinThermalEventListener = mPowerUI.new SkinThermalEventListener();
         mUsbThermalEventListener = mPowerUI.new UsbThermalEventListener();
@@ -690,7 +685,8 @@
 
     private void createPowerUi() {
         mPowerUI = new PowerUI(
-                mContext, mBroadcastDispatcher, mCommandQueue, mStatusBarOptionalLazy);
+                mContext, mBroadcastDispatcher, mCommandQueue, mStatusBarOptionalLazy,
+                mMockWarnings, mEnhancedEstimates, mPowerManager);
         mPowerUI.mThermalService = mThermalServiceMock;
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
index 3242adb..b5ce706 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
@@ -80,6 +80,8 @@
     @Mock
     private TunerService mTunerService;
     @Mock
+    private QSFgsManagerFooter mQSFgsManagerFooter;
+    @Mock
     private QSSecurityFooter mQSSecurityFooter;
     @Mock
     private QSLogger mQSLogger;
@@ -127,8 +129,8 @@
                 .thenReturn(mQSTileRevealController);
         when(mMediaHost.getDisappearParameters()).thenReturn(new DisappearParameters());
 
-        mController = new QSPanelController(mQSPanel, mQSSecurityFooter, mTunerService,
-                mQSTileHost, mQSCustomizerController, true, mMediaHost,
+        mController = new QSPanelController(mQSPanel, mQSFgsManagerFooter, mQSSecurityFooter,
+                mTunerService, mQSTileHost, mQSCustomizerController, true, mMediaHost,
                 mQSTileRevealControllerFactory, mDumpManager, mMetricsLogger, mUiEventLogger,
                 mQSLogger, mBrightnessControllerFactory, mToggleSliderViewControllerFactory,
                 mFalsingManager, mCommandQueue
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSFactoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSFactoryImplTest.kt
index 968b12a..88b133e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSFactoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSFactoryImplTest.kt
@@ -34,7 +34,6 @@
 import com.android.systemui.qs.tiles.DataSaverTile
 import com.android.systemui.qs.tiles.DeviceControlsTile
 import com.android.systemui.qs.tiles.DndTile
-import com.android.systemui.qs.tiles.FgsManagerTile
 import com.android.systemui.qs.tiles.FlashlightTile
 import com.android.systemui.qs.tiles.HotspotTile
 import com.android.systemui.qs.tiles.InternetTile
@@ -92,7 +91,6 @@
         "wallet" to QuickAccessWalletTile::class.java,
         "qr_code_scanner" to QRCodeScannerTile::class.java,
         "onehanded" to OneHandedModeTile::class.java,
-        "fgsmanager" to FgsManagerTile::class.java,
         "color_correction" to ColorCorrectionTile::class.java
 )
 
@@ -133,7 +131,6 @@
     @Mock private lateinit var quickAccessWalletTile: QuickAccessWalletTile
     @Mock private lateinit var qrCodeScannerTile: QRCodeScannerTile
     @Mock private lateinit var oneHandedModeTile: OneHandedModeTile
-    @Mock private lateinit var fgsManagerTile: FgsManagerTile
     @Mock private lateinit var colorCorrectionTile: ColorCorrectionTile
 
     private lateinit var factory: QSFactoryImpl
@@ -178,7 +175,6 @@
                 { quickAccessWalletTile },
                 { qrCodeScannerTile },
                 { oneHandedModeTile },
-                { fgsManagerTile },
                 { colorCorrectionTile }
         )
         // When adding/removing tiles, fix also [specMap]
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/LocationControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/LocationControllerImplTest.java
index 2126dda..f5554c5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/LocationControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/LocationControllerImplTest.java
@@ -14,6 +14,8 @@
 
 package com.android.systemui.statusbar.policy;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
@@ -27,6 +29,7 @@
 import android.os.Handler;
 import android.os.UserHandle;
 import android.provider.DeviceConfig;
+import android.provider.Settings;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
@@ -34,6 +37,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
+import com.android.internal.logging.testing.UiEventLoggerFake;
 import com.android.systemui.BootCompleteCache;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.appops.AppOpItem;
@@ -43,6 +47,7 @@
 import com.android.systemui.statusbar.policy.LocationController.LocationChangeCallback;
 import com.android.systemui.util.DeviceConfigProxy;
 import com.android.systemui.util.DeviceConfigProxyFake;
+import com.android.systemui.util.settings.SecureSettings;
 
 import com.google.common.collect.ImmutableList;
 
@@ -60,9 +65,11 @@
     private LocationControllerImpl mLocationController;
     private TestableLooper mTestableLooper;
     private DeviceConfigProxy mDeviceConfigProxy;
+    private UiEventLoggerFake mUiEventLogger;
 
     @Mock private AppOpsController mAppOpsController;
     @Mock private UserTracker mUserTracker;
+    @Mock private SecureSettings mSecureSettings;
 
     @Before
     public void setup() {
@@ -72,6 +79,7 @@
         when(mUserTracker.getUserProfiles())
                 .thenReturn(ImmutableList.of(new UserInfo(0, "name", 0)));
         mDeviceConfigProxy = new DeviceConfigProxyFake();
+        mUiEventLogger = new UiEventLoggerFake();
 
         mTestableLooper = TestableLooper.get(this);
         mLocationController = new LocationControllerImpl(mContext,
@@ -82,7 +90,9 @@
                 mock(BroadcastDispatcher.class),
                 mock(BootCompleteCache.class),
                 mUserTracker,
-                mContext.getPackageManager());
+                mContext.getPackageManager(),
+                mUiEventLogger,
+                mSecureSettings);
 
         mTestableLooper.processAllMessages();
     }
@@ -160,6 +170,10 @@
         mTestableLooper.processAllMessages();
 
         verify(callback, times(1)).onLocationActiveChanged(anyBoolean());
+        assertThat(mUiEventLogger.numLogs()).isEqualTo(1);
+        assertThat(mUiEventLogger.eventId(0)).isEqualTo(
+                LocationControllerImpl.LocationIndicatorEvent.LOCATION_INDICATOR_MONITOR_HIGH_POWER
+                        .getId());
     }
 
     @Test
@@ -194,7 +208,7 @@
     }
 
     @Test
-    public void testCallbackNotified_additionalOps_shouldShowSystem() {
+    public void testCallbackNotified_additionalOps_shouldNotShowSystem() {
         LocationChangeCallback callback = mock(LocationChangeCallback.class);
         mLocationController.addCallback(callback);
         mDeviceConfigProxy.setProperty(
@@ -219,7 +233,9 @@
 
 
     @Test
-    public void testCallbackNotified_additionalOps_shouldNotShowSystem() {
+    public void testCallbackNotified_additionalOps_shouldShowSystem() {
+        when(mSecureSettings.getInt(Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 0))
+                .thenReturn(1);
         LocationChangeCallback callback = mock(LocationChangeCallback.class);
         mLocationController.addCallback(callback);
         mDeviceConfigProxy.setProperty(
@@ -251,6 +267,66 @@
         mTestableLooper.processAllMessages();
 
         verify(callback, times(1)).onLocationActiveChanged(false);
+
+        when(mSecureSettings.getInt(Settings.Secure.LOCATION_SHOW_SYSTEM_OPS, 0))
+                .thenReturn(0);
+        mLocationController.onActiveStateChanged(AppOpsManager.OP_FINE_LOCATION, 0,
+                "com.google.android.gms", true);
+
+        mTestableLooper.processAllMessages();
+
+        // onLocationActive(true) was not called again because the setting is disabled.
+        verify(callback, times(1)).onLocationActiveChanged(true);
+    }
+
+    @Test
+    public void testCallbackNotified_verifyMetrics() {
+        LocationChangeCallback callback = mock(LocationChangeCallback.class);
+        mLocationController.addCallback(callback);
+        mDeviceConfigProxy.setProperty(
+                DeviceConfig.NAMESPACE_PRIVACY,
+                SystemUiDeviceConfigFlags.PROPERTY_LOCATION_INDICATORS_SMALL_ENABLED,
+                "true",
+                true);
+        mTestableLooper.processAllMessages();
+
+        when(mAppOpsController.getActiveAppOps())
+                .thenReturn(ImmutableList.of(
+                        new AppOpItem(AppOpsManager.OP_FINE_LOCATION, 0, "com.google.android.gms",
+                                System.currentTimeMillis()),
+                        new AppOpItem(AppOpsManager.OP_COARSE_LOCATION, 0,
+                                "com.google.android.googlequicksearchbox",
+                                System.currentTimeMillis()),
+                        new AppOpItem(AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION, 0,
+                                "com.google.android.apps.maps",
+                                System.currentTimeMillis())));
+        mLocationController.onActiveStateChanged(AppOpsManager.OP_FINE_LOCATION, 0,
+                "com.google.android.gms", true);
+
+        mTestableLooper.processAllMessages();
+
+        verify(callback, times(1)).onLocationActiveChanged(true);
+        assertThat(mUiEventLogger.numLogs()).isEqualTo(3);
+        assertThat(mUiEventLogger.eventId(0)).isEqualTo(
+                LocationControllerImpl.LocationIndicatorEvent.LOCATION_INDICATOR_MONITOR_HIGH_POWER
+                        .getId());
+        // Even though the system access wasn't shown due to the device settings, ensure it was
+        // still logged.
+        assertThat(mUiEventLogger.eventId(1)).isEqualTo(
+                LocationControllerImpl.LocationIndicatorEvent.LOCATION_INDICATOR_SYSTEM_APP
+                        .getId());
+        assertThat(mUiEventLogger.eventId(2)).isEqualTo(
+                LocationControllerImpl.LocationIndicatorEvent.LOCATION_INDICATOR_NON_SYSTEM_APP
+                        .getId());
+        mUiEventLogger.getLogs().clear();
+
+        when(mAppOpsController.getActiveAppOps()).thenReturn(ImmutableList.of());
+        mLocationController.onActiveStateChanged(AppOpsManager.OP_FINE_LOCATION, 0,
+                "com.google.android.gms", false);
+        mTestableLooper.processAllMessages();
+
+        verify(callback, times(1)).onLocationActiveChanged(false);
+        assertThat(mUiEventLogger.numLogs()).isEqualTo(0);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
index 2f2e536..6593823 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
@@ -32,6 +32,7 @@
 import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.UserInfoController;
 import com.android.systemui.tracing.ProtoTracer;
 import com.android.wm.shell.ShellCommandHandler;
 import com.android.wm.shell.common.ShellExecutor;
@@ -79,6 +80,7 @@
     @Mock ProtoTracer mProtoTracer;
     @Mock ShellCommandHandler mShellCommandHandler;
     @Mock CompatUI mCompatUI;
+    @Mock UserInfoController mUserInfoController;
     @Mock ShellExecutor mSysUiMainExecutor;
     @Mock DragAndDrop mDragAndDrop;
 
@@ -92,7 +94,7 @@
                 Optional.of(mDragAndDrop),
                 mCommandQueue, mConfigurationController, mKeyguardUpdateMonitor,
                 mNavigationModeController, mScreenLifecycle, mSysUiState, mProtoTracer,
-                mWakefulnessLifecycle, mSysUiMainExecutor);
+                mWakefulnessLifecycle, mUserInfoController, mSysUiMainExecutor);
     }
 
     @Test
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 5d48d78..2f8dea7 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -323,13 +323,20 @@
         if (mHealthInfo.batteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN) {
             return true;
         }
-        if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_AC) != 0 && mHealthInfo.chargerAcOnline) {
+        if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_AC) != 0
+                && mHealthInfo.chargerAcOnline) {
             return true;
         }
-        if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_USB) != 0 && mHealthInfo.chargerUsbOnline) {
+        if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_USB) != 0
+                && mHealthInfo.chargerUsbOnline) {
             return true;
         }
-        if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0 && mHealthInfo.chargerWirelessOnline) {
+        if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0
+                && mHealthInfo.chargerWirelessOnline) {
+            return true;
+        }
+        if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_DOCK) != 0
+                && mHealthInfo.chargerDockOnline) {
             return true;
         }
         return false;
@@ -442,6 +449,8 @@
             return BatteryManager.BATTERY_PLUGGED_USB;
         } else if (healthInfo.chargerWirelessOnline) {
             return BatteryManager.BATTERY_PLUGGED_WIRELESS;
+        } else if (healthInfo.chargerDockOnline) {
+            return BatteryManager.BATTERY_PLUGGED_DOCK;
         } else {
             return BATTERY_PLUGGED_NONE;
         }
@@ -1118,6 +1127,8 @@
                 batteryPluggedValue = OsProtoEnums.BATTERY_PLUGGED_USB;
             } else if (mHealthInfo.chargerWirelessOnline) {
                 batteryPluggedValue = OsProtoEnums.BATTERY_PLUGGED_WIRELESS;
+            } else if (mHealthInfo.chargerDockOnline) {
+                batteryPluggedValue = OsProtoEnums.BATTERY_PLUGGED_DOCK;
             }
             proto.write(BatteryServiceDumpProto.PLUGGED, batteryPluggedValue);
             proto.write(
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b1b4c44..f67e732 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2871,51 +2871,13 @@
         return mode == AppOpsManager.MODE_ALLOWED;
     }
 
-    /**
-     * Checks whether the calling package is trusted.
-     *
-     * The calling package is trusted if it's from system or the supposed package name matches the
-     * UID making the call.
-     *
-     * @throws SecurityException if the package name and UID don't match.
-     */
-    private void verifyCallingPackage(String callingPackage) {
-        final int callingUid = Binder.getCallingUid();
-        // The caller is System or Shell.
-        if (callingUid == SYSTEM_UID || isCallerShell()) {
-            return;
-        }
-
-        // Handle the special UIDs that don't have real package (audioserver, cameraserver, etc).
-        final String resolvedPackage = AppOpsManager.resolvePackageName(callingUid,
-                null /* packageName */);
-        if (resolvedPackage != null && resolvedPackage.equals(callingPackage)) {
-            return;
-        }
-
-        final int claimedUid = getPackageManagerInternal().getPackageUid(callingPackage,
-                0 /* flags */, UserHandle.getUserId(callingUid));
-        if (callingUid == claimedUid) {
-            return;
-        }
-
-        throw new SecurityException(
-                "Claimed calling package " + callingPackage + " does not match the calling UID "
-                        + Binder.getCallingUid());
-    }
-
-    private void enforceUsageStatsPermission(String callingPackage, String func) {
-        verifyCallingPackage(callingPackage);
-        // Since the protection level of PACKAGE_USAGE_STATS has 'appop', apps may grant this
-        // permission via that way. We need to check both app-ops and permission.
-        if (!hasUsageStatsPermission(callingPackage)) {
-            enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS, func);
-        }
-    }
-
     @Override
     public int getPackageProcessState(String packageName, String callingPackage) {
-        enforceUsageStatsPermission(callingPackage, "getPackageProcessState");
+        if (!hasUsageStatsPermission(callingPackage)) {
+            enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS,
+                    "getPackageProcessState");
+        }
+
         final int[] procState = {PROCESS_STATE_NONEXISTENT};
         synchronized (mProcLock) {
             mProcessList.forEachLruProcessesLOSP(false, proc -> {
@@ -6976,7 +6938,11 @@
 
     @Override
     public int getUidProcessState(int uid, String callingPackage) {
-        enforceUsageStatsPermission(callingPackage, "getUidProcessState");
+        if (!hasUsageStatsPermission(callingPackage)) {
+            enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS,
+                    "getUidProcessState");
+        }
+
         synchronized (mProcLock) {
             return mProcessList.getUidProcStateLOSP(uid);
         }
@@ -6984,7 +6950,11 @@
 
     @Override
     public @ProcessCapability int getUidProcessCapabilities(int uid, String callingPackage) {
-        enforceUsageStatsPermission(callingPackage, "getUidProcessCapabilities");
+        if (!hasUsageStatsPermission(callingPackage)) {
+            enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS,
+                    "getUidProcessState");
+        }
+
         synchronized (mProcLock) {
             return mProcessList.getUidProcessCapabilityLOSP(uid);
         }
@@ -6993,7 +6963,10 @@
     @Override
     public void registerUidObserver(IUidObserver observer, int which, int cutpoint,
             String callingPackage) {
-        enforceUsageStatsPermission(callingPackage, "registerUidObserver");
+        if (!hasUsageStatsPermission(callingPackage)) {
+            enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS,
+                    "registerUidObserver");
+        }
         mUidObserverController.register(observer, which, cutpoint, callingPackage,
                 Binder.getCallingUid());
     }
@@ -7005,7 +6978,10 @@
 
     @Override
     public boolean isUidActive(int uid, String callingPackage) {
-        enforceUsageStatsPermission(callingPackage, "isUidActive");
+        if (!hasUsageStatsPermission(callingPackage)) {
+            enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS,
+                    "isUidActive");
+        }
         synchronized (mProcLock) {
             if (isUidActiveLOSP(uid)) {
                 return true;
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index bb939b7..ec6b782 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -28,6 +28,7 @@
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_BROADCAST;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_MU;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.AppGlobals;
@@ -37,6 +38,7 @@
 import android.app.PendingIntent;
 import android.app.RemoteServiceException.CannotDeliverBroadcastException;
 import android.app.usage.UsageEvents.Event;
+import android.app.usage.UsageStatsManagerInternal;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.IIntentReceiver;
@@ -69,6 +71,7 @@
 
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FrameworkStatsLog;
+import com.android.server.LocalServices;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -325,6 +328,7 @@
         mService.updateOomAdjPendingTargetsLocked(OomAdjuster.OOM_ADJ_REASON_START_RECEIVER);
 
         // Tell the application to launch this receiver.
+        maybeReportBroadcastDispatchedEventLocked(r);
         r.intent.setComponent(r.curComponent);
 
         boolean started = false;
@@ -917,6 +921,7 @@
                 r.receiverTime = SystemClock.uptimeMillis();
                 maybeAddAllowBackgroundActivityStartsToken(filter.receiverList.app, r);
                 maybeScheduleTempAllowlistLocked(filter.owningUid, r, r.options);
+                maybeReportBroadcastDispatchedEventLocked(r);
                 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                         new Intent(r.intent), r.resultCode, r.resultData,
                         r.resultExtras, r.ordered, r.initialSticky, r.userId);
@@ -1831,6 +1836,45 @@
         mPendingBroadcastRecvIndex = recIdx;
     }
 
+
+    @Nullable
+    private String getTargetPackage(BroadcastRecord r) {
+        if (r.intent == null) {
+            return null;
+        }
+        if (r.intent.getPackage() != null) {
+            return r.intent.getPackage();
+        } else if (r.intent.getComponent() != null) {
+            return r.intent.getComponent().getPackageName();
+        }
+        return null;
+    }
+
+    private void maybeReportBroadcastDispatchedEventLocked(BroadcastRecord r) {
+        final String targetPackage = getTargetPackage(r);
+        // Ignore non-explicit broadcasts
+        if (targetPackage == null) {
+            return;
+        }
+        // TODO (206518114): Only allow apps with ACCESS_PACKAGE_USAGE_STATS to set
+        // getIdForResponseEvent.
+        if (r.options == null || r.options.getIdForResponseEvent() <= 0) {
+            return;
+        }
+        // TODO (206518114): Only report this event when the broadcast is dispatched while the app
+        // is in the background state.
+        getUsageStatsManagerInternal().reportBroadcastDispatched(
+                r.callingUid, targetPackage, UserHandle.of(r.userId),
+                r.options.getIdForResponseEvent(), SystemClock.elapsedRealtime());
+    }
+
+    @NonNull
+    private UsageStatsManagerInternal getUsageStatsManagerInternal() {
+        final UsageStatsManagerInternal usageStatsManagerInternal =
+                LocalServices.getService(UsageStatsManagerInternal.class);
+        return usageStatsManagerInternal;
+    }
+
     private boolean noteOpForManifestReceiver(int appOp, BroadcastRecord r, ResolveInfo info,
             ComponentName component) {
         if (ArrayUtils.isEmpty(info.activityInfo.attributionTags)) {
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 6ec9836..42fca9b 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -371,7 +371,7 @@
      * @return false if SCO isn't connected
      */
     /*package*/ synchronized boolean isBluetoothScoOn() {
-        if (mBluetoothHeadset == null) {
+        if (mBluetoothHeadset == null || mBluetoothHeadsetDevice == null) {
             return false;
         }
         return mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice)
@@ -505,7 +505,7 @@
         // Discard timeout message
         mDeviceBroker.handleCancelFailureToConnectToBtHeadsetService();
         mBluetoothHeadset = headset;
-        setBtScoActiveDevice(mBluetoothHeadset.getActiveDevice());
+        setBtScoActiveDevice(headset != null ? headset.getActiveDevice() : null);
         // Refresh SCO audio state
         checkScoAudioState();
         if (mScoAudioState != SCO_STATE_ACTIVATE_REQ
@@ -513,7 +513,7 @@
             return;
         }
         boolean status = false;
-        if (mBluetoothHeadsetDevice != null) {
+        if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
             switch (mScoAudioState) {
                 case SCO_STATE_ACTIVATE_REQ:
                     status = connectBluetoothScoAudioHelper(
@@ -552,6 +552,9 @@
     }
 
     private AudioDeviceAttributes btHeadsetDeviceToAudioDevice(BluetoothDevice btDevice) {
+        if (btDevice == null) {
+            return new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, "");
+        }
         String address = btDevice.getAddress();
         if (!BluetoothAdapter.checkBluetoothAddress(address)) {
             address = "";
diff --git a/services/core/java/com/android/server/clipboard/OWNERS b/services/core/java/com/android/server/clipboard/OWNERS
index 5449df9..0d5dbf9 100644
--- a/services/core/java/com/android/server/clipboard/OWNERS
+++ b/services/core/java/com/android/server/clipboard/OWNERS
@@ -1 +1,3 @@
 per-file EmulatorClipboardMonitor.java = bohu@google.com,lfy@google.com,rkir@google.com
+
+olilan@google.com
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index 240168b..a1d722b 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -32,6 +32,7 @@
 import com.android.internal.display.BrightnessSynchronizer;
 import com.android.internal.util.Preconditions;
 import com.android.server.display.utils.Plog;
+import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
 
 import java.io.PrintWriter;
 import java.util.Arrays;
@@ -69,7 +70,7 @@
     @Nullable
     public static BrightnessMappingStrategy create(Resources resources,
             DisplayDeviceConfig displayDeviceConfig) {
-        return create(resources, displayDeviceConfig, /* isForIdleMode= */ false);
+        return create(resources, displayDeviceConfig, /* isForIdleMode= */ false, null);
     }
 
     /**
@@ -80,8 +81,10 @@
      */
     @Nullable
     public static BrightnessMappingStrategy createForIdleMode(Resources resources,
-            DisplayDeviceConfig displayDeviceConfig) {
-        return create(resources, displayDeviceConfig, /* isForIdleMode= */ true);
+            DisplayDeviceConfig displayDeviceConfig, DisplayWhiteBalanceController
+            displayWhiteBalanceController) {
+        return create(resources, displayDeviceConfig, /* isForIdleMode= */ true,
+                displayWhiteBalanceController);
     }
 
     /**
@@ -96,7 +99,8 @@
      */
     @Nullable
     private static BrightnessMappingStrategy create(Resources resources,
-            DisplayDeviceConfig displayDeviceConfig, boolean isForIdleMode) {
+            DisplayDeviceConfig displayDeviceConfig, boolean isForIdleMode,
+            DisplayWhiteBalanceController displayWhiteBalanceController) {
 
         // Display independent, mode dependent values
         float[] brightnessLevelsNits;
@@ -135,7 +139,7 @@
             builder.setShortTermModelLowerLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO);
             builder.setShortTermModelUpperLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO);
             return new PhysicalMappingStrategy(builder.build(), nitsRange, brightnessRange,
-                    autoBrightnessAdjustmentMaxGamma, isForIdleMode);
+                    autoBrightnessAdjustmentMaxGamma, isForIdleMode, displayWhiteBalanceController);
         } else if (isValidMapping(luxLevels, brightnessLevelsBacklight) && !isForIdleMode) {
             return new SimpleMappingStrategy(luxLevels, brightnessLevelsBacklight,
                     autoBrightnessAdjustmentMaxGamma, shortTermModelTimeout);
@@ -770,9 +774,11 @@
         private float mUserLux;
         private float mUserBrightness;
         private final boolean mIsForIdleMode;
+        private final DisplayWhiteBalanceController mDisplayWhiteBalanceController;
 
         public PhysicalMappingStrategy(BrightnessConfiguration config, float[] nits,
-                float[] brightness, float maxGamma, boolean isForIdleMode) {
+                float[] brightness, float maxGamma, boolean isForIdleMode,
+                DisplayWhiteBalanceController displayWhiteBalanceController) {
 
             Preconditions.checkArgument(nits.length != 0 && brightness.length != 0,
                     "Nits and brightness arrays must not be empty!");
@@ -789,6 +795,7 @@
             mAutoBrightnessAdjustment = 0;
             mUserLux = -1;
             mUserBrightness = -1;
+            mDisplayWhiteBalanceController = displayWhiteBalanceController;
 
             mNits = nits;
             mBrightness = brightness;
@@ -836,6 +843,12 @@
         public float getBrightness(float lux, String packageName,
                 @ApplicationInfo.Category int category) {
             float nits = mBrightnessSpline.interpolate(lux);
+
+            // Adjust nits to compensate for display white balance colour strength.
+            if (mDisplayWhiteBalanceController != null && isForIdleMode()) {
+                nits = mDisplayWhiteBalanceController.calculateAdjustedBrightnessNits(nits);
+            }
+
             float brightness = mNitsToBrightnessSpline.interpolate(nits);
             // Correct the brightness according to the current application and its category, but
             // only if no user data point is set (as this will override the user setting).
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 3feffc6..7ad4979 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -1318,7 +1318,9 @@
 
         if (callingUid != Process.SYSTEM_UID
                 && (flags & VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP) != 0) {
-            if (!checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) {
+            // The virtualDevice instance has been validated above using isValidVirtualDevice
+            if (virtualDevice == null
+                    && !checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) {
                 throw new SecurityException("Requires ADD_TRUSTED_DISPLAY permission to "
                         + "create a virtual display which is not in the default DisplayGroup.");
             }
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 31c496ed..ec4b91a 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -50,6 +50,8 @@
 import android.provider.Settings;
 import android.util.Log;
 import android.util.MathUtils;
+import android.util.MutableFloat;
+import android.util.MutableInt;
 import android.util.Slog;
 import android.util.TimeUtils;
 import android.view.Display;
@@ -895,7 +897,7 @@
                 mDisplayDeviceConfig);
         if (isIdleScreenBrightnessEnabled) {
             mIdleModeBrightnessMapper = BrightnessMappingStrategy.createForIdleMode(resources,
-                    mDisplayDeviceConfig);
+                    mDisplayDeviceConfig, mDisplayWhiteBalanceController);
         }
 
         if (mInteractiveModeBrightnessMapper != null) {
@@ -1390,6 +1392,7 @@
 
         // Animate the screen brightness when the screen is on or dozing.
         // Skip the animation when the screen is off or suspended or transition to/from VR.
+        boolean brightnessAdjusted = false;
         if (!mPendingScreenOff) {
             if (mSkipScreenOnBrightnessRamp) {
                 if (state == Display.STATE_ON) {
@@ -1482,15 +1485,19 @@
                     // slider event so notify as if the system changed the brightness.
                     userInitiatedChange = false;
                 }
-                notifyBrightnessChanged(brightnessState, userInitiatedChange,
+                notifyBrightnessTrackerChanged(brightnessState, userInitiatedChange,
                         hadUserBrightnessPoint);
             }
 
             // We save the brightness info *after* the brightness setting has been changed and
             // adjustments made so that the brightness info reflects the latest value.
-            saveBrightnessInfo(getScreenBrightnessSetting(), animateValue);
+            brightnessAdjusted = saveBrightnessInfo(getScreenBrightnessSetting(), animateValue);
         } else {
-            saveBrightnessInfo(getScreenBrightnessSetting());
+            brightnessAdjusted = saveBrightnessInfo(getScreenBrightnessSetting());
+        }
+
+        if (brightnessAdjusted) {
+            postBrightnessChangeRunnable();
         }
 
         // Log any changes to what is currently driving the brightness setting.
@@ -1606,31 +1613,50 @@
     public BrightnessInfo getBrightnessInfo() {
         synchronized (mCachedBrightnessInfo) {
             return new BrightnessInfo(
-                    mCachedBrightnessInfo.brightness,
-                    mCachedBrightnessInfo.adjustedBrightness,
-                    mCachedBrightnessInfo.brightnessMin,
-                    mCachedBrightnessInfo.brightnessMax,
-                    mCachedBrightnessInfo.hbmMode,
-                    mCachedBrightnessInfo.highBrightnessTransitionPoint);
+                    mCachedBrightnessInfo.brightness.value,
+                    mCachedBrightnessInfo.adjustedBrightness.value,
+                    mCachedBrightnessInfo.brightnessMin.value,
+                    mCachedBrightnessInfo.brightnessMax.value,
+                    mCachedBrightnessInfo.hbmMode.value,
+                    mCachedBrightnessInfo.hbmTransitionPoint.value);
         }
     }
 
-    private void saveBrightnessInfo(float brightness) {
-        saveBrightnessInfo(brightness, brightness);
+    private boolean saveBrightnessInfo(float brightness) {
+        return saveBrightnessInfo(brightness, brightness);
     }
 
-    private void saveBrightnessInfo(float brightness, float adjustedBrightness) {
+    private boolean saveBrightnessInfo(float brightness, float adjustedBrightness) {
         synchronized (mCachedBrightnessInfo) {
-            mCachedBrightnessInfo.brightness = brightness;
-            mCachedBrightnessInfo.adjustedBrightness = adjustedBrightness;
-            mCachedBrightnessInfo.brightnessMin = mHbmController.getCurrentBrightnessMin();
-            mCachedBrightnessInfo.brightnessMax = mHbmController.getCurrentBrightnessMax();
-            mCachedBrightnessInfo.hbmMode = mHbmController.getHighBrightnessMode();
-            mCachedBrightnessInfo.highBrightnessTransitionPoint =
-                mHbmController.getTransitionPoint();
+            boolean changed = false;
+
+            changed |=
+                mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.brightness,
+                        brightness);
+            changed |=
+                mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.adjustedBrightness,
+                        adjustedBrightness);
+            changed |=
+                mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.brightnessMin,
+                        mHbmController.getCurrentBrightnessMin());
+            changed |=
+                mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.brightnessMax,
+                        mHbmController.getCurrentBrightnessMax());
+            changed |=
+                mCachedBrightnessInfo.checkAndSetInt(mCachedBrightnessInfo.hbmMode,
+                        mHbmController.getHighBrightnessMode());
+            changed |=
+                mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.hbmTransitionPoint,
+                        mHbmController.getTransitionPoint());
+
+            return changed;
         }
     }
 
+    void postBrightnessChangeRunnable() {
+        mHandler.post(mOnBrightnessChangeRunnable);
+    }
+
     private HighBrightnessModeController createHbmControllerLocked() {
         final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
         final DisplayDeviceConfig ddConfig = device.getDisplayDeviceConfig();
@@ -1645,7 +1671,7 @@
                 displayUniqueId, PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, hbmData,
                 () -> {
                     sendUpdatePowerStateLocked();
-                    mHandler.post(mOnBrightnessChangeRunnable);
+                    postBrightnessChangeRunnable();
                     // TODO(b/192258832): Switch the HBMChangeCallback to a listener pattern.
                     if (mAutomaticBrightnessController != null) {
                         mAutomaticBrightnessController.update();
@@ -2147,7 +2173,7 @@
     private void setCurrentScreenBrightness(float brightnessValue) {
         if (brightnessValue != mCurrentScreenBrightnessSetting) {
             mCurrentScreenBrightnessSetting = brightnessValue;
-            mHandler.post(mOnBrightnessChangeRunnable);
+            postBrightnessChangeRunnable();
         }
     }
 
@@ -2199,7 +2225,7 @@
         return true;
     }
 
-    private void notifyBrightnessChanged(float brightness, boolean userInitiated,
+    private void notifyBrightnessTrackerChanged(float brightness, boolean userInitiated,
             boolean hadUserDataPoint) {
         final float brightnessInNits = convertToNits(brightness);
         if (mPowerRequest.useAutoBrightness && brightnessInNits >= 0.0f
@@ -2309,16 +2335,17 @@
         pw.println("  mColorFadeFadesConfig=" + mColorFadeFadesConfig);
         pw.println("  mColorFadeEnabled=" + mColorFadeEnabled);
         synchronized (mCachedBrightnessInfo) {
-            pw.println("  mCachedBrightnessInfo.brightness=" + mCachedBrightnessInfo.brightness);
+            pw.println("  mCachedBrightnessInfo.brightness=" +
+                    mCachedBrightnessInfo.brightness.value);
             pw.println("  mCachedBrightnessInfo.adjustedBrightness=" +
-                    mCachedBrightnessInfo.adjustedBrightness);
+                    mCachedBrightnessInfo.adjustedBrightness.value);
             pw.println("  mCachedBrightnessInfo.brightnessMin=" +
-                    mCachedBrightnessInfo.brightnessMin);
+                    mCachedBrightnessInfo.brightnessMin.value);
             pw.println("  mCachedBrightnessInfo.brightnessMax=" +
-                    mCachedBrightnessInfo.brightnessMax);
-            pw.println("  mCachedBrightnessInfo.hbmMode=" + mCachedBrightnessInfo.hbmMode);
-            pw.println("  mCachedBrightnessInfo.highBrightnessTransitionPoint=" +
-                    mCachedBrightnessInfo.highBrightnessTransitionPoint);
+                    mCachedBrightnessInfo.brightnessMax.value);
+            pw.println("  mCachedBrightnessInfo.hbmMode=" + mCachedBrightnessInfo.hbmMode.value);
+            pw.println("  mCachedBrightnessInfo.hbmTransitionPoint=" +
+                    mCachedBrightnessInfo.hbmTransitionPoint.value);
         }
         pw.println("  mDisplayBlanksAfterDozeConfig=" + mDisplayBlanksAfterDozeConfig);
         pw.println("  mBrightnessBucketsInDozeConfig=" + mBrightnessBucketsInDozeConfig);
@@ -2476,7 +2503,10 @@
     private void reportStats(float brightness) {
         float hbmTransitionPoint = PowerManager.BRIGHTNESS_MAX;
         synchronized(mCachedBrightnessInfo) {
-            hbmTransitionPoint = mCachedBrightnessInfo.highBrightnessTransitionPoint;
+            if (mCachedBrightnessInfo.hbmTransitionPoint == null) {
+                return;
+            }
+            hbmTransitionPoint = mCachedBrightnessInfo.hbmTransitionPoint.value;
         }
 
         final boolean aboveTransition = brightness > hbmTransitionPoint;
@@ -2773,11 +2803,31 @@
     }
 
     static class CachedBrightnessInfo {
-        public float brightness;
-        public float adjustedBrightness;
-        public float brightnessMin;
-        public float brightnessMax;
-        public int hbmMode;
-        public float highBrightnessTransitionPoint;
+        public MutableFloat brightness = new MutableFloat(PowerManager.BRIGHTNESS_INVALID_FLOAT);
+        public MutableFloat adjustedBrightness =
+            new MutableFloat(PowerManager.BRIGHTNESS_INVALID_FLOAT);
+        public MutableFloat brightnessMin =
+            new MutableFloat(PowerManager.BRIGHTNESS_INVALID_FLOAT);
+        public MutableFloat brightnessMax =
+            new MutableFloat(PowerManager.BRIGHTNESS_INVALID_FLOAT);
+        public MutableInt hbmMode = new MutableInt(BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF);
+        public MutableFloat hbmTransitionPoint =
+            new MutableFloat(HighBrightnessModeController.HBM_TRANSITION_POINT_INVALID);
+
+        public boolean checkAndSetFloat(MutableFloat mf, float f) {
+            if (mf.value != f) {
+                mf.value = f;
+                return true;
+            }
+            return false;
+        }
+
+        public boolean checkAndSetInt(MutableInt mi, int i) {
+            if (mi.value != i) {
+                mi.value = i;
+                return true;
+            }
+            return false;
+        }
     }
 }
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 f9a1368..8035526 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java
@@ -1453,7 +1453,7 @@
     /**
      * Local service that allows color transforms to be enabled from other system services.
      */
-    public final class ColorDisplayServiceInternal {
+    public class ColorDisplayServiceInternal {
 
         /**
          * Set the current CCT value for the display white balance transform, and if the transform
@@ -1472,6 +1472,11 @@
             return false;
         }
 
+        /** Get the luminance of the current chromatic adaptation matrix. */
+        public float getDisplayWhiteBalanceLuminance() {
+            return mDisplayWhiteBalanceTintController.getLuminance();
+        }
+
         /**
          * Reset the CCT value for the display white balance transform to its default value.
          */
diff --git a/services/core/java/com/android/server/display/color/DisplayWhiteBalanceTintController.java b/services/core/java/com/android/server/display/color/DisplayWhiteBalanceTintController.java
index bdbaaa8..936149c 100644
--- a/services/core/java/com/android/server/display/color/DisplayWhiteBalanceTintController.java
+++ b/services/core/java/com/android/server/display/color/DisplayWhiteBalanceTintController.java
@@ -251,6 +251,18 @@
         }
     }
 
+    public float getLuminance() {
+        synchronized (mLock) {
+            if (mChromaticAdaptationMatrix != null && mChromaticAdaptationMatrix.length == 9) {
+                // Compute only the luminance (y) value of the xyz * [1 1 1] transform.
+                return 1 / (mChromaticAdaptationMatrix[1] + mChromaticAdaptationMatrix[4]
+                        + mChromaticAdaptationMatrix[7]);
+            } else {
+                return -1;
+            }
+        }
+    }
+
     private ColorSpace.Rgb makeRgbColorSpaceFromXYZ(float[] redGreenBlueXYZ, float[] whiteXYZ) {
         return new ColorSpace.Rgb(
                 "Display Color Space",
diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
index d64fcbc..151ec81 100644
--- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
+++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
@@ -21,7 +21,6 @@
 import android.util.Spline;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.Preconditions;
 import com.android.server.LocalServices;
 import com.android.server.display.color.ColorDisplayService.ColorDisplayServiceInternal;
 import com.android.server.display.utils.AmbientFilter;
@@ -456,6 +455,22 @@
     }
 
     /**
+     * Calculate the adjusted brightness, in nits, due to the DWB color adaptation
+     *
+     * @param requestedBrightnessNits brightness the framework requires to be output
+     * @return the adjusted brightness the framework needs to output to counter the drop in
+     *         brightness due to DWB, or the requestedBrightnessNits if an adjustment cannot be made
+     */
+    public float calculateAdjustedBrightnessNits(float requestedBrightnessNits) {
+        float luminance = mColorDisplayServiceInternal.getDisplayWhiteBalanceLuminance();
+        if (luminance == -1) {
+            return requestedBrightnessNits;
+        }
+        float effectiveBrightness = requestedBrightnessNits * luminance;
+        return (requestedBrightnessNits - effectiveBrightness) + requestedBrightnessNits;
+    }
+
+    /**
      * The DisplayWhiteBalanceController decouples itself from its parent (DisplayPowerController)
      * by providing this interface to implement (and a method to set its callbacks object), and
      * calling these methods.
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 8a6aa0d..feb0d138 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -203,7 +203,7 @@
 /**
  * This class provides a system service that manages input methods.
  */
-public class InputMethodManagerService extends IInputMethodManager.Stub
+public final class InputMethodManagerService extends IInputMethodManager.Stub
         implements Handler.Callback {
     static final boolean DEBUG = false;
     static final String TAG = "InputMethodManagerService";
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index c01851a..fac7a40 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -100,7 +100,6 @@
 import static android.net.NetworkTemplate.MATCH_WIFI;
 import static android.net.NetworkTemplate.buildTemplateCarrierMetered;
 import static android.net.NetworkTemplate.buildTemplateMobileAll;
-import static android.net.TrafficStats.MB_IN_BYTES;
 import static android.net.netstats.provider.NetworkStatsProvider.QUOTA_UNLIMITED;
 import static android.os.Trace.TRACE_TAG_NETWORK;
 import static android.provider.Settings.Global.NETPOLICY_OVERRIDE_ENABLED;
@@ -182,7 +181,6 @@
 import android.net.NetworkStateSnapshot;
 import android.net.NetworkTemplate;
 import android.net.TelephonyNetworkSpecifier;
-import android.net.TrafficStats;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
 import android.os.BestClock;
@@ -2299,7 +2297,7 @@
         if (dataWarningConfig == WARNING_DISABLED) {
             return WARNING_DISABLED;
         } else {
-            return dataWarningConfig * MB_IN_BYTES;
+            return DataUnit.MEBIBYTES.toBytes(dataWarningConfig);
         }
     }
 
@@ -3468,9 +3466,9 @@
                 plans.add(SubscriptionPlan.Builder
                         .createRecurringMonthly(ZonedDateTime.parse("2007-03-14T00:00:00.000Z"))
                         .setTitle("G-Mobile")
-                        .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
                                 SubscriptionPlan.LIMIT_BEHAVIOR_BILLED)
-                        .setDataUsage(1 * TrafficStats.GB_IN_BYTES,
+                        .setDataUsage(DataUnit.GIBIBYTES.toBytes(1),
                                 ZonedDateTime.now().minusHours(36).toInstant().toEpochMilli())
                         .build());
                 plans.add(SubscriptionPlan.Builder
@@ -3478,15 +3476,15 @@
                         .setTitle("G-Mobile Happy")
                         .setDataLimit(SubscriptionPlan.BYTES_UNLIMITED,
                                 SubscriptionPlan.LIMIT_BEHAVIOR_BILLED)
-                        .setDataUsage(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataUsage(DataUnit.GIBIBYTES.toBytes(5),
                                 ZonedDateTime.now().minusHours(36).toInstant().toEpochMilli())
                         .build());
                 plans.add(SubscriptionPlan.Builder
                         .createRecurringMonthly(ZonedDateTime.parse("2017-03-14T00:00:00.000Z"))
                         .setTitle("G-Mobile, Charged after limit")
-                        .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
                                 SubscriptionPlan.LIMIT_BEHAVIOR_BILLED)
-                        .setDataUsage(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataUsage(DataUnit.GIBIBYTES.toBytes(5),
                                 ZonedDateTime.now().minusHours(36).toInstant().toEpochMilli())
                         .build());
             } else if ("month_soft".equals(fake)) {
@@ -3495,25 +3493,25 @@
                         .setTitle("G-Mobile is the carriers name who this plan belongs to")
                         .setSummary("Crazy unlimited bandwidth plan with incredibly long title "
                                 + "that should be cut off to prevent UI from looking terrible")
-                        .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
                                 SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
-                        .setDataUsage(1 * TrafficStats.GB_IN_BYTES,
+                        .setDataUsage(DataUnit.GIBIBYTES.toBytes(1),
                                 ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli())
                         .build());
                 plans.add(SubscriptionPlan.Builder
                         .createRecurringMonthly(ZonedDateTime.parse("2017-03-14T00:00:00.000Z"))
                         .setTitle("G-Mobile, Throttled after limit")
-                        .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
                                 SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
-                        .setDataUsage(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataUsage(DataUnit.GIBIBYTES.toBytes(5),
                                 ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli())
                         .build());
                 plans.add(SubscriptionPlan.Builder
                         .createRecurringMonthly(ZonedDateTime.parse("2017-03-14T00:00:00.000Z"))
                         .setTitle("G-Mobile, No data connection after limit")
-                        .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
                                 SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED)
-                        .setDataUsage(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataUsage(DataUnit.GIBIBYTES.toBytes(5),
                                 ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli())
                         .build());
 
@@ -3521,25 +3519,25 @@
                 plans.add(SubscriptionPlan.Builder
                         .createRecurringMonthly(ZonedDateTime.parse("2007-03-14T00:00:00.000Z"))
                         .setTitle("G-Mobile is the carriers name who this plan belongs to")
-                        .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
                                 SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
-                        .setDataUsage(6 * TrafficStats.GB_IN_BYTES,
+                        .setDataUsage(DataUnit.GIBIBYTES.toBytes(6),
                                 ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli())
                         .build());
                 plans.add(SubscriptionPlan.Builder
                         .createRecurringMonthly(ZonedDateTime.parse("2017-03-14T00:00:00.000Z"))
                         .setTitle("G-Mobile, Throttled after limit")
-                        .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
                                 SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
-                        .setDataUsage(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataUsage(DataUnit.GIBIBYTES.toBytes(5),
                                 ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli())
                         .build());
                 plans.add(SubscriptionPlan.Builder
                         .createRecurringMonthly(ZonedDateTime.parse("2017-03-14T00:00:00.000Z"))
                         .setTitle("G-Mobile, No data connection after limit")
-                        .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
                                 SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED)
-                        .setDataUsage(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataUsage(DataUnit.GIBIBYTES.toBytes(5),
                                 ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli())
                         .build());
 
@@ -3553,9 +3551,9 @@
                         .createNonrecurring(ZonedDateTime.now().minusDays(20),
                                 ZonedDateTime.now().plusDays(10))
                         .setTitle("G-Mobile")
-                        .setDataLimit(512 * TrafficStats.MB_IN_BYTES,
+                        .setDataLimit(DataUnit.MEBIBYTES.toBytes(512),
                                 SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED)
-                        .setDataUsage(100 * TrafficStats.MB_IN_BYTES,
+                        .setDataUsage(DataUnit.MEBIBYTES.toBytes(100),
                                 ZonedDateTime.now().minusHours(3).toInstant().toEpochMilli())
                         .build());
             } else if ("prepaid_crazy".equals(fake)) {
@@ -3563,9 +3561,9 @@
                         .createNonrecurring(ZonedDateTime.now().minusDays(20),
                                 ZonedDateTime.now().plusDays(10))
                         .setTitle("G-Mobile Anytime")
-                        .setDataLimit(512 * TrafficStats.MB_IN_BYTES,
+                        .setDataLimit(DataUnit.MEBIBYTES.toBytes(512),
                                 SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED)
-                        .setDataUsage(100 * TrafficStats.MB_IN_BYTES,
+                        .setDataUsage(DataUnit.MEBIBYTES.toBytes(100),
                                 ZonedDateTime.now().minusHours(3).toInstant().toEpochMilli())
                         .build());
                 plans.add(SubscriptionPlan.Builder
@@ -3573,9 +3571,9 @@
                                 ZonedDateTime.now().plusDays(20))
                         .setTitle("G-Mobile Nickel Nights")
                         .setSummary("5¢/GB between 1-5AM")
-                        .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+                        .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
                                 SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
-                        .setDataUsage(15 * TrafficStats.MB_IN_BYTES,
+                        .setDataUsage(DataUnit.MEBIBYTES.toBytes(15),
                                 ZonedDateTime.now().minusHours(30).toInstant().toEpochMilli())
                         .build());
                 plans.add(SubscriptionPlan.Builder
@@ -3583,9 +3581,9 @@
                                 ZonedDateTime.now().plusDays(20))
                         .setTitle("G-Mobile Bonus 3G")
                         .setSummary("Unlimited 3G data")
-                        .setDataLimit(1 * TrafficStats.GB_IN_BYTES,
+                        .setDataLimit(DataUnit.GIBIBYTES.toBytes(1),
                                 SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
-                        .setDataUsage(300 * TrafficStats.MB_IN_BYTES,
+                        .setDataUsage(DataUnit.MEBIBYTES.toBytes(300),
                                 ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli())
                         .build());
             } else if ("unlimited".equals(fake)) {
@@ -3595,7 +3593,7 @@
                         .setTitle("G-Mobile Awesome")
                         .setDataLimit(SubscriptionPlan.BYTES_UNLIMITED,
                                 SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
-                        .setDataUsage(50 * TrafficStats.MB_IN_BYTES,
+                        .setDataUsage(DataUnit.MEBIBYTES.toBytes(50),
                                 ZonedDateTime.now().minusHours(3).toInstant().toEpochMilli())
                         .build());
             }
diff --git a/services/core/java/com/android/server/notification/VibratorHelper.java b/services/core/java/com/android/server/notification/VibratorHelper.java
index 54dd113..e5d07bc 100644
--- a/services/core/java/com/android/server/notification/VibratorHelper.java
+++ b/services/core/java/com/android/server/notification/VibratorHelper.java
@@ -16,6 +16,9 @@
 
 package com.android.server.notification;
 
+import static android.os.VibrationEffect.VibrationParameter.targetAmplitude;
+import static android.os.VibrationEffect.VibrationParameter.targetFrequency;
+
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Resources;
@@ -30,6 +33,7 @@
 import com.android.internal.R;
 import com.android.server.pm.PackageManagerService;
 
+import java.time.Duration;
 import java.util.Arrays;
 
 /**
@@ -89,8 +93,7 @@
      * Safely create a {@link VibrationEffect} from given waveform description.
      *
      * <p>The waveform is described by a sequence of values for target amplitude, frequency and
-     * duration, that are forwarded to
-     * {@link VibrationEffect.WaveformBuilder#addRamp(float, float, int)}.
+     * duration, that are forwarded to {@link VibrationEffect.WaveformBuilder#addTransition}.
      *
      * <p>This method returns {@code null} if the pattern is also {@code null} or invalid.
      *
@@ -114,16 +117,17 @@
 
             VibrationEffect.WaveformBuilder waveformBuilder = VibrationEffect.startWaveform();
             for (int i = 0; i < length; i += 3) {
-                waveformBuilder.addRamp(
-                        /* amplitude= */ values[i],
-                        /* frequencyHz= */ values[i + 1],
-                        /* duration= */ (int) values[i + 2]);
+                waveformBuilder.addTransition(Duration.ofMillis((int) values[i + 2]),
+                        targetAmplitude(values[i]), targetFrequency(values[i + 1]));
             }
 
+            VibrationEffect effect = waveformBuilder.build();
             if (insistent) {
-                return waveformBuilder.build(/* repeat= */ 0);
+                return VibrationEffect.startComposition()
+                        .repeatEffectIndefinitely(effect)
+                        .compose();
             }
-            return waveformBuilder.build();
+            return effect;
         } catch (IllegalArgumentException e) {
             Slog.e(TAG, "Error creating vibration PWLE waveform with pattern: "
                     + Arrays.toString(values));
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index d9ade96..390dd3f 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -2264,10 +2264,6 @@
         }
 
         if (params.isStaged) {
-            // TODO(b/136257624): CTS test fails if we don't send session finished broadcast, even
-            //  though ideally, we just need to send session committed broadcast.
-            sendUpdateToRemoteStatusReceiver(INSTALL_SUCCEEDED, "Session staged", null);
-
             mStagedSession.verifySession();
         } else {
             verify();
@@ -2514,6 +2510,7 @@
                 mStagedSession.notifyEndPreRebootVerification();
                 if (error == SessionInfo.SESSION_NO_ERROR) {
                     mStagingManager.commitSession(mStagedSession);
+                    sendUpdateToRemoteStatusReceiver(INSTALL_SUCCEEDED, "Session staged", null);
                 } else {
                     dispatchSessionFinished(INSTALL_FAILED_VERIFICATION_FAILURE, msg, null);
                     maybeFinishChildSessions(INSTALL_FAILED_VERIFICATION_FAILURE, msg);
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index fd2256f..99f70b2 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -3563,18 +3563,27 @@
             }
             final LocalIntentReceiver receiver = new LocalIntentReceiver();
             session.commit(receiver.getIntentSender());
-            final Intent result = receiver.getResult();
-            final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
-                    PackageInstaller.STATUS_FAILURE);
-            if (status == PackageInstaller.STATUS_SUCCESS) {
+            if (!session.isStaged()) {
+                final Intent result = receiver.getResult();
+                final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
+                        PackageInstaller.STATUS_FAILURE);
+                if (status == PackageInstaller.STATUS_SUCCESS) {
+                    if (logSuccess) {
+                        pw.println("Success");
+                    }
+                } else {
+                    pw.println("Failure ["
+                            + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
+                }
+                return status;
+            } else {
+                // Return immediately without retrieving the result. The caller will decide
+                // whether to wait for the session to become ready.
                 if (logSuccess) {
                     pw.println("Success");
                 }
-            } else {
-                pw.println("Failure ["
-                        + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
+                return PackageInstaller.STATUS_SUCCESS;
             }
-            return status;
         } finally {
             IoUtils.closeQuietly(session);
         }
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 15e64df..72db242 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -35,8 +35,8 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.LocusId;
-import android.content.pm.AppSearchPerson;
 import android.content.pm.AppSearchShortcutInfo;
+import android.content.pm.AppSearchShortcutPerson;
 import android.content.pm.PackageInfo;
 import android.content.pm.ShortcutInfo;
 import android.content.pm.ShortcutManager;
@@ -965,7 +965,7 @@
      */
     public ArraySet<String> getUsedBitmapFiles() {
         final ArraySet<String> usedFiles = new ArraySet<>(1);
-        forEachShortcut(AppSearchShortcutInfo.QUERY_HAS_BITMAP_PATH, si -> {
+        forEachShortcut(si -> {
             if (si.getBitmapPath() != null) {
                 usedFiles.add(getFileName(si.getBitmapPath()));
             }
@@ -1176,7 +1176,7 @@
 
         // Keep the previous IDs.
         final ArraySet<String> toDisableList = new ArraySet<>(1);
-        forEachShortcut(AppSearchShortcutInfo.QUERY_IS_MANIFEST, si -> {
+        forEachShortcut(si -> {
             if (si.isManifestShortcut()) {
                 toDisableList.add(si.getId());
             }
@@ -1319,7 +1319,7 @@
     private ArrayMap<ComponentName, ArrayList<ShortcutInfo>> sortShortcutsToActivities() {
         final ArrayMap<ComponentName, ArrayList<ShortcutInfo>> activitiesToShortcuts
                 = new ArrayMap<>();
-        forEachShortcut(AppSearchShortcutInfo.QUERY_IS_NOT_FLOATING, si -> {
+        forEachShortcut(si -> {
             if (si.isFloating()) {
                 return; // Ignore floating shortcuts, which are not tied to any activities.
             }
@@ -1369,14 +1369,7 @@
         // (If it's for update, then don't count dynamic shortcuts, since they'll be replaced
         // anyway.)
         final ArrayMap<ComponentName, Integer> counts = new ArrayMap<>(4);
-        final String query;
-        if (operation != ShortcutService.OPERATION_SET) {
-            query = AppSearchShortcutInfo.QUERY_IS_MANIFEST + " OR "
-                    + AppSearchShortcutInfo.QUERY_IS_DYNAMIC;
-        } else {
-            query = AppSearchShortcutInfo.QUERY_IS_MANIFEST;
-        }
-        forEachShortcut(query, shortcut -> {
+        forEachShortcut(shortcut -> {
             if (shortcut.isManifestShortcut()) {
                 incrementCountForActivity(counts, shortcut.getActivity(), 1);
             } else if (shortcut.isDynamic() && (operation != ShortcutService.OPERATION_SET)) {
@@ -1539,7 +1532,7 @@
     /** @return true if there's any shortcuts that are not manifest shortcuts. */
     public boolean hasNonManifestShortcuts() {
         final boolean[] condition = new boolean[1];
-        forEachShortcutStopWhen(AppSearchShortcutInfo.QUERY_IS_NOT_MANIFEST, si -> {
+        forEachShortcutStopWhen(si -> {
             if (!si.isDeclaredInManifest()) {
                 condition[0] = true;
                 return true;
@@ -2287,12 +2280,7 @@
     }
 
     private void forEachShortcut(@NonNull final Consumer<ShortcutInfo> cb) {
-        forEachShortcut("", cb);
-    }
-
-    private void forEachShortcut(
-            @NonNull final String query, @NonNull final Consumer<ShortcutInfo> cb) {
-        forEachShortcutStopWhen(query, si -> {
+        forEachShortcutStopWhen(si -> {
             cb.accept(si);
             return false;
         });
@@ -2307,11 +2295,6 @@
 
     private void forEachShortcutStopWhen(
             @NonNull final Function<ShortcutInfo, Boolean> cb) {
-        forEachShortcutStopWhen("", cb);
-    }
-
-    private void forEachShortcutStopWhen(
-            @NonNull final String query, @NonNull final Function<ShortcutInfo, Boolean> cb) {
         for (int i = mShortcuts.size() - 1; i >= 0; i--) {
             final ShortcutInfo si = mShortcuts.valueAt(i);
             if (cb.apply(si)) {
@@ -2328,12 +2311,12 @@
                     + " pkg=" + getPackageName());
         }
         SetSchemaRequest.Builder schemaBuilder = new SetSchemaRequest.Builder()
-                .addSchemas(AppSearchPerson.SCHEMA, AppSearchShortcutInfo.SCHEMA)
+                .addSchemas(AppSearchShortcutPerson.SCHEMA, AppSearchShortcutInfo.SCHEMA)
                 .setForceOverride(true);
         for (PackageIdentifier pi : mPackageIdentifiers.values()) {
             schemaBuilder = schemaBuilder
                     .setSchemaTypeVisibilityForPackage(
-                            AppSearchPerson.SCHEMA_TYPE, true, pi)
+                            AppSearchShortcutPerson.SCHEMA_TYPE, true, pi)
                     .setSchemaTypeVisibilityForPackage(
                             AppSearchShortcutInfo.SCHEMA_TYPE, true, pi);
         }
@@ -2403,8 +2386,8 @@
                     .addIds(ids).build(), mShortcutUser.mExecutor, result -> {
                     final List<ShortcutInfo> ret = result.getSuccesses().values()
                             .stream().map(doc ->
-                                    new AppSearchShortcutInfo(doc)
-                                            .toShortcutInfo(mShortcutUser.getUserId()))
+                                    ShortcutInfo.createFromGenericDocument(
+                                            mShortcutUser.getUserId(), doc))
                             .collect(Collectors.toList());
                     cb.accept(ret);
                 });
@@ -2480,8 +2463,8 @@
                 }
                 cb.complete(results.getResultValue().stream()
                         .map(SearchResult::getGenericDocument)
-                        .map(AppSearchShortcutInfo::new)
-                        .map(si -> si.toShortcutInfo(mShortcutUser.getUserId()))
+                        .map(doc -> ShortcutInfo.createFromGenericDocument(
+                                mShortcutUser.getUserId(), doc))
                         .collect(Collectors.toList()));
             });
         }));
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 057f8de..8393dee 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -41,7 +41,6 @@
 import android.content.IntentSender.SendIntentException;
 import android.content.LocusId;
 import android.content.pm.ActivityInfo;
-import android.content.pm.AppSearchShortcutInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ComponentInfo;
 import android.content.pm.IPackageManager;
@@ -2805,28 +2804,6 @@
         }
     }
 
-    private String createQuery(final boolean matchDynamic, final boolean matchPinned,
-            final boolean matchManifest, final boolean matchCached) {
-
-        final List<String> queries = new ArrayList<>(1);
-        if (matchDynamic) {
-            queries.add(AppSearchShortcutInfo.QUERY_IS_DYNAMIC);
-        }
-        if (matchPinned) {
-            queries.add(AppSearchShortcutInfo.QUERY_IS_PINNED);
-        }
-        if (matchManifest) {
-            queries.add(AppSearchShortcutInfo.QUERY_IS_MANIFEST);
-        }
-        if (matchCached) {
-            queries.add(AppSearchShortcutInfo.QUERY_IS_CACHED);
-        }
-        if (queries.isEmpty()) {
-            return "";
-        }
-        return "(" + String.join(" OR ", queries) + ")";
-    }
-
     /**
      * Remove all the information associated with a package.  This will really remove all the
      * information, including the restore information (i.e. it'll remove packages even if they're
diff --git a/services/core/java/com/android/server/power/PowerGroup.java b/services/core/java/com/android/server/power/PowerGroup.java
index 9127484..c1bfdf7 100644
--- a/services/core/java/com/android/server/power/PowerGroup.java
+++ b/services/core/java/com/android/server/power/PowerGroup.java
@@ -16,9 +16,16 @@
 
 package com.android.server.power;
 
+import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP;
 import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE;
+import static android.os.PowerManagerInternal.WAKEFULNESS_DOZING;
+import static android.os.PowerManagerInternal.WAKEFULNESS_DREAMING;
+import static android.os.PowerManagerInternal.isInteractive;
 
 import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
+import android.os.PowerManager;
+import android.os.Trace;
+import android.util.Slog;
 import android.view.Display;
 
 /**
@@ -31,47 +38,66 @@
  */
 public class PowerGroup {
     private static final String TAG = PowerGroup.class.getSimpleName();
+    private static final boolean DEBUG = false;
 
     private final DisplayPowerRequest mDisplayPowerRequest;
+    private final PowerGroupListener mWakefulnessListener;
     private final boolean mSupportsSandman;
     private final int mGroupId;
-
-    // True if DisplayManagerService has applied all the latest display states that were requested
-    // for this group
+    /** True if DisplayManagerService has applied all the latest display states that were requested
+     *  for this group. */
     private boolean mReady;
-    // True if this group is in the process of powering on
+    /** True if this group is in the process of powering on */
     private boolean mPoweringOn;
-    // True if this group is about to dream
+    /** True if this group is about to dream */
     private boolean mIsSandmanSummoned;
     private int mUserActivitySummary;
-    // The current wakefulness of this group
+    /** The current wakefulness of this group */
     private int mWakefulness;
     private int mWakeLockSummary;
     private long mLastPowerOnTime;
     private long mLastUserActivityTime;
     private long mLastUserActivityTimeNoChangeLights;
+    /** Timestamp (milliseconds since boot) of the last time the power group was awoken.*/
+    private long mLastWakeTime;
+    /** Timestamp (milliseconds since boot) of the last time the power group was put to sleep. */
+    private long mLastSleepTime;
 
-    PowerGroup(int groupId, DisplayPowerRequest displayPowerRequest, int wakefulness, boolean ready,
-            boolean supportsSandman) {
-        this.mGroupId = groupId;
-        this.mDisplayPowerRequest = displayPowerRequest;
-        this.mWakefulness = wakefulness;
-        this.mReady = ready;
-        this.mSupportsSandman = supportsSandman;
+    PowerGroup(int groupId, PowerGroupListener wakefulnessListener,
+            DisplayPowerRequest displayPowerRequest, int wakefulness, boolean ready,
+            boolean supportsSandman, long eventTime) {
+        mGroupId = groupId;
+        mWakefulnessListener = wakefulnessListener;
+        mDisplayPowerRequest = displayPowerRequest;
+        mWakefulness = wakefulness;
+        mReady = ready;
+        mSupportsSandman = supportsSandman;
+        mLastWakeTime = eventTime;
+        mLastSleepTime = eventTime;
     }
 
-    PowerGroup() {
-        this.mGroupId = Display.DEFAULT_DISPLAY_GROUP;
-        this.mDisplayPowerRequest = new DisplayPowerRequest();
-        this.mWakefulness = WAKEFULNESS_AWAKE;
-        this.mReady = false;
-        this.mSupportsSandman = true;
-    }
+    PowerGroup(int wakefulness, PowerGroupListener wakefulnessListener, long eventTime) {
+        mGroupId = Display.DEFAULT_DISPLAY_GROUP;
+        mWakefulnessListener = wakefulnessListener;
+        mDisplayPowerRequest = new DisplayPowerRequest();
+        mWakefulness = wakefulness;
+        mReady = false;
+        mSupportsSandman = true;
+        mLastWakeTime = eventTime;
+        mLastSleepTime = eventTime;    }
 
     DisplayPowerRequest getDisplayPowerRequestLocked() {
         return mDisplayPowerRequest;
     }
 
+    long getLastWakeTimeLocked() {
+        return mLastWakeTime;
+    }
+
+    long getLastSleepTimeLocked() {
+        return mLastSleepTime;
+    }
+
     int getWakefulnessLocked() {
         return mWakefulness;
     }
@@ -85,9 +111,19 @@
      *
      * @return {@code true} if the wakefulness value was changed; {@code false} otherwise.
      */
-    boolean setWakefulnessLocked(int newWakefulness) {
+    boolean setWakefulnessLocked(int newWakefulness, long eventTime, int uid, int reason, int opUid,
+            String opPackageName, String details) {
         if (mWakefulness != newWakefulness) {
+            if (newWakefulness == WAKEFULNESS_AWAKE) {
+                setLastPowerOnTimeLocked(eventTime);
+                setIsPoweringOnLocked(true);
+                mLastWakeTime = eventTime;
+            } else if (isInteractive(mWakefulness) && !isInteractive(newWakefulness)) {
+                mLastSleepTime = eventTime;
+            }
             mWakefulness = newWakefulness;
+            mWakefulnessListener.onWakefulnessChangedLocked(mGroupId, mWakefulness, eventTime,
+                    reason, uid, opUid, opPackageName, details);
             return true;
         }
         return false;
@@ -105,8 +141,9 @@
      * Sets whether the displays of this group are all ready.
      *
      * <p>A display is ready if its reported
-     * {@link DisplayManagerInternal.DisplayPowerCallbacks#onStateChanged() actual state} matches
-     * its {@link DisplayManagerInternal#requestPowerState requested state}.
+     * {@link android.hardware.display.DisplayManagerInternal.DisplayPowerCallbacks#onStateChanged()
+     * actual state} matches its
+     * {@link android.hardware.display.DisplayManagerInternal#requestPowerState requested state}.
      *
      * @param isReady {@code true} if every display in the group is ready; otherwise {@code false}.
      * @return {@code true} if the ready state changed; otherwise {@code false}.
@@ -148,6 +185,62 @@
         mIsSandmanSummoned = isSandmanSummoned;
     }
 
+    boolean dreamLocked(long eventTime, int uid) {
+        if (eventTime < mLastWakeTime || mWakefulness != WAKEFULNESS_AWAKE) {
+            return false;
+        }
+
+        Trace.traceBegin(Trace.TRACE_TAG_POWER, "dreamPowerGroup" + getGroupId());
+        try {
+            Slog.i(TAG, "Napping power group (groupId=" + getGroupId() + ", uid=" + uid + ")...");
+            setSandmanSummonedLocked(true);
+            setWakefulnessLocked(WAKEFULNESS_DREAMING, eventTime, uid, /* reason= */0,
+                    /* opUid= */ 0, /* opPackageName= */ null, /* details= */ null);
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_POWER);
+        }
+        return true;
+    }
+
+    boolean dozeLocked(long eventTime, int uid, int reason) {
+        if (eventTime < getLastWakeTimeLocked() || !isInteractive(mWakefulness)) {
+            return false;
+        }
+
+        Trace.traceBegin(Trace.TRACE_TAG_POWER, "powerOffDisplay");
+        try {
+            reason = Math.min(PowerManager.GO_TO_SLEEP_REASON_MAX,
+                    Math.max(reason, PowerManager.GO_TO_SLEEP_REASON_MIN));
+            Slog.i(TAG, "Powering off display group due to "
+                    + PowerManager.sleepReasonToString(reason)  + " (groupId= " + getGroupId()
+                    + ", uid= " + uid + ")...");
+
+            setSandmanSummonedLocked(/* isSandmanSummoned= */ true);
+            setWakefulnessLocked(WAKEFULNESS_DOZING, eventTime, uid, reason, /* opUid= */ 0,
+                    /* opPackageName= */ null, /* details= */ null);
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_POWER);
+        }
+        return true;
+    }
+
+    boolean sleepLocked(long eventTime, int uid, int reason) {
+        if (eventTime < mLastWakeTime || getWakefulnessLocked() == WAKEFULNESS_ASLEEP) {
+            return false;
+        }
+
+        Trace.traceBegin(Trace.TRACE_TAG_POWER, "sleepPowerGroup");
+        try {
+            Slog.i(TAG, "Sleeping power group (groupId=" + getGroupId() + ", uid=" + uid + ")...");
+            setSandmanSummonedLocked(/* isSandmanSummoned= */ true);
+            setWakefulnessLocked(WAKEFULNESS_ASLEEP, eventTime, uid, reason, /* opUid= */0,
+                    /* opPackageName= */ null, /* details= */ null);
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_POWER);
+        }
+        return true;
+    }
+
     long getLastUserActivityTimeLocked() {
         return mLastUserActivityTime;
     }
@@ -187,4 +280,22 @@
     public boolean supportsSandmanLocked() {
         return mSupportsSandman;
     }
+
+    protected interface PowerGroupListener {
+        /**
+         * Informs the recipient about a wakefulness change of a {@link PowerGroup}.
+         *
+         * @param groupId The PowerGroup's id for which the wakefulness has changed.
+         * @param wakefulness The new wakefulness.
+         * @param eventTime The time of the event.
+         * @param reason The reason, any of {@link android.os.PowerManager.WakeReason} or
+         *               {@link android.os.PowerManager.GoToSleepReason}.
+         * @param uid The uid which caused the wakefulness change.
+         * @param opUid The uid used for AppOps.
+         * @param opPackageName The Package name used for AppOps.
+         * @param details Details about the event.
+         */
+        void onWakefulnessChangedLocked(int groupId, int wakefulness, long eventTime, int reason,
+                int uid, int opUid, String opPackageName, String details);
+    }
 }
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index abfa016..4185b2d9 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -29,6 +29,7 @@
 import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE;
 import static android.os.PowerManagerInternal.WAKEFULNESS_DOZING;
 import static android.os.PowerManagerInternal.WAKEFULNESS_DREAMING;
+import static android.os.PowerManagerInternal.isInteractive;
 import static android.os.PowerManagerInternal.wakefulnessToString;
 
 import static com.android.internal.util.LatencyTracker.ACTION_TURN_ON_SCREEN;
@@ -338,12 +339,12 @@
     private boolean mRequestWaitForNegativeProximity;
 
     // Timestamp of the last time the device was awoken or put to sleep.
-    private long mLastWakeTime;
-    private long mLastSleepTime;
+    private long mLastGlobalWakeTime;
+    private long mLastGlobalSleepTime;
 
     // Last reason the device went to sleep.
-    private @WakeReason int mLastWakeReason;
-    private int mLastSleepReason;
+    private @WakeReason int mLastGlobalWakeReason;
+    private int mLastGlobalSleepReason;
 
     // Timestamp of last time power boost interaction was sent.
     private long mLastInteractivePowerHintTime;
@@ -352,6 +353,8 @@
     private long mLastScreenBrightnessBoostTime;
     private boolean mScreenBrightnessBoostInProgress;
 
+    private final PowerGroupWakefulnessChangeListener mPowerGroupWakefulnessChangeListener;
+
     // The suspend blocker used to keep the CPU alive while the device is booting.
     private final SuspendBlocker mBootingSuspendBlocker;
 
@@ -397,6 +400,10 @@
     // The current battery level percentage.
     private int mBatteryLevel;
 
+    // True if updatePowerStateLocked() is already in progress.
+    // TODO(b/215518989): Remove this once transactions are in place
+    private boolean mUpdatePowerStateInProgress;
+
     /**
      * The lock that should be held when interacting with {@link #mEnhancedDischargeTimeElapsed},
      * {@link #mLastEnhancedDischargeTimeUpdatedElapsed}, and
@@ -640,6 +647,23 @@
     // but the DreamService has not yet been told to start (it's an async process).
     private boolean mDozeStartInProgress;
 
+    private final class PowerGroupWakefulnessChangeListener implements
+            PowerGroup.PowerGroupListener {
+        @GuardedBy("mLock")
+        @Override
+        public void onWakefulnessChangedLocked(int groupId, int wakefulness, long eventTime,
+                int reason, int uid, int opUid, String opPackageName, String details) {
+            if (wakefulness == WAKEFULNESS_AWAKE) {
+                // Kick user activity to prevent newly awake group from timing out instantly.
+                userActivityNoUpdateLocked(mPowerGroups.get(groupId), eventTime,
+                        PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, uid);
+            }
+            mDirty |= DIRTY_DISPLAY_GROUP_WAKEFULNESS;
+            updateGlobalWakefulnessLocked(eventTime, reason, uid, opUid, opPackageName, details);
+            updatePowerStateLocked();
+        }
+    }
+
     private final class DisplayGroupPowerChangeListener implements
             DisplayManagerInternal.DisplayGroupListener {
 
@@ -658,10 +682,12 @@
                 final boolean supportsSandman = groupId == Display.DEFAULT_DISPLAY_GROUP;
                 final PowerGroup powerGroup = new PowerGroup(
                         groupId,
+                        mPowerGroupWakefulnessChangeListener,
                         new DisplayPowerRequest(),
-                        getGlobalWakefulnessLocked(),
+                        WAKEFULNESS_AWAKE,
                         /* ready= */ false,
-                        supportsSandman);
+                        supportsSandman,
+                        mClock.uptimeMillis());
                 mPowerGroups.append(groupId, powerGroup);
                 onPowerGroupEventLocked(DISPLAY_GROUP_ADDED, powerGroup);
             }
@@ -992,6 +1018,8 @@
         mInattentiveSleepWarningOverlayController =
                 mInjector.createInattentiveSleepWarningController();
 
+        mPowerGroupWakefulnessChangeListener = new PowerGroupWakefulnessChangeListener();
+
         // Save brightness values:
         // Get float values from config.
         // Store float if valid
@@ -1144,10 +1172,10 @@
 
                 updatePowerStateLocked();
                 if (sQuiescent) {
-                    sleepDisplayGroupNoUpdateLocked(mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP),
+                    sleepPowerGroupLocked(mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP),
                             mClock.uptimeMillis(),
                             PowerManager.GO_TO_SLEEP_REASON_QUIESCENT,
-                            PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE, Process.SYSTEM_UID);
+                            Process.SYSTEM_UID);
                 }
 
                 mContext.getSystemService(DeviceStateManager.class).registerCallback(
@@ -1164,7 +1192,9 @@
             mPolicy = getLocalService(WindowManagerPolicy.class);
             mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);
             mAttentionDetector.systemReady(mContext);
-            mPowerGroups.append(Display.DEFAULT_DISPLAY_GROUP, new PowerGroup());
+            mPowerGroups.append(Display.DEFAULT_DISPLAY_GROUP,
+                    new PowerGroup(WAKEFULNESS_AWAKE, mPowerGroupWakefulnessChangeListener,
+                            mClock.uptimeMillis()));
             DisplayGroupPowerChangeListener displayGroupPowerChangeListener =
                     new DisplayGroupPowerChangeListener();
             mDisplayManagerInternal.registerDisplayGroupListener(displayGroupPowerChangeListener);
@@ -1503,7 +1533,7 @@
                 opUid = wakeLock.mOwnerUid;
             }
             for (int idx = 0; idx < mPowerGroups.size(); idx++) {
-                wakeDisplayGroupNoUpdateLocked(mPowerGroups.valueAt(idx), mClock.uptimeMillis(),
+                wakePowerGroupLocked(mPowerGroups.valueAt(idx), mClock.uptimeMillis(),
                         PowerManager.WAKE_REASON_APPLICATION, wakeLock.mTag, opUid, opPackageName,
                         opUid);
             }
@@ -1777,13 +1807,15 @@
     @GuardedBy("mLock")
     private boolean userActivityNoUpdateLocked(final PowerGroup powerGroup, long eventTime,
             int event, int flags, int uid) {
+        final int groupId = powerGroup.getGroupId();
         if (DEBUG_SPEW) {
-            Slog.d(TAG, "userActivityNoUpdateLocked: groupId=" + powerGroup.getGroupId()
+            Slog.d(TAG, "userActivityNoUpdateLocked: groupId=" + groupId
                     + ", eventTime=" + eventTime + ", event=" + event
                     + ", flags=0x" + Integer.toHexString(flags) + ", uid=" + uid);
         }
 
-        if (eventTime < mLastSleepTime || eventTime < mLastWakeTime || !mSystemReady) {
+        if (eventTime < powerGroup.getLastSleepTimeLocked()
+                || eventTime < powerGroup.getLastWakeTimeLocked() || !mSystemReady) {
             return false;
         }
 
@@ -1801,7 +1833,6 @@
                 mUserInactiveOverrideFromWindowManager = false;
                 mOverriddenTimeout = -1;
             }
-
             final int wakefulness = powerGroup.getWakefulnessLocked();
             if (wakefulness == WAKEFULNESS_ASLEEP
                     || wakefulness == WAKEFULNESS_DOZING
@@ -1846,42 +1877,33 @@
         }
     }
 
-    private void wakeDisplayGroup(int groupId, long eventTime, @WakeReason int reason,
-            String details, int uid, String opPackageName, int opUid) {
-        synchronized (mLock) {
-            if (wakeDisplayGroupNoUpdateLocked(mPowerGroups.get(groupId), eventTime, reason,
-                    details, uid, opPackageName, opUid)) {
-                updatePowerStateLocked();
-            }
-        }
-    }
-
     @GuardedBy("mLock")
-    private boolean wakeDisplayGroupNoUpdateLocked(final PowerGroup powerGroup, long eventTime,
+    private void wakePowerGroupLocked(final PowerGroup powerGroup, long eventTime,
             @WakeReason int reason, String details, int uid, String opPackageName, int opUid) {
         final int groupId = powerGroup.getGroupId();
         if (DEBUG_SPEW) {
-            Slog.d(TAG, "wakeDisplayGroupNoUpdateLocked: eventTime=" + eventTime
+            Slog.d(TAG, "wakePowerGroupLocked: eventTime=" + eventTime
                     + ", groupId=" + groupId + ", uid=" + uid);
         }
 
-        if (eventTime < mLastSleepTime || mForceSuspendActive || !mSystemReady) {
-            return false;
+        if (eventTime < powerGroup.getLastSleepTimeLocked() || mForceSuspendActive
+                || !mSystemReady) {
+            return;
         }
 
-        final int currentState = powerGroup.getWakefulnessLocked();
-        if (currentState == WAKEFULNESS_AWAKE) {
+        final int currentWakefulness = powerGroup.getWakefulnessLocked();
+        if (currentWakefulness == WAKEFULNESS_AWAKE) {
             if (!mBootCompleted && sQuiescent) {
                 mDirty |= DIRTY_QUIESCENT;
-                return true;
+                updatePowerStateLocked();
             }
-            return false;
+            return;
         }
 
         Trace.traceBegin(Trace.TRACE_TAG_POWER, "powerOnDisplay");
         try {
-            Slog.i(TAG, "Powering on display group from"
-                    + PowerManagerInternal.wakefulnessToString(currentState)
+            Slog.i(TAG, "Waking up power group from "
+                    + PowerManagerInternal.wakefulnessToString(currentWakefulness)
                     + " (groupId=" + groupId
                     + ", uid=" + uid
                     + ", reason=" + PowerManager.wakeReasonToString(reason)
@@ -1892,183 +1914,96 @@
             LatencyTracker.getInstance(mContext)
                     .onActionStart(ACTION_TURN_ON_SCREEN, String.valueOf(groupId));
 
-            setWakefulnessLocked(powerGroup, WAKEFULNESS_AWAKE, eventTime, uid, reason, opUid,
+            powerGroup.setWakefulnessLocked(WAKEFULNESS_AWAKE, eventTime, uid, reason, opUid,
                     opPackageName, details);
-            powerGroup.setLastPowerOnTimeLocked(eventTime);
-            powerGroup.setIsPoweringOnLocked(true);
         } finally {
             Trace.traceEnd(Trace.TRACE_TAG_POWER);
         }
-
-        return true;
-    }
-
-    private void sleepDisplayGroup(int groupId, long eventTime, int reason, int flags,
-            int uid) {
-        synchronized (mLock) {
-            if (sleepDisplayGroupNoUpdateLocked(mPowerGroups.get(groupId), eventTime, reason, flags,
-                    uid)) {
-                updatePowerStateLocked();
-            }
-        }
     }
 
     @GuardedBy("mLock")
-    private boolean sleepDisplayGroupNoUpdateLocked(final PowerGroup powerGroup, long eventTime,
-            int reason, int flags, int uid) {
+    private boolean dreamPowerGroupLocked(PowerGroup powerGroup, long eventTime, int uid) {
+        if (DEBUG_SPEW) {
+            Slog.d(TAG, "dreamPowerGroup: groupId=" + powerGroup.getGroupId() + ", eventTime="
+                    + eventTime + ", uid=" + uid);
+        }
+        if (!mBootCompleted || !mSystemReady) {
+            return false;
+        }
+        return powerGroup.dreamLocked(eventTime, uid);
+    }
+
+    @GuardedBy("mLock")
+    private boolean dozePowerGroupLocked(final PowerGroup powerGroup, long eventTime,
+            int reason, int uid) {
         if (DEBUG_SPEW) {
             Slog.d(TAG, "sleepDisplayGroupNoUpdateLocked: eventTime=" + eventTime
                     + ", groupId=" + powerGroup.getGroupId() + ", reason=" + reason
-                    + ", flags=" + flags + ", uid=" + uid);
+                    + ", uid=" + uid);
         }
 
-        if (eventTime < mLastWakeTime
-                || !PowerManagerInternal.isInteractive(getWakefulnessLocked())
-                || !mSystemReady
-                || !mBootCompleted) {
+        if (!mSystemReady || !mBootCompleted) {
             return false;
         }
 
-        final int wakefulness = powerGroup.getWakefulnessLocked();
-        if (!PowerManagerInternal.isInteractive(wakefulness)) {
-            return false;
-        }
-
-        Trace.traceBegin(Trace.TRACE_TAG_POWER, "powerOffDisplay");
-        try {
-            reason = Math.min(PowerManager.GO_TO_SLEEP_REASON_MAX,
-                    Math.max(reason, PowerManager.GO_TO_SLEEP_REASON_MIN));
-            Slog.i(TAG, "Powering off display group due to "
-                    + PowerManager.sleepReasonToString(reason)
-                    + " (groupId= " + powerGroup.getGroupId() + ", uid= " + uid + ")...");
-
-            powerGroup.setSandmanSummonedLocked(/* isSandmanSummoned= */ true);
-            setWakefulnessLocked(powerGroup, WAKEFULNESS_DOZING, eventTime, uid, reason,
-                    /* opUid= */ 0, /* opPackageName= */ null, /* details= */ null);
-            if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) {
-                reallySleepDisplayGroupNoUpdateLocked(powerGroup, eventTime, uid);
-            }
-        } finally {
-            Trace.traceEnd(Trace.TRACE_TAG_POWER);
-        }
-        return true;
-    }
-
-    private void dreamDisplayGroup(int groupId, long eventTime, int uid) {
-        synchronized (mLock) {
-            if (dreamDisplayGroupNoUpdateLocked(mPowerGroups.get(groupId), eventTime, uid)) {
-                updatePowerStateLocked();
-            }
-        }
+        return powerGroup.dozeLocked(eventTime, uid, reason);
     }
 
     @GuardedBy("mLock")
-    private boolean dreamDisplayGroupNoUpdateLocked(final PowerGroup powerGroup, long eventTime,
+    private boolean sleepPowerGroupLocked(final PowerGroup powerGroup, long eventTime, int reason,
             int uid) {
         if (DEBUG_SPEW) {
-            Slog.d(TAG, "dreamDisplayGroupNoUpdateLocked: eventTime=" + eventTime
-                    + ", uid=" + uid);
+            Slog.d(TAG, "sleepPowerGroup: eventTime=" + eventTime + ", uid=" + uid);
         }
-
-        if (eventTime < mLastWakeTime || getWakefulnessLocked() != WAKEFULNESS_AWAKE
-                || !mBootCompleted || !mSystemReady) {
+        if (!mBootCompleted || !mSystemReady) {
             return false;
         }
 
-        Trace.traceBegin(Trace.TRACE_TAG_POWER, "napDisplayGroup");
-        try {
-            Slog.i(TAG, "Napping display group (groupId=" + powerGroup.getGroupId() + ", uid=" + uid
-                    + ")...");
-
-            powerGroup.setSandmanSummonedLocked(/* isSandmanSummoned= */ true);
-            setWakefulnessLocked(powerGroup, WAKEFULNESS_DREAMING, eventTime, uid,
-                    /* reason= */0, /* opUid= */ 0, /* opPackageName= */ null, /* details= */ null);
-
-        } finally {
-            Trace.traceEnd(Trace.TRACE_TAG_POWER);
-        }
-        return true;
-    }
-
-    @GuardedBy("mLock")
-    private boolean reallySleepDisplayGroupNoUpdateLocked(final PowerGroup powerGroup,
-            long eventTime, int uid) {
-        if (DEBUG_SPEW) {
-            Slog.d(TAG, "reallySleepDisplayGroupNoUpdateLocked: eventTime=" + eventTime
-                    + ", uid=" + uid);
-        }
-
-        if (eventTime < mLastWakeTime || getWakefulnessLocked() == WAKEFULNESS_ASLEEP
-                || !mBootCompleted || !mSystemReady
-                || powerGroup.getWakefulnessLocked()
-                == WAKEFULNESS_ASLEEP) {
-            return false;
-        }
-
-        Trace.traceBegin(Trace.TRACE_TAG_POWER, "reallySleepDisplayGroup");
-        try {
-            Slog.i(TAG,
-                    "Sleeping display group (groupId=" + powerGroup.getGroupId() + ", uid=" + uid
-                            + ")...");
-
-            setWakefulnessLocked(powerGroup, WAKEFULNESS_ASLEEP, eventTime, uid,
-                    PowerManager.GO_TO_SLEEP_REASON_TIMEOUT,  /* opUid= */ 0,
-                    /* opPackageName= */ null, /* details= */ null);
-        } finally {
-            Trace.traceEnd(Trace.TRACE_TAG_POWER);
-        }
-        return true;
+        return powerGroup.sleepLocked(eventTime, uid, reason);
     }
 
     @VisibleForTesting
     @GuardedBy("mLock")
     void setWakefulnessLocked(int groupId, int wakefulness, long eventTime, int uid, int reason,
             int opUid, String opPackageName, String details) {
-        setWakefulnessLocked(mPowerGroups.get(groupId), wakefulness, eventTime, uid, reason, opUid,
+        mPowerGroups.get(groupId).setWakefulnessLocked(wakefulness, eventTime, uid, reason, opUid,
                 opPackageName, details);
     }
 
-    @GuardedBy("mLock")
-    private void setWakefulnessLocked(final PowerGroup powerGroup, int wakefulness, long eventTime,
-            int uid, int reason, int opUid, String opPackageName, String details) {
-        if (powerGroup.setWakefulnessLocked(wakefulness)) {
-            mDirty |= DIRTY_DISPLAY_GROUP_WAKEFULNESS;
-            setGlobalWakefulnessLocked(getGlobalWakefulnessLocked(),
-                    eventTime, reason, uid, opUid, opPackageName, details);
-            if (wakefulness == WAKEFULNESS_AWAKE) {
-                // Kick user activity to prevent newly awake group from timing out instantly.
-                userActivityNoUpdateLocked(powerGroup, eventTime,
-                        PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, uid);
-            }
-        }
-    }
-
     @SuppressWarnings("deprecation")
     @GuardedBy("mLock")
-    private void setGlobalWakefulnessLocked(int wakefulness, long eventTime, int reason, int uid,
+    private void updateGlobalWakefulnessLocked(long eventTime, int reason, int uid,
             int opUid, String opPackageName, String details) {
-        if (getWakefulnessLocked() == wakefulness) {
+        int newWakefulness = recalculateGlobalWakefulnessLocked();
+        int currentWakefulness = getGlobalWakefulnessLocked();
+        if (currentWakefulness == newWakefulness) {
             return;
         }
 
         // Phase 1: Handle pre-wakefulness change bookkeeping.
         final String traceMethodName;
-        switch (wakefulness) {
+        switch (newWakefulness) {
             case WAKEFULNESS_ASLEEP:
                 traceMethodName = "reallyGoToSleep";
                 Slog.i(TAG, "Sleeping (uid " + uid + ")...");
+                // TODO(b/215518989): Remove this once transactions are in place
+                if (currentWakefulness != WAKEFULNESS_DOZING) {
+                    // in case we are going to sleep without dozing before
+                    mLastGlobalSleepTime = eventTime;
+                    mLastGlobalSleepReason = reason;
+                }
                 break;
 
             case WAKEFULNESS_AWAKE:
                 traceMethodName = "wakeUp";
                 Slog.i(TAG, "Waking up from "
-                        + PowerManagerInternal.wakefulnessToString(getWakefulnessLocked())
+                        + PowerManagerInternal.wakefulnessToString(currentWakefulness)
                         + " (uid=" + uid
                         + ", reason=" + PowerManager.wakeReasonToString(reason)
                         + ", details=" + details
                         + ")...");
-                mLastWakeTime = eventTime;
-                mLastWakeReason = reason;
+                mLastGlobalWakeTime = eventTime;
+                mLastGlobalWakeReason = reason;
                 break;
 
             case WAKEFULNESS_DREAMING:
@@ -2081,13 +2016,13 @@
                 Slog.i(TAG, "Going to sleep due to " + PowerManager.sleepReasonToString(reason)
                         + " (uid " + uid + ")...");
 
-                mLastSleepTime = eventTime;
-                mLastSleepReason = reason;
+                mLastGlobalSleepTime = eventTime;
+                mLastGlobalSleepReason = reason;
                 mDozeStartInProgress = true;
                 break;
 
             default:
-                throw new IllegalArgumentException("Unexpected wakefulness: " + wakefulness);
+                throw new IllegalArgumentException("Unexpected wakefulness: " + newWakefulness);
         }
 
         Trace.traceBegin(Trace.TRACE_TAG_POWER, traceMethodName);
@@ -2095,20 +2030,20 @@
             // Phase 2: Handle wakefulness change and bookkeeping.
             // Under lock, invalidate before set ensures caches won't return stale values.
             mInjector.invalidateIsInteractiveCaches();
-            mWakefulnessRaw = wakefulness;
+            mWakefulnessRaw = newWakefulness;
             mWakefulnessChanging = true;
             mDirty |= DIRTY_WAKEFULNESS;
 
             // This is only valid while we are in wakefulness dozing. Set to false otherwise.
-            mDozeStartInProgress &= (getWakefulnessLocked() == WAKEFULNESS_DOZING);
+            mDozeStartInProgress &= (newWakefulness == WAKEFULNESS_DOZING);
 
             if (mNotifier != null) {
-                mNotifier.onWakefulnessChangeStarted(wakefulness, reason, eventTime);
+                mNotifier.onWakefulnessChangeStarted(newWakefulness, reason, eventTime);
             }
-            mAttentionDetector.onWakefulnessChangeStarted(wakefulness);
+            mAttentionDetector.onWakefulnessChangeStarted(newWakefulness);
 
             // Phase 3: Handle post-wakefulness change bookkeeping.
-            switch (wakefulness) {
+            switch (newWakefulness) {
                 case WAKEFULNESS_AWAKE:
                     mNotifier.onWakeUp(reason, details, uid, opPackageName, opUid);
                     if (sQuiescent) {
@@ -2116,7 +2051,13 @@
                     }
                     break;
 
+                case WAKEFULNESS_ASLEEP:
+                    // fallthrough
                 case WAKEFULNESS_DOZING:
+                    if (!isInteractive(currentWakefulness)) {
+                        // TODO(b/215518989): remove this once transactions are in place
+                        break;
+                    }
                     // Report the number of wake locks that will be cleared by going to sleep.
                     int numWakeLocksCleared = 0;
                     final int numWakeLocks = mWakeLocks.size();
@@ -2140,7 +2081,7 @@
 
     @VisibleForTesting
     @GuardedBy("mLock")
-    int getWakefulnessLocked() {
+    int getGlobalWakefulnessLocked() {
         return mWakefulnessRaw;
     }
 
@@ -2163,10 +2104,9 @@
      * </ol>
      */
     @GuardedBy("mLock")
-    int getGlobalWakefulnessLocked() {
-        final int size = mPowerGroups.size();
+    int recalculateGlobalWakefulnessLocked() {
         int deviceWakefulness = WAKEFULNESS_ASLEEP;
-        for (int i = 0; i < size; i++) {
+        for (int i = 0; i < mPowerGroups.size(); i++) {
             final int wakefulness = mPowerGroups.valueAt(i).getWakefulnessLocked();
             if (wakefulness == WAKEFULNESS_AWAKE) {
                 return WAKEFULNESS_AWAKE;
@@ -2187,10 +2127,10 @@
     void onPowerGroupEventLocked(int event, PowerGroup powerGroup) {
         final int groupId = powerGroup.getGroupId();
         if (event == DisplayGroupPowerChangeListener.DISPLAY_GROUP_REMOVED) {
-            mPowerGroups.remove(groupId);
+            mPowerGroups.delete(groupId);
         }
-        final int oldWakefulness = getWakefulnessLocked();
-        final int newWakefulness = getGlobalWakefulnessLocked();
+        final int oldWakefulness = getGlobalWakefulnessLocked();
+        final int newWakefulness = recalculateGlobalWakefulnessLocked();
 
         if (event == DisplayGroupPowerChangeListener.DISPLAY_GROUP_ADDED
                 && newWakefulness == WAKEFULNESS_AWAKE) {
@@ -2215,13 +2155,9 @@
                 default:
                     reason = 0;
             }
-
-            setGlobalWakefulnessLocked(
-                    getGlobalWakefulnessLocked(),
-                    mClock.uptimeMillis(), reason, Process.SYSTEM_UID, Process.SYSTEM_UID,
-                    mContext.getOpPackageName(), "groupId: " + groupId);
+            updateGlobalWakefulnessLocked(mClock.uptimeMillis(), reason, Process.SYSTEM_UID,
+                    Process.SYSTEM_UID, mContext.getOpPackageName(), "groupId: " + groupId);
         }
-
         mDirty |= DIRTY_DISPLAY_GROUP_WAKEFULNESS;
         updatePowerStateLocked();
     }
@@ -2243,15 +2179,15 @@
     @GuardedBy("mLock")
     private void finishWakefulnessChangeIfNeededLocked() {
         if (mWakefulnessChanging && areAllDisplaysReadyLocked()) {
-            if (getWakefulnessLocked() == WAKEFULNESS_DOZING
+            if (getGlobalWakefulnessLocked() == WAKEFULNESS_DOZING
                     && (mWakeLockSummary & WAKE_LOCK_DOZE) == 0) {
                 return; // wait until dream has enabled dozing
             } else {
                 // Doze wakelock acquired (doze started) or device is no longer dozing.
                 mDozeStartInProgress = false;
             }
-            if (getWakefulnessLocked() == WAKEFULNESS_DOZING
-                    || getWakefulnessLocked() == WAKEFULNESS_ASLEEP) {
+            if (getGlobalWakefulnessLocked() == WAKEFULNESS_DOZING
+                    || getGlobalWakefulnessLocked() == WAKEFULNESS_ASLEEP) {
                 logSleepTimeoutRecapturedLocked();
             }
             mWakefulnessChanging = false;
@@ -2282,7 +2218,7 @@
      */
     @GuardedBy("mLock")
     private void updatePowerStateLocked() {
-        if (!mSystemReady || mDirty == 0) {
+        if (!mSystemReady || mDirty == 0 || mUpdatePowerStateInProgress) {
             return;
         }
         if (!Thread.holdsLock(mLock)) {
@@ -2290,6 +2226,7 @@
         }
 
         Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");
+        mUpdatePowerStateInProgress = true;
         try {
             // Phase 0: Basic state updates.
             updateIsPoweredLocked(mDirty);
@@ -2332,6 +2269,7 @@
             updateSuspendBlockerLocked();
         } finally {
             Trace.traceEnd(Trace.TRACE_TAG_POWER);
+            mUpdatePowerStateInProgress = false;
         }
     }
 
@@ -2397,7 +2335,7 @@
                 final long now = mClock.uptimeMillis();
                 if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType,
                         dockedOnWirelessCharger)) {
-                    wakeDisplayGroupNoUpdateLocked(mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP),
+                    wakePowerGroupLocked(mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP),
                             now, PowerManager.WAKE_REASON_PLUGGED_IN,
                             "android.server.power:PLUGGED:" + mIsPowered, Process.SYSTEM_UID,
                             mContext.getOpPackageName(), Process.SYSTEM_UID);
@@ -2446,7 +2384,7 @@
         }
 
         // If already dreaming and becoming powered, then don't wake.
-        if (mIsPowered && getWakefulnessLocked() == WAKEFULNESS_DREAMING) {
+        if (mIsPowered && getGlobalWakefulnessLocked() == WAKEFULNESS_DREAMING) {
             return false;
         }
 
@@ -2456,7 +2394,7 @@
         }
 
         // On Always On Display, SystemUI shows the charging indicator
-        if (mAlwaysOnEnabled && getWakefulnessLocked() == WAKEFULNESS_DOZING) {
+        if (mAlwaysOnEnabled && getGlobalWakefulnessLocked() == WAKEFULNESS_DOZING) {
             return false;
         }
 
@@ -2540,24 +2478,23 @@
 
             for (int idx = 0; idx < mPowerGroups.size(); idx++) {
                 final PowerGroup powerGroup = mPowerGroups.valueAt(idx);
-                final int wakeLockSummary = adjustWakeLockSummary(
-                        powerGroup.getWakefulnessLocked(),
+                final int wakeLockSummary = adjustWakeLockSummary(powerGroup.getWakefulnessLocked(),
                         invalidGroupWakeLockSummary | powerGroup.getWakeLockSummaryLocked());
                 powerGroup.setWakeLockSummaryLocked(wakeLockSummary);
             }
 
-            mWakeLockSummary = adjustWakeLockSummary(getWakefulnessLocked(),
+            mWakeLockSummary = adjustWakeLockSummary(getGlobalWakefulnessLocked(),
                     mWakeLockSummary);
 
             for (int i = 0; i < numProfiles; i++) {
                 final ProfilePowerState profile = mProfilePowerState.valueAt(i);
-                profile.mWakeLockSummary = adjustWakeLockSummary(getWakefulnessLocked(),
+                profile.mWakeLockSummary = adjustWakeLockSummary(getGlobalWakefulnessLocked(),
                         profile.mWakeLockSummary);
             }
 
             if (DEBUG_SPEW) {
                 Slog.d(TAG, "updateWakeLockSummaryLocked: mWakefulness="
-                        + PowerManagerInternal.wakefulnessToString(getWakefulnessLocked())
+                        + PowerManagerInternal.wakefulnessToString(getGlobalWakefulnessLocked())
                         + ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));
             }
         }
@@ -2706,11 +2643,12 @@
             int groupUserActivitySummary = 0;
             long groupNextTimeout = 0;
             final PowerGroup powerGroup = mPowerGroups.valueAt(idx);
-            if (powerGroup.getWakefulnessLocked() != WAKEFULNESS_ASLEEP) {
+            final int wakefulness = powerGroup.getWakefulnessLocked();
+            if (wakefulness != WAKEFULNESS_ASLEEP) {
                 final long lastUserActivityTime = powerGroup.getLastUserActivityTimeLocked();
                 final long lastUserActivityTimeNoChangeLights =
                         powerGroup.getLastUserActivityTimeNoChangeLightsLocked();
-                if (lastUserActivityTime >= mLastWakeTime) {
+                if (lastUserActivityTime >= powerGroup.getLastWakeTimeLocked()) {
                     groupNextTimeout = lastUserActivityTime + screenOffTimeout - screenDimDuration;
                     if (now < groupNextTimeout) {
                         groupUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
@@ -2721,8 +2659,8 @@
                         }
                     }
                 }
-                if (groupUserActivitySummary == 0
-                        && lastUserActivityTimeNoChangeLights >= mLastWakeTime) {
+                if (groupUserActivitySummary == 0 && lastUserActivityTimeNoChangeLights
+                        >= powerGroup.getLastWakeTimeLocked()) {
                     groupNextTimeout = lastUserActivityTimeNoChangeLights + screenOffTimeout;
                     if (now < groupNextTimeout) {
                         final DisplayPowerRequest displayPowerRequest =
@@ -2740,7 +2678,7 @@
                     if (sleepTimeout >= 0) {
                         final long anyUserActivity = Math.max(lastUserActivityTime,
                                 lastUserActivityTimeNoChangeLights);
-                        if (anyUserActivity >= mLastWakeTime) {
+                        if (anyUserActivity >= powerGroup.getLastWakeTimeLocked()) {
                             groupNextTimeout = anyUserActivity + sleepTimeout;
                             if (now < groupNextTimeout) {
                                 groupUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
@@ -2786,7 +2724,7 @@
 
             if (DEBUG_SPEW) {
                 Slog.d(TAG, "updateUserActivitySummaryLocked: groupId=" + powerGroup.getGroupId()
-                        + ", mWakefulness=" + wakefulnessToString(powerGroup.getWakefulnessLocked())
+                        + ", mWakefulness=" + wakefulnessToString(wakefulness)
                         + ", mUserActivitySummary=0x" + Integer.toHexString(
                         groupUserActivitySummary)
                         + ", nextTimeout=" + TimeUtils.formatUptime(groupNextTimeout));
@@ -2884,7 +2822,7 @@
             return false;
         }
 
-        if (getWakefulnessLocked() != WAKEFULNESS_AWAKE) {
+        if (getGlobalWakefulnessLocked() != WAKEFULNESS_AWAKE) {
             mInattentiveSleepWarningOverlayController.dismiss(false);
             return true;
         } else if (attentiveTimeout < 0 || isBeingKeptFromInattentiveSleepLocked()
@@ -3024,14 +2962,13 @@
                 if (DEBUG) {
                     Slog.i(TAG, "Going to sleep now due to long user inactivity");
                 }
-                changed = sleepDisplayGroupNoUpdateLocked(powerGroup, time,
-                        PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE,
-                        PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE, Process.SYSTEM_UID);
+                changed = sleepPowerGroupLocked(powerGroup, time,
+                        PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE, Process.SYSTEM_UID);
             } else if (shouldNapAtBedTimeLocked()) {
-                changed = dreamDisplayGroupNoUpdateLocked(powerGroup, time, Process.SYSTEM_UID);
+                changed = dreamPowerGroupLocked(powerGroup, time, Process.SYSTEM_UID);
             } else {
-                changed = sleepDisplayGroupNoUpdateLocked(powerGroup, time,
-                        PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);
+                changed = dozePowerGroupLocked(powerGroup, time,
+                        PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, Process.SYSTEM_UID);
             }
         }
         return changed;
@@ -3228,25 +3165,27 @@
 
                 // Dream has ended or will be stopped.  Update the power state.
                 if (isItBedTimeYetLocked(powerGroup)) {
-                    final int flags = isAttentiveTimeoutExpired(powerGroup, now)
-                            ? PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE : 0;
-                    sleepDisplayGroupNoUpdateLocked(powerGroup, now,
-                            PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, flags, Process.SYSTEM_UID);
+                    if (isAttentiveTimeoutExpired(powerGroup, now)) {
+                        sleepPowerGroupLocked(powerGroup, now,
+                                PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, Process.SYSTEM_UID);
+                    } else {
+                        dozePowerGroupLocked(powerGroup, now,
+                                PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, Process.SYSTEM_UID);
+                    }
                 } else {
-                    wakeDisplayGroupNoUpdateLocked(powerGroup, now,
+                    wakePowerGroupLocked(powerGroup, now,
                             PowerManager.WAKE_REASON_UNKNOWN,
                             "android.server.power:DREAM_FINISHED", Process.SYSTEM_UID,
                             mContext.getOpPackageName(), Process.SYSTEM_UID);
                 }
-                updatePowerStateLocked();
             } else if (wakefulness == WAKEFULNESS_DOZING) {
                 if (isDreaming) {
                     return; // continue dozing
                 }
 
                 // Doze has ended or will be stopped.  Update the power state.
-                reallySleepDisplayGroupNoUpdateLocked(powerGroup, now, Process.SYSTEM_UID);
-                updatePowerStateLocked();
+                sleepPowerGroupLocked(powerGroup, now,  PowerManager.GO_TO_SLEEP_REASON_TIMEOUT,
+                        Process.SYSTEM_UID);
             }
         }
 
@@ -3263,7 +3202,7 @@
     private boolean canDreamLocked(final PowerGroup powerGroup) {
         final DisplayPowerRequest displayPowerRequest = powerGroup.getDisplayPowerRequestLocked();
         if (!mBootCompleted
-                || getWakefulnessLocked() != WAKEFULNESS_DREAMING
+                || getGlobalWakefulnessLocked() != WAKEFULNESS_DREAMING
                 || !mDreamsSupportedConfig
                 || !mDreamsEnabledSetting
                 || !displayPowerRequest.isBrightOrDim()
@@ -3294,7 +3233,7 @@
     @GuardedBy("mLock")
     private boolean canDozeLocked() {
         // TODO (b/175764708): Support per-display doze.
-        return getWakefulnessLocked() == WAKEFULNESS_DOZING;
+        return getGlobalWakefulnessLocked() == WAKEFULNESS_DOZING;
     }
 
     /**
@@ -3375,15 +3314,15 @@
 
                 final boolean ready = mDisplayManagerInternal.requestPowerState(groupId,
                         displayPowerRequest, mRequestWaitForNegativeProximity);
-                mNotifier.onScreenPolicyUpdate(groupId, displayPowerRequest.policy);
+                mNotifier.onScreenPolicyUpdate(powerGroup.getGroupId(), displayPowerRequest.policy);
+                int wakefulness = powerGroup.getWakefulnessLocked();
 
                 if (DEBUG_SPEW) {
                     Slog.d(TAG, "updateDisplayPowerStateLocked: displayReady=" + ready
                             + ", groupId=" + groupId
                             + ", policy=" + policyToString(displayPowerRequest.policy)
                             + ", mWakefulness="
-                            + PowerManagerInternal.wakefulnessToString(
-                            powerGroup.getWakefulnessLocked())
+                            + PowerManagerInternal.wakefulnessToString(wakefulness)
                             + ", mWakeLockSummary=0x" + Integer.toHexString(
                             powerGroup.getWakeLockSummaryLocked())
                             + ", mUserActivitySummary=0x" + Integer.toHexString(
@@ -3401,7 +3340,7 @@
                 final boolean displayReadyStateChanged = powerGroup.setReadyLocked(ready);
                 final boolean poweringOn = powerGroup.isPoweringOnLocked();
                 if (ready && displayReadyStateChanged && poweringOn
-                        && powerGroup.getWakefulnessLocked() == WAKEFULNESS_AWAKE) {
+                        && wakefulness == WAKEFULNESS_AWAKE) {
                     powerGroup.setIsPoweringOnLocked(false);
                     LatencyTracker.getInstance(mContext).onActionEnd(ACTION_TURN_ON_SCREEN);
                     Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, TRACE_SCREEN_ON, groupId);
@@ -3424,7 +3363,7 @@
             if (mScreenBrightnessBoostInProgress) {
                 final long now = mClock.uptimeMillis();
                 mHandler.removeMessages(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);
-                if (mLastScreenBrightnessBoostTime > mLastSleepTime) {
+                if (mLastScreenBrightnessBoostTime > mLastGlobalSleepTime) {
                     final long boostTimeout = mLastScreenBrightnessBoostTime +
                             SCREEN_BRIGHTNESS_BOOST_TIMEOUT;
                     if (boostTimeout > now) {
@@ -3656,7 +3595,7 @@
         // Here we wait for mWakefulnessChanging to become false since the wakefulness
         // transition to DOZING isn't considered "changed" until the doze wake lock is
         // acquired.
-        if (getWakefulnessLocked() == WAKEFULNESS_DOZING && mDozeStartInProgress) {
+        if (getGlobalWakefulnessLocked() == WAKEFULNESS_DOZING && mDozeStartInProgress) {
             return true;
         }
 
@@ -3721,7 +3660,7 @@
 
     private boolean isInteractiveInternal() {
         synchronized (mLock) {
-            return PowerManagerInternal.isInteractive(getWakefulnessLocked());
+            return PowerManagerInternal.isInteractive(getGlobalWakefulnessLocked());
         }
     }
 
@@ -4092,7 +4031,7 @@
 
     private void boostScreenBrightnessInternal(long eventTime, int uid) {
         synchronized (mLock) {
-            if (!mSystemReady || getWakefulnessLocked() == WAKEFULNESS_ASLEEP
+            if (!mSystemReady || getGlobalWakefulnessLocked() == WAKEFULNESS_ASLEEP
                     || eventTime < mLastScreenBrightnessBoostTime) {
                 return;
             }
@@ -4225,14 +4164,9 @@
             synchronized (mLock) {
                 mForceSuspendActive = true;
                 // Place the system in an non-interactive state
-                boolean updatePowerState = false;
                 for (int idx = 0; idx < mPowerGroups.size(); idx++) {
-                    updatePowerState |= sleepDisplayGroupNoUpdateLocked(mPowerGroups.valueAt(idx),
-                            mClock.uptimeMillis(), PowerManager.GO_TO_SLEEP_REASON_FORCE_SUSPEND,
-                            PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE, uid);
-                }
-                if (updatePowerState) {
-                    updatePowerStateLocked();
+                    sleepPowerGroupLocked(mPowerGroups.valueAt(idx), mClock.uptimeMillis(),
+                            PowerManager.GO_TO_SLEEP_REASON_FORCE_SUSPEND, uid);
                 }
 
                 // Disable all the partial wake locks as well
@@ -4331,7 +4265,7 @@
             mConstants.dump(pw);
             pw.println("  mDirty=0x" + Integer.toHexString(mDirty));
             pw.println("  mWakefulness="
-                    + PowerManagerInternal.wakefulnessToString(getWakefulnessLocked()));
+                    + PowerManagerInternal.wakefulnessToString(getGlobalWakefulnessLocked()));
             pw.println("  mWakefulnessChanging=" + mWakefulnessChanging);
             pw.println("  mIsPowered=" + mIsPowered);
             pw.println("  mPlugType=" + mPlugType);
@@ -4382,9 +4316,10 @@
             pw.println("  mDeviceIdleMode=" + mDeviceIdleMode);
             pw.println("  mDeviceIdleWhitelist=" + Arrays.toString(mDeviceIdleWhitelist));
             pw.println("  mDeviceIdleTempWhitelist=" + Arrays.toString(mDeviceIdleTempWhitelist));
-            pw.println("  mLastWakeTime=" + TimeUtils.formatUptime(mLastWakeTime));
-            pw.println("  mLastSleepTime=" + TimeUtils.formatUptime(mLastSleepTime));
-            pw.println("  mLastSleepReason=" + PowerManager.sleepReasonToString(mLastSleepReason));
+            pw.println("  mLastWakeTime=" + TimeUtils.formatUptime(mLastGlobalWakeTime));
+            pw.println("  mLastSleepTime=" + TimeUtils.formatUptime(mLastGlobalSleepTime));
+            pw.println("  mLastSleepReason=" + PowerManager.sleepReasonToString(
+                    mLastGlobalSleepReason));
             pw.println("  mLastInteractivePowerHintTime="
                     + TimeUtils.formatUptime(mLastInteractivePowerHintTime));
             pw.println("  mLastScreenBrightnessBoostTime="
@@ -4565,7 +4500,7 @@
         synchronized (mLock) {
             mConstants.dumpProto(proto);
             proto.write(PowerManagerServiceDumpProto.DIRTY, mDirty);
-            proto.write(PowerManagerServiceDumpProto.WAKEFULNESS, getWakefulnessLocked());
+            proto.write(PowerManagerServiceDumpProto.WAKEFULNESS, getGlobalWakefulnessLocked());
             proto.write(PowerManagerServiceDumpProto.IS_WAKEFULNESS_CHANGING, mWakefulnessChanging);
             proto.write(PowerManagerServiceDumpProto.IS_POWERED, mIsPowered);
             proto.write(PowerManagerServiceDumpProto.PLUG_TYPE, mPlugType);
@@ -4664,8 +4599,8 @@
                 proto.write(PowerManagerServiceDumpProto.DEVICE_IDLE_TEMP_WHITELIST, id);
             }
 
-            proto.write(PowerManagerServiceDumpProto.LAST_WAKE_TIME_MS, mLastWakeTime);
-            proto.write(PowerManagerServiceDumpProto.LAST_SLEEP_TIME_MS, mLastSleepTime);
+            proto.write(PowerManagerServiceDumpProto.LAST_WAKE_TIME_MS, mLastGlobalWakeTime);
+            proto.write(PowerManagerServiceDumpProto.LAST_SLEEP_TIME_MS, mLastGlobalSleepTime);
             proto.write(
                     PowerManagerServiceDumpProto.LAST_INTERACTIVE_POWER_HINT_TIME_MS,
                     mLastInteractivePowerHintTime);
@@ -5505,8 +5440,10 @@
             final int uid = Binder.getCallingUid();
             final long ident = Binder.clearCallingIdentity();
             try {
-                wakeDisplayGroup(Display.DEFAULT_DISPLAY_GROUP, eventTime, reason, details, uid,
-                        opPackageName, uid);
+                synchronized (mLock) {
+                    wakePowerGroupLocked(mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP), eventTime,
+                            reason, details, uid, opPackageName, uid);
+                }
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -5524,7 +5461,14 @@
             final int uid = Binder.getCallingUid();
             final long ident = Binder.clearCallingIdentity();
             try {
-                sleepDisplayGroup(Display.DEFAULT_DISPLAY_GROUP, eventTime, reason, flags, uid);
+                synchronized (mLock) {
+                    PowerGroup defaultPowerGroup = mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP);
+                    if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) {
+                        sleepPowerGroupLocked(defaultPowerGroup, eventTime, reason, uid);
+                    } else {
+                        dozePowerGroupLocked(defaultPowerGroup, eventTime, reason, uid);
+                    }
+                }
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -5542,7 +5486,10 @@
             final int uid = Binder.getCallingUid();
             final long ident = Binder.clearCallingIdentity();
             try {
-                dreamDisplayGroup(Display.DEFAULT_DISPLAY_GROUP, eventTime, uid);
+                synchronized (mLock) {
+                    dreamPowerGroupLocked(mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP),
+                            eventTime, uid);
+                }
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -6181,13 +6128,15 @@
 
     private int getLastSleepReasonInternal() {
         synchronized (mLock) {
-            return mLastSleepReason;
+            return mLastGlobalSleepReason;
         }
     }
 
+    @VisibleForTesting
     private PowerManager.WakeData getLastWakeupInternal() {
         synchronized (mLock) {
-            return new WakeData(mLastWakeTime, mLastWakeReason, mLastWakeTime - mLastSleepTime);
+            return new WakeData(mLastGlobalWakeTime, mLastGlobalWakeReason,
+                    mLastGlobalWakeTime - mLastGlobalSleepTime);
         }
     }
 
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index e180032..277d802 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -23,13 +23,13 @@
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
-import static android.net.NetworkIdentity.OEM_PAID;
-import static android.net.NetworkIdentity.OEM_PRIVATE;
 import static android.net.NetworkStats.METERED_YES;
 import static android.net.NetworkTemplate.MATCH_ETHERNET;
 import static android.net.NetworkTemplate.MATCH_MOBILE;
 import static android.net.NetworkTemplate.MATCH_WIFI;
 import static android.net.NetworkTemplate.OEM_MANAGED_ALL;
+import static android.net.NetworkTemplate.OEM_MANAGED_PAID;
+import static android.net.NetworkTemplate.OEM_MANAGED_PRIVATE;
 import static android.net.NetworkTemplate.getAllCollapsedRatTypes;
 import static android.os.Debug.getIonHeapsSizeKb;
 import static android.os.Process.LAST_SHARED_APPLICATION_GID;
@@ -1292,7 +1292,8 @@
                 new Pair(MATCH_MOBILE, TRANSPORT_CELLULAR),
                 new Pair(MATCH_WIFI, TRANSPORT_WIFI)
         );
-        final int[] oemManagedTypes = new int[] {OEM_PAID | OEM_PRIVATE, OEM_PAID, OEM_PRIVATE};
+        final int[] oemManagedTypes = new int[] {OEM_MANAGED_PAID | OEM_MANAGED_PRIVATE,
+                OEM_MANAGED_PAID, OEM_MANAGED_PRIVATE};
 
         final List<NetworkStatsExt> ret = new ArrayList<>();
 
@@ -1368,12 +1369,12 @@
                 NetworkStatsUtils.fromPublicNetworkStats(queryNonTaggedStats);
         if (!includeTags) return nonTaggedStats;
 
-        final android.app.usage.NetworkStats quaryTaggedStats =
+        final android.app.usage.NetworkStats queryTaggedStats =
                 mNetworkStatsManager.queryTaggedSummary(template,
                 currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration,
                 currentTimeInMillis);
         final NetworkStats taggedStats =
-                NetworkStatsUtils.fromPublicNetworkStats(quaryTaggedStats);
+                NetworkStatsUtils.fromPublicNetworkStats(queryTaggedStats);
         return nonTaggedStats.add(taggedStats);
     }
 
@@ -1470,7 +1471,7 @@
      */
     @NonNull private NetworkStats sliceNetworkStats(@NonNull NetworkStats stats,
             @NonNull Function<NetworkStats.Entry, NetworkStats.Entry> slicer) {
-        NetworkStats ret = new NetworkStats(stats.getElapsedRealtime(), 1);
+        NetworkStats ret = new NetworkStats(0, 1);
         NetworkStats.Entry entry = new NetworkStats.Entry();
         for (NetworkStats.Entry e : stats) {
             if (slicer != null) {
diff --git a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
index 468612f..53a9244 100644
--- a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
+++ b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
@@ -2100,7 +2100,7 @@
 
         @Override
         public void onCommandRequest(
-                @TvInteractiveAppService.InteractiveAppServiceCommandType String cmdType,
+                @TvInteractiveAppService.PlaybackCommandType String cmdType,
                 Bundle parameters) {
             synchronized (mLock) {
                 if (DEBUG) {
diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java
index eafd9d7..6c5d952 100644
--- a/services/core/java/com/android/server/vibrator/VibrationSettings.java
+++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java
@@ -179,7 +179,7 @@
         try {
             ActivityManager.getService().registerUidObserver(mUidObserver,
                     ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE,
-                    ActivityManager.PROCESS_STATE_UNKNOWN, mContext.getOpPackageName());
+                    ActivityManager.PROCESS_STATE_UNKNOWN, null);
         } catch (RemoteException e) {
             // ignored; both services live in system_server
         }
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index a95b6c9..b2e34da 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -16,6 +16,9 @@
 
 package com.android.server.vibrator;
 
+import static android.os.VibrationEffect.VibrationParameter.targetAmplitude;
+import static android.os.VibrationEffect.VibrationParameter.targetFrequency;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
@@ -65,6 +68,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
+import java.time.Duration;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.LinkedList;
@@ -1711,7 +1715,8 @@
             long duration = Long.parseLong(getNextArgRequired());
             int amplitude = hasAmplitude ? Integer.parseInt(getNextArgRequired())
                     : VibrationEffect.DEFAULT_AMPLITUDE;
-            composition.addEffect(VibrationEffect.createOneShot(duration, amplitude), delay);
+            composition.addOffDuration(Duration.ofMillis(delay));
+            composition.addEffect(VibrationEffect.createOneShot(duration, amplitude));
         }
 
         private void addWaveformToComposition(VibrationEffect.Composition composition) {
@@ -1762,23 +1767,44 @@
                 }
             }
 
+            // Add delay before the waveform.
+            composition.addOffDuration(Duration.ofMillis(delay));
+
             VibrationEffect.WaveformBuilder waveform = VibrationEffect.startWaveform();
             for (int i = 0; i < durations.size(); i++) {
-                if (isContinuous) {
-                    if (hasFrequencies) {
-                        waveform.addRamp(amplitudes.get(i), frequencies.get(i), durations.get(i));
-                    } else {
-                        waveform.addRamp(amplitudes.get(i), durations.get(i));
-                    }
+                Duration transitionDuration = isContinuous
+                        ? Duration.ofMillis(durations.get(i))
+                        : Duration.ZERO;
+
+                if (hasFrequencies) {
+                    waveform.addTransition(transitionDuration, targetAmplitude(amplitudes.get(i)),
+                            targetFrequency(frequencies.get(i)));
                 } else {
+                    waveform.addTransition(transitionDuration, targetAmplitude(amplitudes.get(i)));
+                }
+                if (!isContinuous) {
+                    waveform.addSustain(Duration.ofMillis(durations.get(i)));
+                }
+
+                if ((i > 0) && (i == repeat)) {
+                    // Add segment that is not repeated to the composition and reset builder.
+                    composition.addEffect(waveform.build());
+
                     if (hasFrequencies) {
-                        waveform.addStep(amplitudes.get(i), frequencies.get(i), durations.get(i));
+                        waveform = VibrationEffect.startWaveform(targetAmplitude(amplitudes.get(i)),
+                                targetFrequency(frequencies.get(i)));
                     } else {
-                        waveform.addStep(amplitudes.get(i), durations.get(i));
+                        waveform = VibrationEffect.startWaveform(
+                                targetAmplitude(amplitudes.get(i)));
                     }
                 }
             }
-            composition.addEffect(waveform.build(repeat), delay);
+            if (repeat < 0) {
+                composition.addEffect(waveform.build());
+            } else {
+                // The waveform was already split at the repeat index, just repeat what remains.
+                composition.repeatEffectIndefinitely(waveform.build());
+            }
         }
 
         private void addPrebakedToComposition(VibrationEffect.Composition composition) {
@@ -1796,7 +1822,8 @@
             }
 
             int effectId = Integer.parseInt(getNextArgRequired());
-            composition.addEffect(VibrationEffect.get(effectId, shouldFallback), delay);
+            composition.addOffDuration(Duration.ofMillis(delay));
+            composition.addEffect(VibrationEffect.get(effectId, shouldFallback));
         }
 
         private void addPrimitivesToComposition(VibrationEffect.Composition composition) {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 49d6a34..897549b 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -395,9 +395,9 @@
     // How many activities have to be scheduled to stop to force a stop pass.
     private static final int MAX_STOPPING_TO_FORCE = 3;
 
-    private static final int STARTING_WINDOW_TYPE_NONE = 0;
-    private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
-    private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
+    static final int STARTING_WINDOW_TYPE_NONE = 0;
+    static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
+    static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
 
     static final int INVALID_PID = -1;
 
@@ -2149,7 +2149,8 @@
 
         final int typeParameter = StartingSurfaceController
                 .makeStartingWindowTypeParameter(newTask, taskSwitch, processRunning,
-                        allowTaskSnapshot, activityCreated, useEmpty, useLegacy, activityAllDrawn);
+                        allowTaskSnapshot, activityCreated, useEmpty, useLegacy, activityAllDrawn,
+                        type, packageName, mUserId);
 
         if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
             if (isActivityTypeHome()) {
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index e119a9a..5164bf0 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -2924,7 +2924,7 @@
         final boolean onTop =
                 (aOptions == null || !aOptions.getAvoidMoveToFront()) && !mLaunchTaskBehind;
         return mRootWindowContainer.getLaunchRootTask(r, aOptions, task, mSourceRootTask, onTop,
-                mLaunchParams, launchFlags, mRequest.realCallingPid, mRequest.realCallingUid);
+                mLaunchParams, launchFlags);
     }
 
     private boolean isLaunchModeOneOf(int mode1, int mode2) {
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index dd394ca..5d879ce 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -2224,25 +2224,9 @@
             return;
         }
 
-        if (!task.supportsSplitScreenWindowingMode() || forceNonResizable) {
-            if (task.mTransitionController.isShellTransitionsEnabled()) return;
-            // Dismiss docked root task. If task appeared to be in docked root task but is not
-            // resizable - we need to move it to top of fullscreen root task, otherwise it will
-            // be covered.
-            final TaskDisplayArea taskDisplayArea = task.getDisplayArea();
-            if (taskDisplayArea.isSplitScreenModeActivated()) {
-                // Display a warning toast that we tried to put an app that doesn't support
-                // split-screen in split-screen.
-                mService.getTaskChangeNotificationController()
-                        .notifyActivityDismissingDockedRootTask();
-                taskDisplayArea.onSplitScreenModeDismissed(task);
-                taskDisplayArea.mDisplayContent.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS,
-                        true /* notifyClients */);
-            }
-            return;
+        if (!forceNonResizable) {
+            handleForcedResizableTaskIfNeeded(task, FORCED_RESIZEABLE_REASON_SPLIT_SCREEN);
         }
-
-        handleForcedResizableTaskIfNeeded(task, FORCED_RESIZEABLE_REASON_SPLIT_SCREEN);
     }
 
     /** Notifies that the top activity of the task is forced to be resizeable. */
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 5facc0d..a1c823e 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3043,13 +3043,6 @@
             mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
         }
         amendWindowTapExcludeRegion(mTouchExcludeRegion);
-        // TODO(multi-display): Support docked root tasks on secondary displays & task containers.
-        if (mDisplayId == DEFAULT_DISPLAY
-                && getDefaultTaskDisplayArea().isSplitScreenModeActivated()) {
-            mDividerControllerLocked.getTouchRegion(mTmpRect);
-            mTmpRegion.set(mTmpRect);
-            mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
-        }
         mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion);
     }
 
@@ -3440,12 +3433,6 @@
         if (rootPinnedTask != null) {
             pw.println(prefix + "rootPinnedTask=" + rootPinnedTask.getName());
         }
-        final Task rootSplitScreenPrimaryTask = getDefaultTaskDisplayArea()
-                .getRootSplitScreenPrimaryTask();
-        if (rootSplitScreenPrimaryTask != null) {
-            pw.println(
-                    prefix + "rootSplitScreenPrimaryTask=" + rootSplitScreenPrimaryTask.getName());
-        }
         // TODO: Support recents on non-default task containers
         final Task rootRecentsTask = getDefaultTaskDisplayArea().getRootTask(
                 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_RECENTS);
@@ -4849,13 +4836,10 @@
         }
 
         private static boolean skipImeWindowsDuringTraversal(DisplayContent dc) {
-            // We skip IME windows so they're processed just above their target, except
-            // in split-screen mode where we process the IME containers above the docked divider.
+            // We skip IME windows so they're processed just above their target.
             // Note that this method check should align with {@link
             // WindowState#applyImeWindowsIfNeeded} in case of any state mismatch.
             return dc.mImeLayeringTarget != null
-                    && (!dc.getDefaultTaskDisplayArea().isSplitScreenModeActivated()
-                             || dc.mImeLayeringTarget.getTask() == null)
                     // Make sure that the IME window won't be skipped to report that it has
                     // completed the orientation change.
                     && !dc.mWmService.mDisplayFrozen;
diff --git a/services/core/java/com/android/server/wm/EmbeddedWindowController.java b/services/core/java/com/android/server/wm/EmbeddedWindowController.java
index e04e3a3..0e2d847 100644
--- a/services/core/java/com/android/server/wm/EmbeddedWindowController.java
+++ b/services/core/java/com/android/server/wm/EmbeddedWindowController.java
@@ -41,8 +41,6 @@
     private static final String TAG = TAG_WITH_CLASS_NAME ? "EmbeddedWindowController" : TAG_WM;
     /* maps input token to an embedded window */
     private ArrayMap<IBinder /*input token */, EmbeddedWindow> mWindows = new ArrayMap<>();
-    private ArrayMap<IBinder /*focus grant token */, EmbeddedWindow> mWindowsByFocusToken =
-        new ArrayMap<>();
     private final Object mGlobalLock;
     private final ActivityTaskManagerService mAtmService;
 
@@ -61,13 +59,10 @@
     void add(IBinder inputToken, EmbeddedWindow window) {
         try {
             mWindows.put(inputToken, window);
-            final IBinder focusToken = window.getFocusGrantToken();
-            mWindowsByFocusToken.put(focusToken, window);
             updateProcessController(window);
             window.mClient.asBinder().linkToDeath(()-> {
                 synchronized (mGlobalLock) {
                     mWindows.remove(inputToken);
-                    mWindowsByFocusToken.remove(focusToken);
                 }
             }, 0);
         } catch (RemoteException e) {
@@ -112,10 +107,8 @@
 
     void remove(IWindow client) {
         for (int i = mWindows.size() - 1; i >= 0; i--) {
-            EmbeddedWindow ew = mWindows.valueAt(i);
-            if (ew.mClient.asBinder() == client.asBinder()) {
+            if (mWindows.valueAt(i).mClient.asBinder() == client.asBinder()) {
                 mWindows.removeAt(i).onRemoved();
-                mWindowsByFocusToken.remove(ew.getFocusGrantToken());
                 return;
             }
         }
@@ -123,10 +116,8 @@
 
     void onWindowRemoved(WindowState host) {
         for (int i = mWindows.size() - 1; i >= 0; i--) {
-            EmbeddedWindow ew = mWindows.valueAt(i);
-            if (ew.mHostWindowState == host) {
+            if (mWindows.valueAt(i).mHostWindowState == host) {
                 mWindows.removeAt(i).onRemoved();
-                mWindowsByFocusToken.remove(ew.getFocusGrantToken());
             }
         }
     }
@@ -135,10 +126,6 @@
         return mWindows.get(inputToken);
     }
 
-    EmbeddedWindow getByFocusToken(IBinder focusGrantToken) {
-        return mWindowsByFocusToken.get(focusGrantToken);
-    }
-
     void onActivityRemoved(ActivityRecord activityRecord) {
         for (int i = mWindows.size() - 1; i >= 0; i--) {
             final EmbeddedWindow window = mWindows.valueAt(i);
@@ -170,8 +157,6 @@
         // and this variable is mostly used for tracking that.
         boolean mIsOverlay = false;
 
-        private IBinder mFocusGrantToken;
-
         /**
          * @param session  calling session to check ownership of the window
          * @param clientToken client token used to clean up the map if the embedding process dies
@@ -186,7 +171,7 @@
          */
         EmbeddedWindow(Session session, WindowManagerService service, IWindow clientToken,
                        WindowState hostWindowState, int ownerUid, int ownerPid, int windowType,
-                       int displayId, IBinder focusGrantToken) {
+                       int displayId) {
             mSession = session;
             mWmService = service;
             mClient = clientToken;
@@ -197,7 +182,6 @@
             mOwnerPid = ownerPid;
             mWindowType = windowType;
             mDisplayId = displayId;
-            mFocusGrantToken = focusGrantToken;
         }
 
         @Override
@@ -258,17 +242,6 @@
             return mIsOverlay;
         }
 
-        IBinder getFocusGrantToken() {
-            return mFocusGrantToken;
-        }
-
-        IBinder getInputChannelToken() {
-            if (mInputChannel != null) {
-                return mInputChannel.getToken();
-            }
-            return null;
-        }
-
         /**
          * System hosted overlays need the WM to invoke grantEmbeddedWindowFocus and
          * so we need to participate inside handlePointerDownOutsideFocus logic
@@ -282,7 +255,7 @@
 
         private void handleTap(boolean grantFocus) {
             if (mInputChannel != null) {
-                mWmService.grantEmbeddedWindowFocus(mSession, mFocusGrantToken, grantFocus);
+                mWmService.grantEmbeddedWindowFocus(mSession, mInputChannel.getToken(), grantFocus);
             }
         }
 
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index baf7f87..5c8502b 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -450,16 +450,6 @@
             return;
         }
 
-        // Dismiss split screen
-        // The lock screen is currently showing, but is occluded by a window that can
-        // show on top of the lock screen. In this can we want to dismiss the docked
-        // stack since it will be complicated/risky to try to put the activity on top
-        // of the lock screen in the right fullscreen configuration.
-        final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
-        if (taskDisplayArea.isSplitScreenModeActivated()) {
-            taskDisplayArea.onSplitScreenModeDismissed();
-        }
-
         // Dismiss freeform windowing mode
         if (currentTaskControllingOcclusion == null) {
             return;
diff --git a/services/core/java/com/android/server/wm/LaunchParamsController.java b/services/core/java/com/android/server/wm/LaunchParamsController.java
index 3793e4b..8e5d73f 100644
--- a/services/core/java/com/android/server/wm/LaunchParamsController.java
+++ b/services/core/java/com/android/server/wm/LaunchParamsController.java
@@ -150,10 +150,8 @@
 
             if (mTmpParams.hasWindowingMode() && task.isRootTask()
                     && mTmpParams.mWindowingMode != task.getWindowingMode()) {
-                final int activityType = activity != null
-                        ? activity.getActivityType() : task.getActivityType();
                 task.setWindowingMode(task.getDisplayArea().validateWindowingMode(
-                        mTmpParams.mWindowingMode, activity, task, activityType));
+                        mTmpParams.mWindowingMode, activity, task));
             }
 
             if (mTmpParams.mBounds.isEmpty()) {
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 4c72d02b..76a7981 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -1907,10 +1907,6 @@
         final Task topFocusedRootTask = getTopDisplayFocusedRootTask();
         final int focusRootTaskId = topFocusedRootTask != null
                 ? topFocusedRootTask.getRootTaskId() : INVALID_TASK_ID;
-        // We dismiss the docked root task whenever we switch users.
-        if (getDefaultTaskDisplayArea().isSplitScreenModeActivated()) {
-            getDefaultTaskDisplayArea().onSplitScreenModeDismissed();
-        }
         // Also dismiss the pinned root task whenever we switch users. Removing the pinned root task
         // will also cause all tasks to be moved to the fullscreen root task at a position that is
         // appropriate.
@@ -2765,8 +2761,7 @@
     Task getLaunchRootTask(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
             @Nullable Task candidateTask, boolean onTop) {
         return getLaunchRootTask(r, options, candidateTask, null /* sourceTask */, onTop,
-                null /* launchParams */, 0 /* launchFlags */, -1 /* no realCallingPid */,
-                -1 /* no realCallingUid */);
+                null /* launchParams */, 0 /* launchFlags */);
     }
 
     /**
@@ -2785,8 +2780,7 @@
     Task getLaunchRootTask(@Nullable ActivityRecord r,
             @Nullable ActivityOptions options, @Nullable Task candidateTask,
             @Nullable Task sourceTask, boolean onTop,
-            @Nullable LaunchParamsController.LaunchParams launchParams, int launchFlags,
-            int realCallingPid, int realCallingUid) {
+            @Nullable LaunchParamsController.LaunchParams launchParams, int launchFlags) {
         int taskId = INVALID_TASK_ID;
         int displayId = INVALID_DISPLAY;
         TaskDisplayArea taskDisplayArea = null;
@@ -2835,11 +2829,7 @@
 
         if (taskDisplayArea != null) {
             final int tdaDisplayId = taskDisplayArea.getDisplayId();
-            final boolean canLaunchOnDisplayFromStartRequest =
-                    realCallingPid != 0 && realCallingUid > 0 && r != null
-                            && mTaskSupervisor.canPlaceEntityOnDisplay(tdaDisplayId,
-                            realCallingPid, realCallingUid, r.info);
-            if (canLaunchOnDisplayFromStartRequest || canLaunchOnDisplay(r, tdaDisplayId)) {
+            if (canLaunchOnDisplay(r, tdaDisplayId)) {
                 if (r != null) {
                     final Task result = getValidLaunchRootTaskInTaskDisplayArea(
                             taskDisplayArea, r, candidateTask, options, launchParams);
@@ -2872,8 +2862,7 @@
             container = rootTask.getDisplayArea();
             if (container != null && canLaunchOnDisplay(r, container.mDisplayContent.mDisplayId)) {
                 if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
-                    windowingMode = container.resolveWindowingMode(r, options, candidateTask,
-                            activityType);
+                    windowingMode = container.resolveWindowingMode(r, options, candidateTask);
                 }
                 // Always allow organized tasks that created by organizer since the activity type
                 // of an organized task is decided by the activity type of its top child, which
@@ -2889,8 +2878,7 @@
                 || !canLaunchOnDisplay(r, container.mDisplayContent.mDisplayId)) {
             container = getDefaultTaskDisplayArea();
             if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
-                windowingMode = container.resolveWindowingMode(r, options, candidateTask,
-                        activityType);
+                windowingMode = container.resolveWindowingMode(r, options, candidateTask);
             }
         }
 
@@ -2952,8 +2940,7 @@
             windowingMode = options != null ? options.getLaunchWindowingMode()
                     : r.getWindowingMode();
         }
-        windowingMode = taskDisplayArea.validateWindowingMode(windowingMode, r, candidateTask,
-                r.getActivityType());
+        windowingMode = taskDisplayArea.validateWindowingMode(windowingMode, r, candidateTask);
 
         // Return the topmost valid root task on the display.
         final int targetWindowingMode = windowingMode;
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 98acc46..9b94f44 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -813,7 +813,7 @@
     @Override
     public void grantInputChannel(int displayId, SurfaceControl surface,
             IWindow window, IBinder hostInputToken, int flags, int privateFlags, int type,
-            IBinder focusGrantToken, InputChannel outInputChannel) {
+            InputChannel outInputChannel) {
         if (hostInputToken == null && !mCanAddInternalSystemWindow) {
             // Callers without INTERNAL_SYSTEM_WINDOW permission cannot grant input channel to
             // embedded windows without providing a host window input token
@@ -829,7 +829,7 @@
         try {
             mService.grantInputChannel(this, mUid, mPid, displayId, surface, window, hostInputToken,
                     flags, mCanAddInternalSystemWindow ? privateFlags : 0,
-                    mCanAddInternalSystemWindow ? type : 0, focusGrantToken, outInputChannel);
+                    mCanAddInternalSystemWindow ? type : 0, outInputChannel);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
diff --git a/services/core/java/com/android/server/wm/ShellRoot.java b/services/core/java/com/android/server/wm/ShellRoot.java
index 6ed59e9..2eab3ba 100644
--- a/services/core/java/com/android/server/wm/ShellRoot.java
+++ b/services/core/java/com/android/server/wm/ShellRoot.java
@@ -141,8 +141,7 @@
                 && mShellRootLayer != SHELL_ROOT_LAYER_PIP) {
             return null;
         }
-        if (mShellRootLayer == SHELL_ROOT_LAYER_DIVIDER
-                && !mDisplayContent.getDefaultTaskDisplayArea().isSplitScreenModeActivated()) {
+        if (mShellRootLayer == SHELL_ROOT_LAYER_DIVIDER) {
             return null;
         }
         if (mShellRootLayer == SHELL_ROOT_LAYER_PIP
diff --git a/services/core/java/com/android/server/wm/StartingSurfaceController.java b/services/core/java/com/android/server/wm/StartingSurfaceController.java
index eb73cd8..2a3767f 100644
--- a/services/core/java/com/android/server/wm/StartingSurfaceController.java
+++ b/services/core/java/com/android/server/wm/StartingSurfaceController.java
@@ -18,6 +18,7 @@
 
 import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED;
 import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_DRAWN;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_HANDLE_EMPTY_SCREEN;
 import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT;
 import static android.window.StartingWindowInfo.TYPE_PARAMETER_LEGACY_SPLASH_SCREEN;
 import static android.window.StartingWindowInfo.TYPE_PARAMETER_NEW_TASK;
@@ -25,12 +26,17 @@
 import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH;
 import static android.window.StartingWindowInfo.TYPE_PARAMETER_USE_EMPTY_SPLASH_SCREEN;
 
+import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.compat.CompatChanges;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
 import android.content.pm.ApplicationInfo;
+import android.os.UserHandle;
 import android.util.Slog;
 import android.window.TaskSnapshot;
 
@@ -43,6 +49,14 @@
 public class StartingSurfaceController {
     private static final String TAG = TAG_WITH_CLASS_NAME
             ? StartingSurfaceController.class.getSimpleName() : TAG_WM;
+    /**
+     * Allow the empty style splash screen view can be copy and transfer to another process if
+     * the app targeting to {@link android.os.Build.VERSION_CODES#TIRAMISU} or higher.
+     */
+    @ChangeId
+    @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.TIRAMISU)
+    private static final long ALLOW_COPY_EMPTY_VIEW = 205907456L;
+
     private final WindowManagerService mService;
     private final SplashScreenExceptionList mSplashScreenExceptionsList;
 
@@ -81,7 +95,8 @@
 
     static int makeStartingWindowTypeParameter(boolean newTask, boolean taskSwitch,
             boolean processRunning, boolean allowTaskSnapshot, boolean activityCreated,
-            boolean useEmpty, boolean useLegacy, boolean activityDrawn) {
+            boolean useEmpty, boolean useLegacy, boolean activityDrawn, int startingWindowType,
+            String packageName, int userId) {
         int parameter = 0;
         if (newTask) {
             parameter |= TYPE_PARAMETER_NEW_TASK;
@@ -107,6 +122,11 @@
         if (activityDrawn) {
             parameter |= TYPE_PARAMETER_ACTIVITY_DRAWN;
         }
+        if (startingWindowType == STARTING_WINDOW_TYPE_SPLASH_SCREEN
+                && CompatChanges.isChangeEnabled(ALLOW_COPY_EMPTY_VIEW, packageName,
+                UserHandle.of(userId))) {
+            parameter |= TYPE_PARAMETER_ALLOW_HANDLE_EMPTY_SCREEN;
+        }
         return parameter;
     }
 
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index ff9d9f7..91c1374 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -4500,22 +4500,11 @@
         // right mode.
         if (!creating) {
             if (!taskDisplayArea.isValidWindowingMode(windowingMode, null /* ActivityRecord */,
-                    topTask, getActivityType())) {
+                    topTask)) {
                 windowingMode = WINDOWING_MODE_UNDEFINED;
             }
         }
 
-        final boolean alreadyInSplitScreenMode = taskDisplayArea.isSplitScreenModeActivated();
-
-        if (creating && alreadyInSplitScreenMode && windowingMode == WINDOWING_MODE_FULLSCREEN
-                && isActivityTypeStandardOrUndefined()) {
-            // If the root task is being created explicitly in fullscreen mode, dismiss split-screen
-            // and display a warning toast about it.
-            mAtmService.getTaskChangeNotificationController()
-                    .notifyActivityDismissingDockedRootTask();
-            taskDisplayArea.onSplitScreenModeDismissed(this);
-        }
-
         if (currentMode == windowingMode) {
             // You are already in the window mode, so we can skip most of the work below. However,
             // it's possible that we have inherited the current windowing mode from a parent. So,
@@ -6501,9 +6490,8 @@
 
             if (!TaskDisplayArea.isWindowingModeSupported(mWindowingMode,
                     mAtmService.mSupportsMultiWindow,
-                    mAtmService.mSupportsSplitScreenMultiWindow,
                     mAtmService.mSupportsFreeformWindowManagement,
-                    mAtmService.mSupportsPictureInPicture, mActivityType)) {
+                    mAtmService.mSupportsPictureInPicture)) {
                 throw new IllegalArgumentException("Can't create root task for unsupported "
                         + "windowingMode=" + mWindowingMode);
             }
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index dfb559f..1bba103 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -24,8 +24,6 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
@@ -53,8 +51,6 @@
 import android.util.Slog;
 import android.view.RemoteAnimationTarget;
 import android.view.SurfaceControl;
-import android.window.WindowContainerToken;
-import android.window.WindowContainerTransaction;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.protolog.common.ProtoLog;
@@ -114,7 +110,6 @@
     // through the list to find them.
     private Task mRootHomeTask;
     private Task mRootPinnedTask;
-    private Task mRootSplitScreenPrimaryTask;
 
     // TODO(b/159029784): Remove when getStack() behavior is cleaned-up
     private Task mRootRecentsTask;
@@ -232,8 +227,6 @@
         }
         if (windowingMode == WINDOWING_MODE_PINNED) {
             return mRootPinnedTask;
-        } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
-            return mRootSplitScreenPrimaryTask;
         }
         return getRootTask(rootTask -> {
             if (activityType == ACTIVITY_TYPE_UNDEFINED
@@ -265,21 +258,6 @@
         return mRootPinnedTask;
     }
 
-    Task getRootSplitScreenPrimaryTask() {
-        return mRootSplitScreenPrimaryTask;
-    }
-
-    Task getRootSplitScreenSecondaryTask() {
-        // Only check the direct child Task for now, since the primary is also a direct child Task.
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            final Task task = mChildren.get(i).asTask();
-            if (task != null && task.inSplitScreenSecondaryWindowingMode()) {
-                return task;
-            }
-        }
-        return null;
-    }
-
     ArrayList<Task> getVisibleTasks() {
         final ArrayList<Task> visibleTasks = new ArrayList<>();
         forAllTasks(task -> {
@@ -333,14 +311,6 @@
                                 + " already exist on display=" + this + " rootTask=" + rootTask);
             }
             mRootPinnedTask = rootTask;
-        } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
-            if (mRootSplitScreenPrimaryTask != null) {
-                throw new IllegalArgumentException(
-                        "addRootTaskReferenceIfNeeded: root split screen primary task="
-                                + mRootSplitScreenPrimaryTask
-                                + " already exist on display=" + this + " rootTask=" + rootTask);
-            }
-            mRootSplitScreenPrimaryTask = rootTask;
         }
     }
 
@@ -351,8 +321,6 @@
             mRootRecentsTask = null;
         } else if (rootTask == mRootPinnedTask) {
             mRootPinnedTask = null;
-        } else if (rootTask == mRootSplitScreenPrimaryTask) {
-            mRootSplitScreenPrimaryTask = null;
         }
     }
 
@@ -708,39 +676,13 @@
             }, SCREEN_ORIENTATION_UNSET);
         }
 
-        if (isRootTaskVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) {
-            // Apps and their containers are not allowed to specify an orientation while using
-            // root tasks...except for the root home task if it is not resizable and currently
-            // visible (top of) its root task.
-            if (mRootHomeTask != null && !mRootHomeTask.isResizeable()) {
-                // Manually nest one-level because because getOrientation() checks fillsParent()
-                // which checks that requestedOverrideBounds() is empty. However, in this case,
-                // it is not empty because it's been overridden to maintain the fullscreen size
-                // within a smaller split-root.
-                final Task topHomeTask = mRootHomeTask.getTopMostTask();
-                final ActivityRecord topHomeActivity = topHomeTask.getTopNonFinishingActivity();
-                // If a home activity is in the process of launching and isn't yet visible we
-                // should still respect the root task's preferred orientation to ensure rotation
-                // occurs before the home activity finishes launching.
-                final boolean isHomeActivityLaunching = topHomeActivity != null
-                        && topHomeActivity.mVisibleRequested;
-                if (topHomeTask.isVisible() || isHomeActivityLaunching) {
-                    final int orientation = topHomeTask.getOrientation();
-                    if (orientation != SCREEN_ORIENTATION_UNSET) {
-                        return orientation;
-                    }
-                }
-            }
+        // Apps and their containers are not allowed to specify an orientation of non floating
+        // visible tasks created by organizer. The organizer handles the orientation instead.
+        final Task nonFloatingTopTask =
+                getRootTask(t -> !t.getWindowConfiguration().tasksAreFloating());
+        if (nonFloatingTopTask != null && nonFloatingTopTask.mCreatedByOrganizer
+                && nonFloatingTopTask.isVisible()) {
             return SCREEN_ORIENTATION_UNSPECIFIED;
-        } else {
-            // Apps and their containers are not allowed to specify an orientation of non floating
-            // visible tasks created by organizer. The organizer handles the orientation instead.
-            final Task nonFloatingTopTask =
-                    getRootTask(t -> !t.getWindowConfiguration().tasksAreFloating());
-            if (nonFloatingTopTask != null && nonFloatingTopTask.mCreatedByOrganizer
-                    && nonFloatingTopTask.isVisible()) {
-                return SCREEN_ORIENTATION_UNSPECIFIED;
-            }
         }
 
         final int orientation = super.getOrientation(candidate);
@@ -845,7 +787,7 @@
                     && child.inMultiWindowMode()
                     && childTask.getRootTask().getAdjacentTaskFragment() != null;
 
-            if (inAdjacentTask || child.inSplitScreenWindowingMode()) {
+            if (inAdjacentTask) {
                 hasAdjacentTask = true;
             } else if (hasAdjacentTask && startLayer < SPLIT_DIVIDER_LAYER) {
                 // Task on top of adjacent tasks should be higher than split divider layer so
@@ -1086,7 +1028,7 @@
         // Validate that our desired windowingMode will work under the current conditions.
         // UNDEFINED windowing mode is a valid result and means that the new root task will inherit
         // it's display's windowing mode.
-        windowingMode = validateWindowingMode(windowingMode, r, candidateTask, activityType);
+        windowingMode = validateWindowingMode(windowingMode, r, candidateTask);
         return getOrCreateRootTask(windowingMode, activityType, onTop, candidateTask, sourceTask,
                 options, launchFlags);
     }
@@ -1283,23 +1225,6 @@
                 continue;
             }
 
-            if (currentWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
-                    && candidate == null && rootTask.inSplitScreenPrimaryWindowingMode()) {
-                // If the currently focused root task is in split-screen secondary we save off the
-                // top primary split-screen root task as a candidate for focus because we might
-                // prefer focus to move to an other root task to avoid primary split-screen root
-                // task overlapping with a fullscreen root task when a fullscreen root task is
-                // higher in z than the next split-screen root task. Assistant root task, I am
-                // looking at you...
-                // We only move the focus to the primary-split screen root task if there isn't a
-                // better alternative.
-                candidate = rootTask;
-                continue;
-            }
-            if (candidate != null && rootTask.inSplitScreenSecondaryWindowingMode()) {
-                // Use the candidate root task since we are now at the secondary split-screen.
-                return candidate;
-            }
             return rootTask;
         }
         return candidate;
@@ -1416,75 +1341,18 @@
         return someActivityPaused[0] > 0;
     }
 
-    void onSplitScreenModeDismissed() {
-        // The focused task could be a non-resizeable fullscreen root task that is on top of the
-        // other split-screen tasks, therefore had to dismiss split-screen, make sure the current
-        // focused root task can still be on top after dismissal
-        final Task rootTask = getFocusedRootTask();
-        final Task toTop =
-                rootTask != null && !rootTask.inSplitScreenWindowingMode() ? rootTask : null;
-        onSplitScreenModeDismissed(toTop);
-    }
-
-    void onSplitScreenModeDismissed(Task toTop) {
-        mAtmService.deferWindowLayout();
-        try {
-            moveSplitScreenTasksToFullScreen();
-        } finally {
-            final Task topFullscreenRootTask = toTop != null
-                    ? toTop : getTopRootTaskInWindowingMode(WINDOWING_MODE_FULLSCREEN);
-            final Task rootHomeTask = getOrCreateRootHomeTask();
-            if (rootHomeTask != null && ((topFullscreenRootTask != null && !isTopRootTask(
-                    rootHomeTask)) || toTop != null)) {
-                // Whenever split-screen is dismissed we want the root home task directly behind the
-                // current top fullscreen root task so it shows up when the top root task is
-                // finished. Or, if the caller specified a root task to be on top after
-                // split-screen is dismissed.
-                // TODO: Would be better to use ActivityDisplay.positionChildAt() for this, however
-                // ActivityDisplay doesn't have a direct controller to WM side yet. We can switch
-                // once we have that.
-                rootHomeTask.moveToFront("onSplitScreenModeDismissed");
-                topFullscreenRootTask.moveToFront("onSplitScreenModeDismissed");
-            }
-            mAtmService.continueWindowLayout();
-        }
-    }
-
-    private void moveSplitScreenTasksToFullScreen() {
-        final WindowContainerTransaction wct = new WindowContainerTransaction();
-        mTmpTasks.clear();
-        forAllTasks(task -> {
-            if (task.mCreatedByOrganizer && task.inSplitScreenWindowingMode() && task.hasChild()) {
-                mTmpTasks.add(task);
-            }
-        });
-
-        for (int i = mTmpTasks.size() - 1; i >= 0; i--) {
-            final Task root = mTmpTasks.get(i);
-            for (int j = 0; j < root.getChildCount(); j++) {
-                final WindowContainerToken token =
-                        root.getChildAt(j).mRemoteToken.toWindowContainerToken();
-                wct.reparent(token, null, true /* toTop */);
-                wct.setBounds(token, null);
-            }
-        }
-        mAtmService.mWindowOrganizerController.applyTransaction(wct);
-    }
 
     /**
      * Returns true if the {@param windowingMode} is supported based on other parameters passed in.
      *
      * @param windowingMode       The windowing mode we are checking support for.
      * @param supportsMultiWindow If we should consider support for multi-window mode in general.
-     * @param supportsSplitScreen If we should consider support for split-screen multi-window.
      * @param supportsFreeform    If we should consider support for freeform multi-window.
      * @param supportsPip         If we should consider support for picture-in-picture mutli-window.
-     * @param activityType        The activity type under consideration.
      * @return true if the windowing mode is supported.
      */
     static boolean isWindowingModeSupported(int windowingMode, boolean supportsMultiWindow,
-            boolean supportsSplitScreen, boolean supportsFreeform, boolean supportsPip,
-            int activityType) {
+            boolean supportsFreeform, boolean supportsPip) {
 
         if (windowingMode == WINDOWING_MODE_UNDEFINED
                 || windowingMode == WINDOWING_MODE_FULLSCREEN) {
@@ -1498,12 +1366,6 @@
             return true;
         }
 
-        if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
-                || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
-            return supportsSplitScreen
-                    && WindowConfiguration.supportSplitScreenWindowingMode(activityType);
-        }
-
         if (!supportsFreeform && windowingMode == WINDOWING_MODE_FREEFORM) {
             return false;
         }
@@ -1525,7 +1387,7 @@
      * @return The resolved (not UNDEFINED) windowing-mode that the activity would be in.
      */
     int resolveWindowingMode(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
-            @Nullable Task task, int activityType) {
+            @Nullable Task task) {
 
         // First preference if the windowing mode in the activity options if set.
         int windowingMode = (options != null)
@@ -1545,7 +1407,7 @@
                 windowingMode = getWindowingMode();
             }
         }
-        windowingMode = validateWindowingMode(windowingMode, r, task, activityType);
+        windowingMode = validateWindowingMode(windowingMode, r, task);
         return windowingMode != WINDOWING_MODE_UNDEFINED
                 ? windowingMode : WINDOWING_MODE_FULLSCREEN;
     }
@@ -1557,19 +1419,16 @@
      * @param windowingMode The windowing-mode to validate.
      * @param r             The {@link ActivityRecord} to check against.
      * @param task          The {@link Task} to check against.
-     * @param activityType  An activity type.
      * @return {@code true} if windowingMode is valid, {@code false} otherwise.
      */
-    boolean isValidWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task,
-            int activityType) {
+    boolean isValidWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task
+    ) {
         // Make sure the windowing mode we are trying to use makes sense for what is supported.
         boolean supportsMultiWindow = mAtmService.mSupportsMultiWindow;
-        boolean supportsSplitScreen = mAtmService.mSupportsSplitScreenMultiWindow;
         boolean supportsFreeform = mAtmService.mSupportsFreeformWindowManagement;
         boolean supportsPip = mAtmService.mSupportsPictureInPicture;
         if (supportsMultiWindow) {
             if (task != null) {
-                supportsSplitScreen = task.supportsSplitScreenWindowingModeInDisplayArea(this);
                 supportsFreeform = task.supportsFreeformInDisplayArea(this);
                 supportsMultiWindow = task.supportsMultiWindowInDisplayArea(this)
                         // When the activity needs to be moved to PIP while the Task is not in PIP,
@@ -1577,7 +1436,6 @@
                         // always valid for Task as long as the device supports it.
                         || (windowingMode == WINDOWING_MODE_PINNED && supportsPip);
             } else if (r != null) {
-                supportsSplitScreen = r.supportsSplitScreenWindowingModeInDisplayArea(this);
                 supportsFreeform = r.supportsFreeformInDisplayArea(this);
                 supportsPip = r.supportsPictureInPicture();
                 supportsMultiWindow = r.supportsMultiWindowInDisplayArea(this);
@@ -1585,8 +1443,8 @@
         }
 
         return windowingMode != WINDOWING_MODE_UNDEFINED
-                && isWindowingModeSupported(windowingMode, supportsMultiWindow, supportsSplitScreen,
-                supportsFreeform, supportsPip, activityType);
+                && isWindowingModeSupported(windowingMode, supportsMultiWindow, supportsFreeform,
+                supportsPip);
     }
 
     /**
@@ -1596,20 +1454,10 @@
      * @param windowingMode The windowing-mode to validate.
      * @param r             The {@link ActivityRecord} to check against.
      * @param task          The {@link Task} to check against.
-     * @param activityType  An activity type.
      * @return The provided windowingMode or the closest valid mode which is appropriate.
      */
-    int validateWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task,
-            int activityType) {
-        final boolean inSplitScreenMode = isSplitScreenModeActivated();
-        if (!inSplitScreenMode && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
-            // Switch to the display's windowing mode if we are not in split-screen mode and we are
-            // trying to launch in split-screen secondary.
-            windowingMode = WINDOWING_MODE_UNDEFINED;
-        } else if (inSplitScreenMode && windowingMode == WINDOWING_MODE_UNDEFINED) {
-            windowingMode = WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
-        }
-        if (!isValidWindowingMode(windowingMode, r, task, activityType)) {
+    int validateWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task) {
+        if (!isValidWindowingMode(windowingMode, r, task)) {
             return WINDOWING_MODE_UNDEFINED;
         }
         return windowingMode;
@@ -1774,11 +1622,6 @@
         return homeTask;
     }
 
-    boolean isSplitScreenModeActivated() {
-        Task task = getRootSplitScreenPrimaryTask();
-        return task != null && task.hasChild();
-    }
-
     /**
      * Returns the topmost root task on the display that is compatible with the input windowing
      * mode. Null is no compatible root task on the display.
@@ -1866,8 +1709,7 @@
                 continue;
             }
             final int winMode = s.getWindowingMode();
-            final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN
-                    || winMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+            final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN;
             if (s.shouldBeVisible(null) && isValidWindowingMode) {
                 // Move the provided root task to behind this root task
                 final int position = Math.max(0, rootTaskNdx - 1);
@@ -1882,8 +1724,7 @@
     private Task getBottomMostVisibleRootTask(Task excludeRootTask) {
         return getRootTask(task -> {
             final int winMode = task.getWindowingMode();
-            final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN
-                    || winMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+            final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN;
             return task.shouldBeVisible(null) && isValidWindowingMode;
         }, false /* traverseTopToBottom */);
     }
@@ -2067,20 +1908,11 @@
             numRootTasks = mChildren.size();
         }
 
-        if (lastReparentedRootTask != null) {
-            if (toDisplayArea.isSplitScreenModeActivated()
-                    && !lastReparentedRootTask.supportsSplitScreenWindowingModeInDisplayArea(
-                            toDisplayArea)) {
-                // Dismiss split screen if the last reparented root task doesn't support split mode.
-                mAtmService.getTaskChangeNotificationController()
-                        .notifyActivityDismissingDockedRootTask();
-                toDisplayArea.onSplitScreenModeDismissed(lastReparentedRootTask);
-            } else if (!lastReparentedRootTask.isRootTask()) {
-                // Update focus when the last reparented root task is not a root task anymore.
-                // (For example, if it has been reparented to a split screen root task, move the
-                // focus to the split root task)
-                lastReparentedRootTask.getRootTask().moveToFront("display-removed");
-            }
+        if (lastReparentedRootTask != null && !lastReparentedRootTask.isRootTask()) {
+            // Update focus when the last reparented root task is not a root task anymore.
+            // (For example, if it has been reparented to a split screen root task, move the
+            // focus to the split root task)
+            lastReparentedRootTask.getRootTask().moveToFront("display-removed");
         }
 
         mRemoved = true;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 71a24d7..eb1274c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -8276,8 +8276,7 @@
      */
     void grantInputChannel(Session session, int callingUid, int callingPid, int displayId,
                            SurfaceControl surface, IWindow window, IBinder hostInputToken,
-                           int flags, int privateFlags, int type, IBinder focusGrantToken,
-                           InputChannel outInputChannel) {
+                           int flags, int privateFlags, int type, InputChannel outInputChannel) {
         final InputApplicationHandle applicationHandle;
         final String name;
         final InputChannel clientChannel;
@@ -8285,7 +8284,7 @@
             EmbeddedWindowController.EmbeddedWindow win =
                     new EmbeddedWindowController.EmbeddedWindow(session, this, window,
                             mInputToWindowMap.get(hostInputToken), callingUid, callingPid, type,
-                            displayId, focusGrantToken);
+                            displayId);
             clientChannel = win.openInputChannel();
             mEmbeddedWindowController.add(clientChannel.getToken(), win);
             applicationHandle = win.getApplicationHandle();
@@ -8564,10 +8563,10 @@
         }
     }
 
-    void grantEmbeddedWindowFocus(Session session, IBinder focusToken, boolean grantFocus) {
+    void grantEmbeddedWindowFocus(Session session, IBinder inputToken, boolean grantFocus) {
         synchronized (mGlobalLock) {
             final EmbeddedWindowController.EmbeddedWindow embeddedWindow =
-                    mEmbeddedWindowController.getByFocusToken(focusToken);
+                    mEmbeddedWindowController.get(inputToken);
             if (embeddedWindow == null) {
                 Slog.e(TAG, "Embedded window not found");
                 return;
@@ -8576,11 +8575,6 @@
                 Slog.e(TAG, "Window not in session:" + session);
                 return;
             }
-            IBinder inputToken = embeddedWindow.getInputChannelToken();
-            if (inputToken == null) {
-                Slog.e(TAG, "Focus token found but input channel token not found");
-                return;
-            }
             SurfaceControl.Transaction t = mTransactionFactory.get();
             final int displayId = embeddedWindow.mDisplayId;
             if (grantFocus) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index a228d6a..8864b98 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1731,20 +1731,6 @@
             } else {
                 intersectWithRootTaskBounds = false;
             }
-            if (inSplitScreenPrimaryWindowingMode()) {
-                // If this is in the primary split and the root home task is the top visible task in
-                // the secondary split, it means this is "minimized" and thus must prevent
-                // overlapping with home.
-                // TODO(b/158242495): get rid of this when drag/drop can use surface bounds.
-                final Task rootSecondary =
-                        task.getDisplayArea().getRootSplitScreenSecondaryTask();
-                if (rootSecondary.isActivityTypeHome() || rootSecondary.isActivityTypeRecents()) {
-                    final WindowContainer topTask = rootSecondary.getTopChild();
-                    if (topTask.isVisible()) {
-                        cutRect(mTmpRect, topTask.getBounds());
-                    }
-                }
-            }
         }
 
         bounds.set(mWindowFrames.mFrame);
@@ -4714,14 +4700,6 @@
         if (!isImeLayeringTarget()) {
             return false;
         }
-        // If we are in split screen which case we process the IME at the DisplayContent level to
-        // ensure it is above the docked divider.
-        // i.e. Like {@link DisplayContent.ImeContainer#skipImeWindowsDuringTraversal}, the IME
-        // window will be ignored to traverse when the IME target is still in split-screen mode.
-        if (mDisplayContent.getDefaultTaskDisplayArea().isSplitScreenModeActivated()
-                && getTask() != null) {
-            return false;
-        }
         // Note that we don't process IME window if the IME input target is not on the screen.
         // In case some unexpected IME visibility cases happen like starting the remote
         // animation on the keyguard but seeing the IME window that originally on the app
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 79a980f..95ef5f7 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -145,8 +145,8 @@
         "libutils",
         "libhwui",
         "libbpf_android",
-        "libnetdbpf",
         "libnetdutils",
+        "libnetworkstats",
         "libpsi",
         "libdataloader",
         "libincfs",
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index e0b6273..733cfcd 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -11042,7 +11042,8 @@
 
     @Override
     public int getLogoutUserId() {
-        Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()));
+        Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity())
+                || hasCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS));
 
         return getLogoutUserIdUnchecked();
     }
@@ -11057,16 +11058,7 @@
         }
     }
 
-    @Override
-    public void clearLogoutUser() {
-        CallerIdentity caller = getCallerIdentity();
-        Preconditions.checkCallAuthorization(canManageUsers(caller));
-
-        Slogf.i(LOG_TAG, "Clearing logout user as requested by %s", caller);
-        clearLogoutUserUnchecked();
-    }
-
-    private void clearLogoutUserUnchecked() {
+    private void clearLogoutUser() {
         if (!mInjector.userManagerIsHeadlessSystemUserMode()) return; // ignore
 
         synchronized (getLockObject()) {
@@ -11167,6 +11159,21 @@
             return stopUserUnchecked(callingUserId);
         }
 
+        return logoutUserUnchecked(/* userIdToStop= */ callingUserId);
+    }
+
+    @Override
+    public int logoutUserInternal() {
+        CallerIdentity caller = getCallerIdentity();
+        Preconditions.checkCallAuthorization(
+                canManageUsers(caller) || hasCallingOrSelfPermission(permission.CREATE_USERS));
+
+        int result = logoutUserUnchecked(getCurrentForegroundUserId());
+        Slogf.d(LOG_TAG, "logout called by uid %d. Result: %d", caller.getUid(), result);
+        return result;
+    }
+
+    private int logoutUserUnchecked(@UserIdInt int userIdToStop) {
         int logoutUserId = getLogoutUserIdUnchecked();
         if (logoutUserId == UserHandle.USER_NULL) {
             // Could happen on devices using headless system user mode when called before calling
@@ -11182,7 +11189,7 @@
                 // This should never happen as target user is determined by getPreviousUserId()
                 return UserManager.USER_OPERATION_ERROR_UNKNOWN;
             }
-            clearLogoutUserUnchecked();
+            clearLogoutUser();
         } catch (RemoteException e) {
             // Same process, should not happen.
             return UserManager.USER_OPERATION_ERROR_UNKNOWN;
@@ -11190,7 +11197,7 @@
             mInjector.binderRestoreCallingIdentity(id);
         }
 
-        return stopUserUnchecked(callingUserId);
+        return stopUserUnchecked(userIdToStop);
     }
 
     private int stopUserUnchecked(@UserIdInt int userId) {
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index 677f0f6..36c37c4 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -541,14 +541,11 @@
                     | ActivityManager.UID_OBSERVER_CAPABILITY
         };
         final IUidObserver[] observers = new IUidObserver.Stub[changesToObserve.length];
-        doReturn(Process.myUid()).when(sPackageManagerInternal)
-                .getPackageUid(mContext.getOpPackageName(), 0 /* flags */, mContext.getUserId());
         for (int i = 0; i < observers.length; ++i) {
             observers[i] = mock(IUidObserver.Stub.class);
             when(observers[i].asBinder()).thenReturn((IBinder) observers[i]);
             mAms.registerUidObserver(observers[i], changesToObserve[i] /* which */,
-                    ActivityManager.PROCESS_STATE_UNKNOWN /* cutpoint */,
-                    mContext.getOpPackageName());
+                    ActivityManager.PROCESS_STATE_UNKNOWN /* cutpoint */, null /* caller */);
 
             // When we invoke AMS.registerUidObserver, there are some interactions with observers[i]
             // mock in RemoteCallbackList class. We don't want to test those interactions and
@@ -677,12 +674,10 @@
         mockNoteOperation();
 
         final IUidObserver observer = mock(IUidObserver.Stub.class);
+
         when(observer.asBinder()).thenReturn((IBinder) observer);
-        doReturn(Process.myUid()).when(sPackageManagerInternal)
-                .getPackageUid(mContext.getOpPackageName(), 0 /* flags */, mContext.getUserId());
         mAms.registerUidObserver(observer, ActivityManager.UID_OBSERVER_PROCSTATE /* which */,
-                ActivityManager.PROCESS_STATE_SERVICE /* cutpoint */,
-                mContext.getOpPackageName());
+                ActivityManager.PROCESS_STATE_SERVICE /* cutpoint */, null /* callingPackage */);
         // When we invoke AMS.registerUidObserver, there are some interactions with observer
         // mock in RemoteCallbackList class. We don't want to test those interactions and
         // at the same time, we don't want those to interfere with verifyNoMoreInteractions.
@@ -776,9 +771,7 @@
 
         final IUidObserver observer = mock(IUidObserver.Stub.class);
         when(observer.asBinder()).thenReturn((IBinder) observer);
-        doReturn(Process.myUid()).when(sPackageManagerInternal)
-                .getPackageUid(mContext.getOpPackageName(), 0 /* flags */, mContext.getUserId());
-        mAms.registerUidObserver(observer, 0, 0, mContext.getOpPackageName());
+        mAms.registerUidObserver(observer, 0, 0, null);
         // Verify that when observers are registered, then validateUids is correctly updated.
         addPendingUidChanges(pendingItemsForUids);
         mAms.mUidObserverController.dispatchUidsChanged();
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
index c675726..24a4751 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
@@ -393,7 +393,8 @@
 
         // Create an idle mode bms
         // This will fail if it tries to fetch the wrong configuration.
-        BrightnessMappingStrategy bms = BrightnessMappingStrategy.createForIdleMode(res, ddc);
+        BrightnessMappingStrategy bms = BrightnessMappingStrategy.createForIdleMode(res, ddc,
+                null);
         assertNotNull("BrightnessMappingStrategy should not be null", bms);
 
         // Ensure that the config is the one we set
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index eaa271a..1fb5898 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -33,6 +33,7 @@
 import static org.mockito.Mockito.when;
 
 import android.app.PropertyInvalidatedCache;
+import android.companion.virtual.IVirtualDevice;
 import android.compat.testing.PlatformCompatChangeRule;
 import android.content.Context;
 import android.content.ContextWrapper;
@@ -73,6 +74,7 @@
 
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
+import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
 import com.android.server.display.DisplayManagerService.SyncRoot;
 import com.android.server.lights.LightsManager;
 import com.android.server.sensors.SensorManagerInternal;
@@ -167,6 +169,7 @@
             };
 
     @Mock InputManagerInternal mMockInputManagerInternal;
+    @Mock VirtualDeviceManagerInternal mMockVirtualDeviceManagerInternal;
     @Mock IVirtualDisplayCallback.Stub mMockAppToken;
     @Mock IVirtualDisplayCallback.Stub mMockAppToken2;
     @Mock WindowManagerInternal mMockWindowManagerInternal;
@@ -187,6 +190,9 @@
         LocalServices.addService(LightsManager.class, mMockLightsManager);
         LocalServices.removeServiceForTest(SensorManagerInternal.class);
         LocalServices.addService(SensorManagerInternal.class, mMockSensorManagerInternal);
+        LocalServices.removeServiceForTest(VirtualDeviceManagerInternal.class);
+        LocalServices.addService(
+                VirtualDeviceManagerInternal.class, mMockVirtualDeviceManagerInternal);
 
         mContext = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
         mDeviceConfig = new FakeDeviceConfigInterface();
@@ -661,6 +667,101 @@
     }
 
     /**
+     * Tests that specifying VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP is allowed when the permission
+     * ADD_TRUSTED_DISPLAY is granted.
+     */
+    @Test
+    public void testOwnDisplayGroup_allowCreationWithAddTrustedDisplayPermission() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        registerDefaultDisplays(displayManager);
+
+        DisplayManagerService.BinderService bs = displayManager.new BinderService();
+        when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
+
+        when(mContext.checkCallingPermission(ADD_TRUSTED_DISPLAY)).thenReturn(
+                PackageManager.PERMISSION_GRANTED);
+
+        final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
+                VIRTUAL_DISPLAY_NAME, 600, 800, 320);
+        builder.setFlags(DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP);
+        builder.setUniqueId("uniqueId --- OWN_DISPLAY_GROUP");
+
+        int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
+                null /* projection */, null /* virtualDeviceToken */, PACKAGE_NAME);
+        displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
+        displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
+        DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId);
+        assertNotNull(ddi);
+        assertNotEquals(0, ddi.flags & DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP);
+    }
+
+    /**
+     * Tests that specifying VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP is blocked when the permission
+     * ADD_TRUSTED_DISPLAY is denied.
+     */
+    @Test
+    public void testOwnDisplayGroup_withoutAddTrustedDisplayPermission_throwsSecurityException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        registerDefaultDisplays(displayManager);
+
+        DisplayManagerService.BinderService bs = displayManager.new BinderService();
+        when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
+
+        when(mContext.checkCallingPermission(ADD_TRUSTED_DISPLAY)).thenReturn(
+                PackageManager.PERMISSION_DENIED);
+
+        final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
+                VIRTUAL_DISPLAY_NAME, 600, 800, 320);
+        builder.setFlags(DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP);
+        builder.setUniqueId("uniqueId --- OWN_DISPLAY_GROUP");
+
+        try {
+            bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
+                    null /* projection */, null /* virtualDeviceToken */, PACKAGE_NAME);
+            fail("Creating virtual display with VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP without "
+                    + "ADD_TRUSTED_DISPLAY permission should throw SecurityException.");
+        } catch (SecurityException e) {
+            // SecurityException is expected
+        }
+    }
+
+    /**
+     * Tests that specifying VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP is allowed when called with
+     * a virtual device, even if ADD_TRUSTED_DISPLAY is not granted.
+     */
+    @Test
+    public void testOwnDisplayGroup_allowCreationWithVirtualDevice() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        registerDefaultDisplays(displayManager);
+
+        DisplayManagerService.BinderService bs = displayManager.new BinderService();
+        when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
+
+        when(mContext.checkCallingPermission(ADD_TRUSTED_DISPLAY)).thenReturn(
+                PackageManager.PERMISSION_DENIED);
+
+        final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
+                VIRTUAL_DISPLAY_NAME, 600, 800, 320);
+        builder.setFlags(DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP);
+        builder.setUniqueId("uniqueId --- OWN_DISPLAY_GROUP");
+
+        IVirtualDevice virtualDevice = mock(IVirtualDevice.class);
+        when(mMockVirtualDeviceManagerInternal.isValidVirtualDevice(virtualDevice))
+            .thenReturn(true);
+
+        int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
+                null /* projection */, virtualDevice /* virtualDeviceToken */, PACKAGE_NAME);
+        displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
+        displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
+        DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId);
+        assertNotNull(ddi);
+        assertNotEquals(0, ddi.flags & DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP);
+    }
+
+    /**
      * Tests that there is a display change notification if the frame rate override
      * list is updated.
      */
diff --git a/services/tests/servicestests/src/com/android/server/display/whitebalance/AmbientLuxTest.java b/services/tests/servicestests/src/com/android/server/display/whitebalance/AmbientLuxTest.java
index 2565ae3..0f3742f 100644
--- a/services/tests/servicestests/src/com/android/server/display/whitebalance/AmbientLuxTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/whitebalance/AmbientLuxTest.java
@@ -21,6 +21,7 @@
 import static org.mockito.Matchers.anyLong;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
@@ -37,7 +38,9 @@
 import androidx.test.InstrumentationRegistry;
 
 import com.android.internal.R;
+import com.android.server.LocalServices;
 import com.android.server.display.TestUtils;
+import com.android.server.display.color.ColorDisplayService;
 import com.android.server.display.utils.AmbientFilter;
 import com.android.server.display.utils.AmbientFilterStubber;
 
@@ -75,6 +78,7 @@
     @Mock private TypedArray mHighLightBiases;
     @Mock private TypedArray mAmbientColorTemperatures;
     @Mock private TypedArray mDisplayColorTemperatures;
+    @Mock private ColorDisplayService.ColorDisplayServiceInternal mColorDisplayServiceInternalMock;
 
     @Before
     public void setUp() throws Exception {
@@ -120,6 +124,18 @@
                 R.array.config_displayWhiteBalanceHighLightAmbientBiases))
                 .thenReturn(mHighLightBiases);
         mockThrottler();
+        LocalServices.removeServiceForTest(ColorDisplayService.ColorDisplayServiceInternal.class);
+        LocalServices.addService(ColorDisplayService.ColorDisplayServiceInternal.class,
+                mColorDisplayServiceInternalMock);
+    }
+
+    @Test
+    public void testCalculateAdjustedBrightnessNits() {
+        doReturn(0.9f).when(mColorDisplayServiceInternalMock).getDisplayWhiteBalanceLuminance();
+        DisplayWhiteBalanceController controller =
+                DisplayWhiteBalanceFactory.create(mHandler, mSensorManagerMock, mResourcesSpy);
+        final float adjustedNits = controller.calculateAdjustedBrightnessNits(500f);
+        assertEquals(/* expected= */ 550f, adjustedNits, /* delta= */ 0.001);
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerGroupTest.java b/services/tests/servicestests/src/com/android/server/power/PowerGroupTest.java
new file mode 100644
index 0000000..c59b58d
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/power/PowerGroupTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.power;
+
+
+import static android.os.PowerManager.GO_TO_SLEEP_REASON_APPLICATION;
+import static android.os.PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN;
+import static android.os.PowerManager.GO_TO_SLEEP_REASON_TIMEOUT;
+import static android.os.PowerManager.WAKE_REASON_GESTURE;
+import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP;
+import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE;
+import static android.os.PowerManagerInternal.WAKEFULNESS_DOZING;
+import static android.os.PowerManagerInternal.WAKEFULNESS_DREAMING;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.verify;
+
+import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests for {@link com.android.server.power.PowerGroup}.
+ *
+ * Build/Install/Run:
+ *  atest FrameworksServicesTests:PowerManagerServiceTest
+ */
+public class PowerGroupTest {
+
+    private static final int GROUP_ID = 0;
+    private static final long TIMESTAMP_CREATE = 1;
+    private static final long TIMESTAMP1 = 999;
+    private static final long TIMESTAMP2 = TIMESTAMP1 + 10;
+    private static final long TIMESTAMP3 = TIMESTAMP2 + 10;
+    private static final int UID = 11;
+
+    private PowerGroup mPowerGroup;
+    @Mock
+    private PowerGroup.PowerGroupListener mWakefulnessCallbackMock;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mPowerGroup = new PowerGroup(GROUP_ID, mWakefulnessCallbackMock, new DisplayPowerRequest(),
+                WAKEFULNESS_AWAKE, /* ready= */ true, /* supportsSandman= */true, TIMESTAMP_CREATE);
+    }
+
+    @Test
+    public void testDreamPowerGroupTriggersOnWakefulnessChangedCallback() {
+        mPowerGroup.dreamLocked(TIMESTAMP1, UID);
+        verify(mWakefulnessCallbackMock).onWakefulnessChangedLocked(eq(GROUP_ID),
+                eq(WAKEFULNESS_DREAMING), eq(TIMESTAMP1), eq(GO_TO_SLEEP_REASON_APPLICATION),
+                eq(UID), /* opUid= */anyInt(), /* opPackageName= */ isNull(), /* details= */
+                isNull());
+    }
+
+    @Test
+    public void testLastWakeAndSleepTimeIsUpdated() {
+        assertThat(mPowerGroup.getLastWakeTimeLocked()).isEqualTo(TIMESTAMP_CREATE);
+        assertThat(mPowerGroup.getLastSleepTimeLocked()).isEqualTo(TIMESTAMP_CREATE);
+
+        // Verify that the transition to WAKEFULNESS_DOZING updates the last sleep time
+        String details = "PowerGroup1 Timeout";
+        mPowerGroup.setWakefulnessLocked(WAKEFULNESS_DOZING, TIMESTAMP1, UID,
+                GO_TO_SLEEP_REASON_TIMEOUT, /* opUid= */ 0, /* opPackageName= */ null, details);
+        assertThat(mPowerGroup.getLastSleepTimeLocked()).isEqualTo(TIMESTAMP1);
+        assertThat(mPowerGroup.getLastWakeTimeLocked()).isEqualTo(TIMESTAMP_CREATE);
+        assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING);
+        verify(mWakefulnessCallbackMock).onWakefulnessChangedLocked(eq(GROUP_ID),
+                eq(WAKEFULNESS_DOZING), eq(TIMESTAMP1), eq(GO_TO_SLEEP_REASON_TIMEOUT),
+                eq(UID), /* opUid= */anyInt(), /* opPackageName= */ isNull(), eq(details));
+
+        // Verify that the transition to WAKEFULNESS_ASLEEP after dozing does not update the last
+        // wake or sleep time
+        mPowerGroup.setWakefulnessLocked(WAKEFULNESS_ASLEEP, TIMESTAMP2, UID,
+                GO_TO_SLEEP_REASON_DEVICE_ADMIN, /* opUid= */ 0, /* opPackageName= */ null,
+                details);
+        assertThat(mPowerGroup.getLastSleepTimeLocked()).isEqualTo(TIMESTAMP1);
+        assertThat(mPowerGroup.getLastWakeTimeLocked()).isEqualTo(TIMESTAMP_CREATE);
+        assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
+        verify(mWakefulnessCallbackMock).onWakefulnessChangedLocked(eq(GROUP_ID),
+                eq(WAKEFULNESS_ASLEEP), eq(TIMESTAMP2), eq(GO_TO_SLEEP_REASON_DEVICE_ADMIN),
+                eq(UID), /* opUid= */anyInt(), /* opPackageName= */ isNull(), eq(details));
+
+        // Verify that waking up the power group only updates the last wake time
+        details = "PowerGroup1 Gesture";
+        mPowerGroup.setWakefulnessLocked(WAKEFULNESS_AWAKE, TIMESTAMP2, UID,
+                WAKE_REASON_GESTURE, /* opUid= */ 0, /* opPackageName= */ null, details);
+        assertThat(mPowerGroup.getLastWakeTimeLocked()).isEqualTo(TIMESTAMP2);
+        assertThat(mPowerGroup.getLastSleepTimeLocked()).isEqualTo(TIMESTAMP1);
+        assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        verify(mWakefulnessCallbackMock).onWakefulnessChangedLocked(eq(GROUP_ID),
+                eq(WAKEFULNESS_AWAKE), eq(TIMESTAMP2), eq(WAKE_REASON_GESTURE),
+                eq(UID), /* opUid= */ anyInt(), /* opPackageName= */ isNull(), eq(details));
+
+        // Verify that a transition to WAKEFULNESS_ASLEEP from an interactive state updates the last
+        // sleep time
+        mPowerGroup.setWakefulnessLocked(WAKEFULNESS_ASLEEP, TIMESTAMP3, UID,
+                GO_TO_SLEEP_REASON_DEVICE_ADMIN, /* opUid= */ 0, /* opPackageName= */ null,
+                details);
+        assertThat(mPowerGroup.getLastSleepTimeLocked()).isEqualTo(TIMESTAMP3);
+        assertThat(mPowerGroup.getLastWakeTimeLocked()).isEqualTo(TIMESTAMP2);
+        assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
+        verify(mWakefulnessCallbackMock).onWakefulnessChangedLocked(eq(GROUP_ID),
+                eq(WAKEFULNESS_ASLEEP), eq(TIMESTAMP3), eq(GO_TO_SLEEP_REASON_DEVICE_ADMIN),
+                eq(UID), /* opUid= */anyInt(), /* opPackageName= */ isNull(), eq(details));
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index c832a3e..d35c679 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -111,6 +111,7 @@
  * Build/Install/Run:
  *  atest FrameworksServicesTests:PowerManagerServiceTest
  */
+@SuppressWarnings("GuardedBy")
 public class PowerManagerServiceTest {
     private static final String SYSTEM_PROPERTY_QUIESCENT = "ro.boot.quiescent";
     private static final String SYSTEM_PROPERTY_REBOOT_REASON = "sys.boot.reason";
@@ -437,7 +438,7 @@
     @Test
     public void testWakefulnessAwake_InitialValue() {
         createService();
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
     }
 
     @Test
@@ -445,12 +446,12 @@
         createService();
         // Start with AWAKE state
         startSystem();
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
 
         // Take a nap and verify.
         mService.getBinderServiceInstance().goToSleep(mClock.now(),
                 PowerManager.GO_TO_SLEEP_REASON_APPLICATION, PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
     }
 
     @Test
@@ -467,21 +468,21 @@
         int flags = PowerManager.FULL_WAKE_LOCK;
         mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
                 null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
         mService.getBinderServiceInstance().releaseWakeLock(token, 0 /* flags */);
 
         // Ensure that the flag does *NOT* work with a partial wake lock.
         flags = PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP;
         mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
                 null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
         mService.getBinderServiceInstance().releaseWakeLock(token, 0 /* flags */);
 
         // Verify that flag forces a wakeup when paired to a FULL_WAKE_LOCK
         flags = PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP;
         mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
                 null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
         mService.getBinderServiceInstance().releaseWakeLock(token, 0 /* flags */);
     }
 
@@ -492,7 +493,7 @@
         forceSleep();
         mService.getBinderServiceInstance().wakeUp(mClock.now(),
                 PowerManager.WAKE_REASON_UNKNOWN, "testing IPowerManager.wakeUp()", "pkg.name");
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
     }
 
     /**
@@ -511,7 +512,7 @@
                 .thenReturn(false);
         mService.readConfigurationLocked();
         setPluggedIn(true);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
         when(mResourcesSpy.getBoolean(com.android.internal.R.bool.config_unplugTurnsOnScreen))
                 .thenReturn(true);
         mService.readConfigurationLocked();
@@ -526,20 +527,20 @@
         when(mWirelessChargerDetectorMock.update(true /* isPowered */,
                 BatteryManager.BATTERY_PLUGGED_WIRELESS)).thenReturn(false);
         setPluggedIn(true);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
 
         // Test 3:
         // Do not wake up if the phone is being REMOVED from a wireless charger
         when(mBatteryManagerInternalMock.getPlugType()).thenReturn(0);
         setPluggedIn(false);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
 
         // Test 4:
         // Do not wake if we are dreaming.
         forceAwake();  // Needs to be awake first before it can dream.
         forceDream();
         setPluggedIn(true);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING);
         forceSleep();
 
         // Test 5:
@@ -552,7 +553,7 @@
                 com.android.internal.R.bool.config_allowTheaterModeWakeFromUnplug))
                 .thenReturn(false);
         setPluggedIn(false);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
         Settings.Global.putInt(
                 mContextSpy.getContentResolver(), Settings.Global.THEATER_MODE_ON, 0);
         mUserSwitchedReceiver.onReceive(mContextSpy, new Intent(Intent.ACTION_USER_SWITCHED));
@@ -565,14 +566,14 @@
         forceAwake();
         forceDozing();
         setPluggedIn(true);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING);
 
         // Test 7:
         // Finally, take away all the factors above and ensure the device wakes up!
         forceAwake();
         forceSleep();
         setPluggedIn(false);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
     }
 
     @Test
@@ -580,12 +581,12 @@
         createService();
         // Start with AWAKE state
         startSystem();
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
 
         // Take a nap and verify.
         mService.getBinderServiceInstance().goToSleep(mClock.now(),
                 PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING);
     }
 
     @Test
@@ -616,12 +617,12 @@
         mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
 
         // Verify that we start awake
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
 
         // Grab the wakefulness value when PowerManager finally calls into the
         // native component to actually perform the suspend.
         when(mNativeWrapperMock.nativeForceSuspend()).then(inv -> {
-            assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
+            assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
             return true;
         });
 
@@ -629,7 +630,7 @@
         assertThat(retval).isTrue();
 
         // Still asleep when the function returns.
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
     }
 
     @Test
@@ -662,7 +663,7 @@
         mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
 
         // Verify that we start awake
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
 
         // Create a wakelock
         mService.getBinderServiceInstance().acquireWakeLock(new Binder(), flags, tag, pkg,
@@ -718,7 +719,7 @@
 
         // Start with AWAKE state
         startSystem();
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
         assertTrue(isAcquired[0]);
 
         // Take a nap and verify we no longer hold the blocker
@@ -728,7 +729,7 @@
         when(mDreamManagerInternalMock.isDreaming()).thenReturn(true);
         mService.getBinderServiceInstance().goToSleep(mClock.now(),
                 PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING);
         assertFalse(isAcquired[0]);
 
         // Override the display state by DreamManager and verify is reacquires the blocker.
@@ -841,9 +842,9 @@
         verify(mInattentiveSleepWarningControllerMock, atLeastOnce()).show();
         when(mInattentiveSleepWarningControllerMock.isShown()).thenReturn(true);
         advanceTime(70);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
         forceAwake();
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
         verify(mInattentiveSleepWarningControllerMock, atLeastOnce()).dismiss(false);
     }
 
@@ -862,7 +863,7 @@
         createService();
         startSystem();
         advanceTime(20);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
         assertThat(mService.getBinderServiceInstance().getLastSleepReason()).isEqualTo(
                 PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE);
     }
@@ -882,9 +883,9 @@
                 PowerManager.SCREEN_BRIGHT_WAKE_LOCK, tag, pkg,
                 null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
 
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
         advanceTime(60);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
         assertThat(mService.getBinderServiceInstance().getLastSleepReason()).isEqualTo(
                 PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE);
     }
@@ -912,7 +913,7 @@
         mService.getBinderServiceInstance().releaseWakeLock(token, 0 /* flags */);
 
         advanceTime(520);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
         assertThat(mService.getBinderServiceInstance().getLastSleepReason()).isEqualTo(
                 PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE);
     }
@@ -934,7 +935,7 @@
                 PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS);
 
         advanceTime(520);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
         assertThat(mService.getBinderServiceInstance().getLastSleepReason()).isEqualTo(
                 PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE);
     }
@@ -955,7 +956,7 @@
                 PowerManager.USER_ACTIVITY_EVENT_OTHER, 0 /* flags */);
 
         advanceTime(520);
-        assertThat(mService.getWakefulnessLocked()).isNotEqualTo(WAKEFULNESS_ASLEEP);
+        assertThat(mService.getGlobalWakefulnessLocked()).isNotEqualTo(WAKEFULNESS_ASLEEP);
     }
 
     @Test
@@ -984,14 +985,14 @@
                 PowerManager.SCREEN_BRIGHT_WAKE_LOCK, tag, pkg,
                 null /* workSource */, null /* historyTag */, Display.DEFAULT_DISPLAY);
 
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
         assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
                 WAKEFULNESS_AWAKE);
         assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo(
                 WAKEFULNESS_AWAKE);
 
         advanceTime(15000);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
         assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
                 WAKEFULNESS_AWAKE);
         assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo(
@@ -1024,14 +1025,14 @@
                 PowerManager.SCREEN_BRIGHT_WAKE_LOCK, tag, pkg,
                 null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
 
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
         assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
                 WAKEFULNESS_AWAKE);
         assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo(
                 WAKEFULNESS_AWAKE);
 
         advanceTime(15000);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
         assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
                 WAKEFULNESS_AWAKE);
         assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo(
@@ -1069,14 +1070,14 @@
                 WAKEFULNESS_AWAKE);
         assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo(
                 WAKEFULNESS_AWAKE);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
 
         listener.get().onDisplayGroupRemoved(nonDefaultDisplayGroupId);
 
         advanceTime(15000);
         assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
                 WAKEFULNESS_DOZING);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING);
     }
 
     @Test
@@ -1084,7 +1085,7 @@
         createService();
         startSystem();
 
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
         verify(mNotifierMock, never()).onWakefulnessChangeStarted(anyInt(), anyInt(), anyLong());
     }
 
@@ -1103,7 +1104,7 @@
         createService();
         startSystem();
 
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
         verify(mNotifierMock).onWakefulnessChangeStarted(eq(WAKEFULNESS_ASLEEP), anyInt(),
                 anyLong());
     }
@@ -1137,7 +1138,7 @@
                 PowerManager.WAKE_REASON_UNKNOWN, "testing IPowerManager.wakeUp()", "pkg.name");
 
         mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
         assertThat(mService.getDesiredScreenPolicyLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
                 DisplayPowerRequest.POLICY_BRIGHT);
     }
@@ -1418,23 +1419,23 @@
         startSystem();
         listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId);
 
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
 
         mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_ASLEEP, 0, 0, 0, 0,
                 null, null);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
 
         mService.setWakefulnessLocked(nonDefaultDisplayGroupId, WAKEFULNESS_ASLEEP, 0, 0, 0, 0,
                 null, null);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
 
         mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_AWAKE, 0, 0, 0, 0,
                 null, null);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
     }
 
     @Test
-    public void testMultiDisplay_addDisplayGroup_preservesWakefulness() {
+    public void testMultiDisplay_addDisplayGroup_wakesDeviceUp() {
         final int nonDefaultDisplayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1;
         final AtomicReference<DisplayManagerInternal.DisplayGroupListener> listener =
                 new AtomicReference<>();
@@ -1446,15 +1447,15 @@
         createService();
         startSystem();
 
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
 
         mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_ASLEEP, 0, 0, 0, 0,
                 null, null);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
 
         listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId);
 
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
     }
 
     @Test
@@ -1471,18 +1472,79 @@
         startSystem();
         listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId);
 
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
 
         mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_ASLEEP, 0, 0, 0, 0,
                 null, null);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
 
         listener.get().onDisplayGroupRemoved(nonDefaultDisplayGroupId);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
 
         mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_AWAKE, 0, 0, 0, 0,
                 null, null);
-        assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+    }
+
+    @Test
+    public void testMultiDisplay_updatesLastGlobalWakeTime() {
+        final int nonDefaultPowerGroupId = Display.DEFAULT_DISPLAY_GROUP + 1;
+        final AtomicReference<DisplayManagerInternal.DisplayGroupListener> listener =
+                new AtomicReference<>();
+        long eventTime1 = 10;
+        long eventTime2 = eventTime1 + 1;
+        long eventTime3 = eventTime2 + 1;
+        long eventTime4 = eventTime3 + 1;
+        doAnswer((Answer<Void>) invocation -> {
+            listener.set(invocation.getArgument(0));
+            return null;
+        }).when(mDisplayManagerInternalMock).registerDisplayGroupListener(any());
+
+        createService();
+        startSystem();
+        listener.get().onDisplayGroupAdded(nonDefaultPowerGroupId);
+
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+
+        mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_DOZING, eventTime1,
+                0, PowerManager.GO_TO_SLEEP_REASON_INATTENTIVE, 0, null, null);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+
+        mService.setWakefulnessLocked(nonDefaultPowerGroupId, WAKEFULNESS_DOZING, eventTime2,
+                0, PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0, null, null);
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING);
+        assertThat(mService.getBinderServiceInstance().getLastSleepReason()).isEqualTo(
+                PowerManager.GO_TO_SLEEP_REASON_APPLICATION);
+
+        mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_AWAKE,
+                eventTime3, /* uid= */ 0, PowerManager.WAKE_REASON_PLUGGED_IN, /* opUid= */
+                0, /* opPackageName= */ null, /* details= */ null);
+        PowerManager.WakeData wakeData = mService.getLocalServiceInstance().getLastWakeup();
+        assertThat(wakeData.wakeTime).isEqualTo(eventTime3);
+        assertThat(wakeData.wakeReason).isEqualTo(PowerManager.WAKE_REASON_PLUGGED_IN);
+        assertThat(wakeData.sleepDuration).isEqualTo(eventTime3 - eventTime2);
+
+        // The global wake time and reason as well as sleep duration shouldn't change when another
+        // PowerGroup wakes up.
+        mService.setWakefulnessLocked(nonDefaultPowerGroupId, WAKEFULNESS_AWAKE,
+                eventTime4, /* uid= */ 0, PowerManager.WAKE_REASON_CAMERA_LAUNCH, /* opUid= */
+                0, /* opPackageName= */ null, /* details= */ null);
+        assertThat(wakeData.wakeTime).isEqualTo(eventTime3);
+        assertThat(wakeData.wakeReason).isEqualTo(PowerManager.WAKE_REASON_PLUGGED_IN);
+        assertThat(wakeData.sleepDuration).isEqualTo(eventTime3 - eventTime2);
+    }
+
+    @Test
+    public void testLastSleepTime_notUpdatedWhenDreaming() {
+        createService();
+        startSystem();
+
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+        PowerManager.WakeData initialWakeData = mService.getLocalServiceInstance().getLastWakeup();
+
+        forceDream();
+        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING);
+        assertThat(mService.getLocalServiceInstance().getLastWakeup()).isEqualTo(initialWakeData);
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
index 5dd44ff..020d9f8 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
@@ -16,6 +16,9 @@
 
 package com.android.server.vibrator;
 
+import static android.os.VibrationEffect.VibrationParameter.targetAmplitude;
+import static android.os.VibrationEffect.VibrationParameter.targetFrequency;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
@@ -69,6 +72,7 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
+import java.time.Duration;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
@@ -525,7 +529,8 @@
                 .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f)
                 .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f)
                 .addEffect(VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
-                .addEffect(VibrationEffect.get(VibrationEffect.EFFECT_CLICK), /* delay= */ 100)
+                .addOffDuration(Duration.ofMillis(100))
+                .addEffect(VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
                 .compose();
         VibrationThread thread = startThreadAndDispatcher(vibrationId, effect);
         waitForCompletion(thread);
@@ -558,11 +563,12 @@
                 0.5f /* 100Hz*/, 1 /* 150Hz */, 0.6f /* 200Hz */);
 
         long vibrationId = 1;
-        VibrationEffect effect = VibrationEffect.startWaveform()
-                .addStep(1, 10)
-                .addRamp(0, 20)
-                .addStep(0.8f, 100, 30)
-                .addRamp(0.6f, 200, 40)
+        VibrationEffect effect = VibrationEffect.startWaveform(targetAmplitude(1))
+                .addSustain(Duration.ofMillis(10))
+                .addTransition(Duration.ofMillis(20), targetAmplitude(0))
+                .addTransition(Duration.ZERO, targetAmplitude(0.8f), targetFrequency(100))
+                .addSustain(Duration.ofMillis(30))
+                .addTransition(Duration.ofMillis(40), targetAmplitude(0.6f), targetFrequency(200))
                 .build();
         VibrationThread thread = startThreadAndDispatcher(vibrationId, effect);
         waitForCompletion(thread);
@@ -595,11 +601,12 @@
         fakeVibrator.setPwleSizeMax(2);
 
         long vibrationId = 1;
-        VibrationEffect effect = VibrationEffect.startWaveform()
-                .addStep(1, 10)
-                .addRamp(0, 20)
-                .addStep(0.8f, 10, 30)
-                .addRamp(0.6f, 100, 40)
+        VibrationEffect effect = VibrationEffect.startWaveform(targetAmplitude(1))
+                .addSustain(Duration.ofMillis(10))
+                .addTransition(Duration.ofMillis(20), targetAmplitude(0))
+                .addTransition(Duration.ZERO, targetAmplitude(0.8f), targetFrequency(100))
+                .addSustain(Duration.ofMillis(30))
+                .addTransition(Duration.ofMillis(40), targetAmplitude(0.6f), targetFrequency(200))
                 .build();
         VibrationThread thread = startThreadAndDispatcher(vibrationId, effect);
         waitForCompletion(thread);
@@ -1261,7 +1268,9 @@
         fakeVibrator.setPwleSizeMax(2);
 
         long vibrationId = 1;
-        VibrationEffect effect = VibrationEffect.startWaveform().addRamp(1, 1).build();
+        VibrationEffect effect = VibrationEffect.startWaveform()
+                .addTransition(Duration.ofMillis(1), targetAmplitude(1))
+                .build();
         VibrationThread thread = startThreadAndDispatcher(vibrationId, effect);
         waitForCompletion(thread);
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index fdc8982..c58bf3b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -340,7 +340,7 @@
             doReturn(stack).when(mRootWindowContainer)
                     .getLaunchRootTask(any(), any(), any(), anyBoolean());
             doReturn(stack).when(mRootWindowContainer).getLaunchRootTask(any(), any(), any(), any(),
-                    anyBoolean(), any(), anyInt(), anyInt(), anyInt());
+                    anyBoolean(), any(), anyInt());
         }
 
         // Set up mock package manager internal and make sure no unmocked methods are called
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 f4abf88..ee17f52 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -25,7 +25,6 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
 import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.Display.TYPE_VIRTUAL;
 import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
@@ -935,39 +934,6 @@
         assertEquals(infoFake1.activityInfo.name, resolvedInfo.first.name);
     }
 
-    /**
-     * Test that {@link RootWindowContainer#getLaunchRootTask} with the real caller id will get the
-     * expected root task when requesting the activity launch on the secondary display.
-     */
-    @Test
-    public void testGetLaunchRootTaskWithRealCallerId() {
-        // Create a non-system owned virtual display.
-        final TestDisplayContent secondaryDisplay =
-                new TestDisplayContent.Builder(mAtm, 1000, 1500)
-                        .setType(TYPE_VIRTUAL).setOwnerUid(100).build();
-
-        // Create an activity with specify the original launch pid / uid.
-        final ActivityRecord r = new ActivityBuilder(mAtm).setLaunchedFromPid(200)
-                .setLaunchedFromUid(200).build();
-
-        // Simulate ActivityStarter to find a launch root task for requesting the activity to launch
-        // on the secondary display with realCallerId.
-        final ActivityOptions options = ActivityOptions.makeBasic();
-        options.setLaunchDisplayId(secondaryDisplay.mDisplayId);
-        options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
-        doReturn(true).when(mSupervisor).canPlaceEntityOnDisplay(secondaryDisplay.mDisplayId,
-                300 /* test realCallerPid */, 300 /* test realCallerUid */, r.info);
-        final Task result = mRootWindowContainer.getLaunchRootTask(r, options,
-                null /* task */, null /* sourceTask */, true /* onTop */, null /* launchParams */,
-                0 /* launchFlags */, 300 /* test realCallerPid */,
-                300 /* test realCallerUid */);
-
-        // Assert that the root task is returned as expected.
-        assertNotNull(result);
-        assertEquals("The display ID of the root task should same as secondary display ",
-                secondaryDisplay.mDisplayId, result.getDisplayId());
-    }
-
     @Test
     public void testGetValidLaunchRootTaskOnDisplayWithCandidateRootTask() {
         // Create a root task with an activity on secondary display.
diff --git a/services/usb/java/com/android/server/usb/UsbPortManager.java b/services/usb/java/com/android/server/usb/UsbPortManager.java
index 65b79bf..d0825ba 100644
--- a/services/usb/java/com/android/server/usb/UsbPortManager.java
+++ b/services/usb/java/com/android/server/usb/UsbPortManager.java
@@ -503,6 +503,49 @@
             return HAL_MODE_DFP;
     }
 
+    /**
+     * Reset USB port.
+     *
+     * @param portId port identifier.
+     */
+    public boolean resetUsbPort(@NonNull String portId, int transactionId,
+            @NonNull IUsbOperationInternal callback, IndentingPrintWriter pw) {
+        synchronized (mLock) {
+            Objects.requireNonNull(callback);
+            Objects.requireNonNull(portId);
+            final PortInfo portInfo = mPorts.get(portId);
+            if (portInfo == null) {
+                logAndPrint(Log.ERROR, pw, "resetUsbPort: No such port: " + portId
+                    + " opId:" + transactionId);
+                try {
+                    callback.onOperationComplete(
+                            USB_OPERATION_ERROR_PORT_MISMATCH);
+                } catch (RemoteException e) {
+                    logAndPrintException(pw,
+                            "resetUsbPort: Failed to call OperationComplete. opId:"
+                            + transactionId, e);
+                }
+                return false;
+            }
+
+            try {
+                try {
+                    return mUsbPortHal.resetUsbPort(portId, transactionId, callback);
+                } catch (Exception e) {
+                    logAndPrintException(pw,
+                        "reseetUsbPort: Failed to resetUsbPort. opId:"
+                        + transactionId , e);
+                    callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
+                }
+            } catch (RemoteException e) {
+                logAndPrintException(pw,
+                        "resetUsbPort: Failed to call onOperationComplete. opId:"
+                        + transactionId, e);
+            }
+            return false;
+        }
+    }
+
     public void setPortRoles(String portId, int newPowerRole, int newDataRole,
             IndentingPrintWriter pw) {
         synchronized (mLock) {
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index 88ffc7d61..f3308bb 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -680,6 +680,35 @@
     }
 
     @Override
+    public boolean resetUsbPort(String portId, int operationId,
+            IUsbOperationInternal callback) {
+        Objects.requireNonNull(portId, "resetUsbPort: portId must not be null. opId:"
+                + operationId);
+        Objects.requireNonNull(callback, "resetUsbPort: callback must not be null. opId:"
+                + operationId);
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
+
+        final long ident = Binder.clearCallingIdentity();
+        boolean wait;
+
+        try {
+            if (mPortManager != null) {
+                wait = mPortManager.resetUsbPort(portId, operationId, callback, null);
+            } else {
+                wait = false;
+                try {
+                    callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "resetUsbPort: Failed to call onOperationComplete", e);
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+        return wait;
+    }
+
+    @Override
     public List<ParcelableUsbPort> getPorts() {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
 
diff --git a/services/usb/java/com/android/server/usb/hal/port/UsbPortAidl.java b/services/usb/java/com/android/server/usb/hal/port/UsbPortAidl.java
index 5582600..f468db3 100644
--- a/services/usb/java/com/android/server/usb/hal/port/UsbPortAidl.java
+++ b/services/usb/java/com/android/server/usb/hal/port/UsbPortAidl.java
@@ -238,6 +238,50 @@
     }
 
     @Override
+    public boolean resetUsbPort(String portName, long operationID,
+            IUsbOperationInternal callback) {
+        Objects.requireNonNull(portName);
+        Objects.requireNonNull(callback);
+        long key = operationID;
+        synchronized (mLock) {
+            try {
+                if (mProxy == null) {
+                    logAndPrint(Log.ERROR, mPw,
+                            "resetUsbPort: Proxy is null. Retry !opID:"
+                            + operationID);
+                    callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
+                    return false;
+                }
+                while (sCallbacks.get(key) != null) {
+                    key = ThreadLocalRandom.current().nextInt();
+                }
+                if (key != operationID) {
+                    logAndPrint(Log.INFO, mPw, "resetUsbPort: operationID exists ! opID:"
+                            + operationID + " key:" + key);
+                }
+                try {
+                    sCallbacks.put(operationID, callback);
+                    mProxy.resetUsbPort(portName, operationID);
+                } catch (RemoteException e) {
+                    logAndPrintException(mPw,
+                            "resetUsbPort: Failed to resetUsbPort: portID="
+                            + portName + "opId:" + operationID, e);
+                    callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
+                    sCallbacks.remove(key);
+                    return false;
+                }
+            } catch (RemoteException e) {
+                logAndPrintException(mPw,
+                        "resetUsbPort: Failed to call onOperationComplete portID="
+                        + portName + "opID:" + operationID, e);
+                sCallbacks.remove(key);
+                return false;
+            }
+            return true;
+        }
+    }
+
+    @Override
     public boolean enableUsbData(String portName, boolean enable, long operationID,
             IUsbOperationInternal callback) {
         Objects.requireNonNull(portName);
@@ -605,5 +649,27 @@
                         e);
             }
         }
+
+        @Override
+        public void notifyResetUsbPortStatus(String portName, int retval,
+                long operationID) {
+            if (retval == Status.SUCCESS) {
+                UsbPortManager.logAndPrint(Log.INFO, mPw, "notifyResetUsbPortStatus:"
+                        + portName + ": opID:" + operationID);
+            } else {
+                UsbPortManager.logAndPrint(Log.ERROR, mPw, portName
+                        + "notifyEnableUsbDataStatus: opID:"
+                        + operationID + " failed. err:" + retval);
+            }
+            try {
+                sCallbacks.get(operationID).onOperationComplete(retval == Status.SUCCESS
+                        ? USB_OPERATION_SUCCESS
+                        : USB_OPERATION_ERROR_INTERNAL);
+            } catch (RemoteException e) {
+                logAndPrintException(mPw,
+                        "notifyResetUsbPortStatus: Failed to call onOperationComplete",
+                        e);
+            }
+        }
     }
 }
diff --git a/services/usb/java/com/android/server/usb/hal/port/UsbPortHal.java b/services/usb/java/com/android/server/usb/hal/port/UsbPortHal.java
index abfdd6f..4fa296d 100644
--- a/services/usb/java/com/android/server/usb/hal/port/UsbPortHal.java
+++ b/services/usb/java/com/android/server/usb/hal/port/UsbPortHal.java
@@ -193,4 +193,18 @@
      */
     public void enableLimitPowerTransfer(String portName, boolean limit, long transactionId,
             IUsbOperationInternal callback);
+
+    /**
+     * Invoked to reset UsbData on the specified port.
+     *
+     * @param portName Port Identifier.
+     * @param transactionId Used for tracking the current request and is passed down to the HAL
+     *                      implementation as needed.
+     * @param callback callback object to be invoked to invoke the status of the operation upon
+     *                 completion.
+     * @param callback callback object to be invoked to invoke the status of the operation upon
+     *                 completion.
+     */
+    public boolean resetUsbPort(String portName, long transactionId,
+            IUsbOperationInternal callback);
 }
diff --git a/services/usb/java/com/android/server/usb/hal/port/UsbPortHidl.java b/services/usb/java/com/android/server/usb/hal/port/UsbPortHidl.java
index c1d7635..64e8adc 100644
--- a/services/usb/java/com/android/server/usb/hal/port/UsbPortHidl.java
+++ b/services/usb/java/com/android/server/usb/hal/port/UsbPortHidl.java
@@ -318,6 +318,19 @@
     }
 
     @Override
+    public boolean resetUsbPort(String portName, long transactionId,
+            IUsbOperationInternal callback) {
+        try {
+            callback.onOperationComplete(USB_OPERATION_ERROR_NOT_SUPPORTED);
+        } catch (RemoteException e) {
+            logAndPrintException(mPw, "Failed to call onOperationComplete. opID:"
+                    + transactionId
+                    + " portId:" + portName, e);
+        }
+        return false;
+    }
+
+    @Override
     public boolean enableUsbData(String portName, boolean enable, long transactionId,
             IUsbOperationInternal callback) {
         int halVersion;
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index e332d3f..ec18c6a 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -380,7 +380,45 @@
      */
     public static final int CAPABILITY_CALL_COMPOSER = 0x8000;
 
-    /* NEXT CAPABILITY: 0x10000 */
+    /**
+     * Flag indicating that this {@link PhoneAccount} provides SIM-based voice calls, potentially as
+     * an over-the-top solution such as wi-fi calling.
+     *
+     * <p>Similar to {@link #CAPABILITY_SUPPORTS_VIDEO_CALLING}, this capability indicates this
+     * {@link PhoneAccount} has the ability to make voice calls (but not necessarily at this time).
+     * Whether this {@link PhoneAccount} can make a voice call is ultimately controlled by {@link
+     * #CAPABILITY_VOICE_CALLING_AVAILABLE}, which indicates whether this {@link PhoneAccount} is
+     * currently capable of making a voice call. Consider a case where, for example, a {@link
+     * PhoneAccount} supports making voice calls (e.g. {@link
+     * #CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS}), but a current lack of network connectivity
+     * prevents voice calls from being made (e.g. {@link #CAPABILITY_VOICE_CALLING_AVAILABLE}).
+     *
+     * <p>In order to declare this capability, this {@link PhoneAccount} must also declare {@link
+     * #CAPABILITY_SIM_SUBSCRIPTION} or {@link #CAPABILITY_CONNECTION_MANAGER} and satisfy the
+     * associated requirements.
+     *
+     * @see #CAPABILITY_VOICE_CALLING_AVAILABLE
+     * @see #getCapabilities
+     */
+    public static final int CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS = 0x10000;
+
+    /**
+     * Flag indicating that this {@link PhoneAccount} is <em>currently</em> able to place SIM-based
+     * voice calls, similar to {@link #CAPABILITY_VIDEO_CALLING}.
+     *
+     * <p>See also {@link #CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS}, which indicates whether
+     * the {@code PhoneAccount} supports placing SIM-based voice calls or not.
+     *
+     * <p>In order to declare this capability, this {@link PhoneAccount} must also declare {@link
+     * #CAPABILITY_SIM_SUBSCRIPTION} or {@link #CAPABILITY_CONNECTION_MANAGER} and satisfy the
+     * associated requirements.
+     *
+     * @see #CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS
+     * @see #getCapabilities
+     */
+    public static final int CAPABILITY_VOICE_CALLING_AVAILABLE = 0x20000;
+
+    /* NEXT CAPABILITY: 0x40000 */
 
     /**
      * URI scheme for telephone number URIs.
@@ -1102,14 +1140,20 @@
             sb.append("SimSub ");
         }
         if (hasCapabilities(CAPABILITY_RTT)) {
-            sb.append("Rtt");
+            sb.append("Rtt ");
         }
         if (hasCapabilities(CAPABILITY_ADHOC_CONFERENCE_CALLING)) {
-            sb.append("AdhocConf");
+            sb.append("AdhocConf ");
         }
         if (hasCapabilities(CAPABILITY_CALL_COMPOSER)) {
             sb.append("CallComposer ");
         }
+        if (hasCapabilities(CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS)) {
+            sb.append("SuppVoice ");
+        }
+        if (hasCapabilities(CAPABILITY_VOICE_CALLING_AVAILABLE)) {
+            sb.append("Voice ");
+        }
         return sb.toString();
     }
 
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index d5c846d..7ba4b11 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -5186,6 +5186,20 @@
         public static final int E911_RTP_INACTIVITY_ON_CONNECTED = 4;
 
         /**
+         * List of different RAT technologies on which IMS
+         * is supported.
+         *
+         * <p>Possible values are,
+         * {@link AccessNetworkConstants.AccessNetworkType#NGRAN}
+         * {@link AccessNetworkConstants.AccessNetworkType#EUTRAN}
+         * {@link AccessNetworkConstants.AccessNetworkType#IWLAN}
+         * {@link AccessNetworkConstants.AccessNetworkType#UTRAN}
+         * {@link AccessNetworkConstants.AccessNetworkType#GERAN}
+         */
+        public static final String KEY_SUPPORTED_RATS_INT_ARRAY =
+                KEY_PREFIX + "supported_rats_int_array";
+
+        /**
          * A bundle which specifies the MMTEL capability and registration technology
          * that requires provisioning. If a tuple is not present, the
          * framework will not require that the tuple requires provisioning before
@@ -5375,6 +5389,13 @@
                     new int[] {
                         GEOLOCATION_PIDF_FOR_EMERGENCY_ON_WIFI
                     });
+            defaults.putIntArray(
+                    KEY_SUPPORTED_RATS_INT_ARRAY,
+                    new int[] {
+                        AccessNetworkType.NGRAN,
+                        AccessNetworkType.EUTRAN,
+                        AccessNetworkType.IWLAN
+                    });
 
             defaults.putString(KEY_PHONE_CONTEXT_DOMAIN_NAME_STRING, "");
             defaults.putString(KEY_IMS_USER_AGENT_STRING,
@@ -5499,6 +5520,44 @@
         public static final String KEY_SESSION_REFRESHER_TYPE_INT =
                 KEY_PREFIX + "session_refresher_type_int";
 
+
+        /** @hide */
+        @IntDef({
+            SESSION_PRIVACY_TYPE_HEADER,
+            SESSION_PRIVACY_TYPE_NONE,
+            SESSION_PRIVACY_TYPE_ID
+        })
+
+        public @interface SessionPrivacyType {}
+
+        /**
+         * Session privacy type is HEADER as per RFC 3323 Section 4.2.
+         */
+        public static final int SESSION_PRIVACY_TYPE_HEADER = 0;
+
+        /**
+         * Session privacy type is NONE as per RFC 3323 Section 4.2.
+         */
+        public static final int SESSION_PRIVACY_TYPE_NONE = 1;
+
+        /**
+         * Session privacy type is ID as per RFC 3325 Section 9.3.
+         */
+        public static final int SESSION_PRIVACY_TYPE_ID = 2;
+
+        /**
+         * Specify the session privacy type.
+         *
+         * <p>Reference: RFC 3323 Section 4.2, RFC 3325 Section 9.3.
+         *
+         * <p>Possible values are,
+         * {@link #SESSION_PRIVACY_TYPE_HEADER},
+         * {@link #SESSION_PRIVACY_TYPE_NONE},
+         * {@link #SESSION_PRIVACY_TYPE_ID}
+         */
+        public static final String KEY_SESSION_PRIVACY_TYPE_INT =
+                KEY_PREFIX + "session_privacy_type_int";
+
         /**
          * Flag indicating whether PRACK must be enabled for all 18x messages.
          *
@@ -6320,6 +6379,7 @@
             defaults.putBoolean(KEY_VOICE_ON_DEFAULT_BEARER_SUPPORTED_BOOL, false);
 
             defaults.putInt(KEY_SESSION_REFRESHER_TYPE_INT, SESSION_REFRESHER_TYPE_UNKNOWN);
+            defaults.putInt(KEY_SESSION_PRIVACY_TYPE_INT, SESSION_PRIVACY_TYPE_HEADER);
             defaults.putInt(KEY_SESSION_REFRESH_METHOD_INT,
                             SESSION_REFRESH_METHOD_UPDATE_PREFERRED);
             defaults.putInt(KEY_CONFERENCE_SUBSCRIBE_TYPE_INT,
@@ -6567,22 +6627,6 @@
                 KEY_PREFIX + "text_rr_bandwidth_bps_int";
 
         /**
-         * List of various reasons for RTT call to end due to
-         * media inactivity.
-         *
-         * <p>Possible values are,
-         * <UL>
-         *     <LI>{@link Ims#RTCP_INACTIVITY_ON_HOLD}</LI>
-         *     <LI>{@link Ims#RTCP_INACTIVITY_ON_CONNECTED}</LI>
-         *     <LI>{@link Ims#RTP_INACTIVITY_ON_CONNECTED}</LI>
-         *     <LI>{@link Ims#E911_RTCP_INACTIVITY_ON_CONNECTED}</LI>
-         *     <LI>{@link Ims#E911_RTP_INACTIVITY_ON_CONNECTED}</LI>
-         * </UL>
-         */
-        public static final String KEY_TEXT_INACTIVITY_CALL_END_REASONS_INT_ARRAY =
-                KEY_PREFIX + "text_inactivity_call_end_reasons_int_array";
-
-        /**
          * Specifies the Text Codec capability.
          *
          * <p>Possible keys in this bundle are,
@@ -6617,13 +6661,6 @@
             defaults.putInt(KEY_TEXT_RS_BANDWIDTH_BPS_INT, 100);
             defaults.putInt(KEY_TEXT_RR_BANDWIDTH_BPS_INT, 300);
 
-            defaults.putIntArray(
-                    KEY_TEXT_INACTIVITY_CALL_END_REASONS_INT_ARRAY,
-                    new int[] {
-                        Ims.RTCP_INACTIVITY_ON_CONNECTED,
-                        Ims.RTP_INACTIVITY_ON_CONNECTED
-                    });
-
             PersistableBundle text_codec_capability_payload_types = new PersistableBundle();
 
             text_codec_capability_payload_types.putInt(
@@ -6707,6 +6744,13 @@
         public static final String KEY_EMERGENCY_REGISTRATION_TIMER_MILLIS_INT =
                 KEY_PREFIX + "emergency_registration_timer_millis_int";
 
+        /**
+         * This setting will be specify the wait time for refreshing
+         * geolocation information before dialing emergency call.
+         */
+        public static final String KEY_REFRESH_GEOLOCATION_TIMEOUT_MILLIS_INT =
+                KEY_PREFIX + "refresh_geolocation_timeout_millis_int";
+
         private static PersistableBundle getDefaults() {
             PersistableBundle defaults = new PersistableBundle();
             defaults.putBoolean(KEY_RETRY_EMERGENCY_ON_IMS_PDN_BOOL, false);
@@ -6721,6 +6765,7 @@
                     });
 
             defaults.putInt(KEY_EMERGENCY_REGISTRATION_TIMER_MILLIS_INT, 20000);
+            defaults.putInt(KEY_REFRESH_GEOLOCATION_TIMEOUT_MILLIS_INT, 5000);
 
             return defaults;
         }
@@ -7035,6 +7080,17 @@
                 KEY_PREFIX + "ut_requires_ims_registration_bool";
 
         /**
+         * Flag that controls whether XCAP over UT is supported
+         * when on roaming network.
+         *
+         * <p>If {@code true}: XCAP over UT is supported when on
+         * roaming network.
+         * {@code false} otherwise.
+         */
+        public static final String KEY_UT_SUPPORTED_WHEN_ROAMING_BOOL =
+                KEY_PREFIX + "ut_supported_when_roaming_bool";
+
+        /**
          * Flag that controls whether Circuit Switched Fallback (CSFB)
          * option is available when XCAP over UT fails.
          *
@@ -7385,6 +7441,7 @@
             defaults.putBoolean(KEY_USE_CSFB_ON_XCAP_OVER_UT_FAILURE_BOOL, true);
             defaults.putBoolean(KEY_UT_SUPPORTED_WHEN_PS_DATA_OFF_BOOL, true);
             defaults.putBoolean(KEY_NETWORK_INITIATED_USSD_OVER_IMS_SUPPORTED_BOOL, true);
+            defaults.putBoolean(KEY_UT_SUPPORTED_WHEN_ROAMING_BOOL, true);
 
             defaults.putInt(KEY_UT_IPTYPE_HOME_INT, ApnSetting.PROTOCOL_IPV4V6);
             defaults.putInt(KEY_UT_IPTYPE_ROAMING_INT, ApnSetting.PROTOCOL_IPV4V6);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 536517c..edb817e 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -150,7 +150,6 @@
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
-
 /**
  * Provides access to information about the telephony services on
  * the device. Applications can use the methods in this class to
@@ -16805,4 +16804,37 @@
         }
         mTelephonyRegistryMgr.removeCarrierPrivilegesListener(listener);
     }
+
+    /**
+     * Sets a voice service state override from telecom based on the current {@link PhoneAccount}s
+     * registered. See {@link PhoneAccount#CAPABILITY_VOICE_CALLING_AVAILABLE}.
+     *
+     * <p>Currently, this API is only called to indicate over-the-top voice calling capability of
+     * the SIM call manager, which will get merged into {@link ServiceState#getState} and propagated
+     * to interested callers via {@link #getServiceState} and {@link
+     * TelephonyCallback.ServiceStateListener}.
+     *
+     * <p>If callers are truly interested in the actual device <-> tower connection status and not
+     * an overall "device can make voice calls" boolean, they can use {@link
+     * ServiceState#getNetworkRegistrationInfo} to check CS registration state.
+     *
+     * <p>TODO(b/215240050) In the future, this API will be removed and replaced with a new superset
+     * API to disentangle the "true" {@link ServiceState} meaning of "this is the connection status
+     * to the tower" from IMS registration state and over-the-top voice calling capabilities.
+     *
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(Manifest.permission.BIND_TELECOM_CONNECTION_SERVICE)
+    public void setVoiceServiceStateOverride(boolean hasService) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony == null) {
+                throw new IllegalStateException("Telephony service is null");
+            }
+            telephony.setVoiceServiceStateOverride(getSubId(), hasService, getOpPackageName());
+        } catch (RemoteException ex) {
+            ex.rethrowAsRuntimeException();
+        }
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index bce7a24..dc96b35 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2543,4 +2543,10 @@
      * registration technology specified, false if it is not required.
      */
     boolean isRcsProvisioningRequiredForCapability(int subId, int capability, int tech);
+
+    /**
+     * Sets a voice service state from telecom based on the current PhoneAccounts registered. See
+     * PhoneAccount#CAPABILITY_VOICE_CALLING_AVAILABLE.
+     */
+    void setVoiceServiceStateOverride(int subId, boolean hasService, String callingPackage);
 }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
index 8de38f6..294a220 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
@@ -27,6 +27,7 @@
 import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import org.junit.Assume.assumeFalse
+import org.junit.Assume.assumeTrue
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -91,6 +92,13 @@
         super.statusBarLayerRotatesScales()
     }
 
+    @FlakyTest(bugId = 214452854)
+    @Test
+    fun statusBarLayerRotatesScales_shellTransit() {
+        assumeTrue(isShellTransitionsEnabled)
+        super.statusBarLayerRotatesScales()
+    }
+
     /** {@inheritDoc} */
     @Presubmit
     @Test
@@ -100,6 +108,13 @@
         super.launcherLayerReplacesApp()
     }
 
+    @FlakyTest(bugId = 214452854)
+    @Test
+    fun launcherLayerReplacesApp_shellTransit() {
+        assumeTrue(isShellTransitionsEnabled)
+        super.launcherLayerReplacesApp()
+    }
+
     /** {@inheritDoc} */
     @Presubmit
     @Test
@@ -109,6 +124,13 @@
         super.entireScreenCovered()
     }
 
+    @FlakyTest(bugId = 214452854)
+    @Test
+    fun entireScreenCovered_shellTransit() {
+        assumeTrue(isShellTransitionsEnabled)
+        super.entireScreenCovered()
+    }
+
     companion object {
         /**
          * Creates the test configurations.
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
index d960e94..519bd56 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
@@ -26,6 +26,7 @@
 import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import org.junit.Assume.assumeFalse
+import org.junit.Assume.assumeTrue
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -90,6 +91,13 @@
         super.statusBarLayerRotatesScales()
     }
 
+    @FlakyTest(bugId = 214452854)
+    @Test
+    fun statusBarLayerRotatesScales_shellTransit() {
+        assumeTrue(isShellTransitionsEnabled)
+        super.statusBarLayerRotatesScales()
+    }
+
     /** {@inheritDoc} */
     @Presubmit
     @Test
@@ -99,6 +107,13 @@
         super.launcherLayerReplacesApp()
     }
 
+    @FlakyTest(bugId = 214452854)
+    @Test
+    fun launcherLayerReplacesApp_shellTransit() {
+        assumeTrue(isShellTransitionsEnabled)
+        super.launcherLayerReplacesApp()
+    }
+
     /** {@inheritDoc} */
     @Presubmit
     @Test
@@ -108,6 +123,13 @@
         super.entireScreenCovered()
     }
 
+    @FlakyTest(bugId = 214452854)
+    @Test
+    fun entireScreenCovered_shellTransit() {
+        assumeTrue(isShellTransitionsEnabled)
+        super.entireScreenCovered()
+    }
+
     /** {@inheritDoc} */
     @Presubmit
     @Test
@@ -117,6 +139,13 @@
         super.visibleLayersShownMoreThanOneConsecutiveEntry()
     }
 
+    @FlakyTest(bugId = 214452854)
+    @Test
+    fun visibleLayersShownMoreThanOneConsecutiveEntry_shellTransit() {
+        assumeTrue(isShellTransitionsEnabled)
+        super.visibleLayersShownMoreThanOneConsecutiveEntry()
+    }
+
     companion object {
         /**
          * Creates the test configurations.
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
index 01fce05..42941c2 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
@@ -40,6 +40,7 @@
 import com.android.server.wm.traces.common.FlickerComponentName
 import com.android.server.wm.traces.common.Rect
 import org.junit.Assume
+import org.junit.Before
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -62,7 +63,7 @@
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 @Group1
-class QuickSwitchBetweenTwoAppsForwardTest(private val testSpec: FlickerTestParameter) {
+open class QuickSwitchBetweenTwoAppsForwardTest(private val testSpec: FlickerTestParameter) {
     private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
 
     private val testApp1 = SimpleAppHelper(instrumentation)
@@ -85,9 +86,9 @@
                         ?: error("Display not found")
 
                     // Swipe right from bottom to quick switch back
-                    // NOTE: We don't perform an edge-to-edge swipe but instead only swipe in the middle
-                    // as to not accidentally trigger a swipe back or forward action which would result
-                    // in the same behavior but not testing quick swap.
+                    // NOTE: We don't perform an edge-to-edge swipe but instead only swipe in the
+                    // middle as to not accidentally trigger a swipe back or forward action which
+                    // would result in the same behavior but not testing quick swap.
                     device.swipe(
                             startDisplayBounds.right / 3,
                             startDisplayBounds.bottom,
@@ -126,15 +127,19 @@
         }
     }
 
+    @Before
+    open fun setup() {
+        // This test doesn't work in shell transitions because of b/213867585
+        Assume.assumeFalse(isShellTransitionsEnabled)
+    }
+
     /**
      * Checks that the transition starts with [testApp1]'s windows filling/covering exactly the
      * entirety of the display.
      */
     @Presubmit
     @Test
-    fun startsWithApp1WindowsCoverFullScreen() {
-        // This test doesn't work in shell transitions because of b/209936664
-        Assume.assumeFalse(isShellTransitionsEnabled)
+    open fun startsWithApp1WindowsCoverFullScreen() {
         testSpec.assertWmStart {
             this.frameRegion(testApp1.component, FlickerComponentName.LETTERBOX)
                 .coversExactly(startDisplayBounds)
@@ -147,9 +152,7 @@
      */
     @Presubmit
     @Test
-    fun startsWithApp1LayersCoverFullScreen() {
-        // This test doesn't work in shell transitions because of b/209936664
-        Assume.assumeFalse(isShellTransitionsEnabled)
+    open fun startsWithApp1LayersCoverFullScreen() {
         testSpec.assertLayersStart {
             this.visibleRegion(testApp1.component).coversExactly(startDisplayBounds)
         }
@@ -160,23 +163,19 @@
      */
     @Presubmit
     @Test
-    fun startsWithApp1WindowBeingOnTop() {
-        // This test doesn't work in shell transitions because of b/209936664
-        Assume.assumeFalse(isShellTransitionsEnabled)
+    open fun startsWithApp1WindowBeingOnTop() {
         testSpec.assertWmStart {
             this.isAppWindowOnTop(testApp1.component)
         }
     }
 
     /**
-     * Checks that [testApp2] windows fill the entire screen (i.e. is "fullscreen") at the end of the
-     * transition once we have fully quick switched from [testApp1] back to the [testApp2].
+     * Checks that [testApp2] windows fill the entire screen (i.e. is "fullscreen") at the end of
+     * the transition once we have fully quick switched from [testApp1] back to the [testApp2].
      */
     @Presubmit
     @Test
-    fun endsWithApp2WindowsCoveringFullScreen() {
-        // This test doesn't work in shell transitions because of b/209936664
-        Assume.assumeFalse(isShellTransitionsEnabled)
+    open fun endsWithApp2WindowsCoveringFullScreen() {
         testSpec.assertWmEnd {
             this.frameRegion(testApp2.component).coversExactly(startDisplayBounds)
         }
@@ -188,9 +187,7 @@
      */
     @Presubmit
     @Test
-    fun endsWithApp2LayersCoveringFullScreen() {
-        // This test doesn't work in shell transitions because of b/209936664
-        Assume.assumeFalse(isShellTransitionsEnabled)
+    open fun endsWithApp2LayersCoveringFullScreen() {
         testSpec.assertLayersEnd {
             this.visibleRegion(testApp2.component, FlickerComponentName.LETTERBOX)
                 .coversExactly(startDisplayBounds)
@@ -198,14 +195,12 @@
     }
 
     /**
-     * Checks that [testApp2] is the top window at the end of the transition once we have fully quick
-     * switched from [testApp1] back to the [testApp2].
+     * Checks that [testApp2] is the top window at the end of the transition once we have fully
+     * quick switched from [testApp1] back to the [testApp2].
      */
     @Presubmit
     @Test
-    fun endsWithApp2BeingOnTop() {
-        // This test doesn't work in shell transitions because of b/209936664
-        Assume.assumeFalse(isShellTransitionsEnabled)
+    open fun endsWithApp2BeingOnTop() {
         testSpec.assertWmEnd {
             this.isAppWindowOnTop(testApp2.component)
         }
@@ -217,9 +212,7 @@
      */
     @Presubmit
     @Test
-    fun app2WindowBecomesAndStaysVisible() {
-        // This test doesn't work in shell transitions because of b/209936664
-        Assume.assumeFalse(isShellTransitionsEnabled)
+    open fun app2WindowBecomesAndStaysVisible() {
         testSpec.assertWm {
             this.isAppWindowInvisible(testApp2.component)
                     .then()
@@ -235,9 +228,7 @@
      */
     @Presubmit
     @Test
-    fun app2LayerBecomesAndStaysVisible() {
-        // This test doesn't work in shell transitions because of b/209936664
-        Assume.assumeFalse(isShellTransitionsEnabled)
+    open fun app2LayerBecomesAndStaysVisible() {
         testSpec.assertLayers {
             this.isInvisible(testApp2.component)
                     .then()
@@ -251,9 +242,7 @@
      */
     @Presubmit
     @Test
-    fun app1WindowBecomesAndStaysInvisible() {
-        // This test doesn't work in shell transitions because of b/209936664
-        Assume.assumeFalse(isShellTransitionsEnabled)
+    open fun app1WindowBecomesAndStaysInvisible() {
         testSpec.assertWm {
             this.isAppWindowVisible(testApp1.component)
                     .then()
@@ -267,9 +256,7 @@
      */
     @Presubmit
     @Test
-    fun app1LayerBecomesAndStaysInvisible() {
-        // This test doesn't work in shell transitions because of b/209936664
-        Assume.assumeFalse(isShellTransitionsEnabled)
+    open fun app1LayerBecomesAndStaysInvisible() {
         testSpec.assertLayers {
             this.isVisible(testApp1.component)
                     .then()
@@ -284,9 +271,7 @@
      */
     @Presubmit
     @Test
-    fun app2WindowIsVisibleOnceApp1WindowIsInvisible() {
-        // This test doesn't work in shell transitions because of b/209936664
-        Assume.assumeFalse(isShellTransitionsEnabled)
+    open fun app2WindowIsVisibleOnceApp1WindowIsInvisible() {
         testSpec.assertWm {
             this.isAppWindowVisible(testApp1.component)
                     .then()
@@ -305,9 +290,7 @@
      */
     @Presubmit
     @Test
-    fun app2LayerIsVisibleOnceApp1LayerIsInvisible() {
-        // This test doesn't work in shell transitions because of b/209936664
-        Assume.assumeFalse(isShellTransitionsEnabled)
+    open fun app2LayerIsVisibleOnceApp1LayerIsInvisible() {
         testSpec.assertLayers {
             this.isVisible(testApp1.component)
                     .then()
@@ -324,9 +307,7 @@
      */
     @Presubmit
     @Test
-    fun navBarWindowIsAlwaysVisible() {
-        // This test doesn't work in shell transitions because of b/209936664
-        Assume.assumeFalse(isShellTransitionsEnabled)
+    open fun navBarWindowIsAlwaysVisible() {
         testSpec.navBarWindowIsVisible()
     }
 
@@ -335,9 +316,7 @@
      */
     @Presubmit
     @Test
-    fun navBarLayerAlwaysIsVisible() {
-        // This test doesn't work in shell transitions because of b/209936664
-        Assume.assumeFalse(isShellTransitionsEnabled)
+    open fun navBarLayerAlwaysIsVisible() {
         testSpec.navBarLayerIsVisible()
     }
 
@@ -348,9 +327,7 @@
      */
     @Presubmit
     @Test
-    fun navbarIsAlwaysInRightPosition() {
-        // This test doesn't work in shell transitions because of b/209936664
-        Assume.assumeFalse(isShellTransitionsEnabled)
+    open fun navbarIsAlwaysInRightPosition() {
         testSpec.navBarLayerRotatesAndScales()
     }
 
@@ -359,9 +336,7 @@
      */
     @Presubmit
     @Test
-    fun statusBarWindowIsAlwaysVisible() {
-        // This test doesn't work in shell transitions because of b/209936664
-        Assume.assumeFalse(isShellTransitionsEnabled)
+    open fun statusBarWindowIsAlwaysVisible() {
         testSpec.statusBarWindowIsVisible()
     }
 
@@ -370,9 +345,7 @@
      */
     @Presubmit
     @Test
-    fun statusBarLayerIsAlwaysVisible() {
-        // This test doesn't work in shell transitions because of b/209936664
-        Assume.assumeFalse(isShellTransitionsEnabled)
+    open fun statusBarLayerIsAlwaysVisible() {
         testSpec.statusBarLayerIsVisible()
     }
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTestShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTestShellTransit.kt
new file mode 100644
index 0000000..49b9733
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTestShellTransit.kt
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2021 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.wm.flicker.quickswitch
+
+import android.platform.test.annotations.RequiresDevice
+import androidx.test.filters.FlakyTest
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.annotation.Group1
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
+import org.junit.Assume
+import org.junit.Before
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test quick switching back to previous app from last opened app
+ *
+ * To run this test: `atest FlickerTests:QuickSwitchBetweenTwoAppsForwardTestShellTransit`
+ *
+ * Actions:
+ *     Launch an app [testApp1]
+ *     Launch another app [testApp2]
+ *     Swipe right from the bottom of the screen to quick switch back to the first app [testApp1]
+ *     Swipe left from the bottom of the screen to quick switch forward to the second app [testApp2]
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Group1
+class QuickSwitchBetweenTwoAppsForwardTestShellTransit(private val testSpec: FlickerTestParameter)
+    : QuickSwitchBetweenTwoAppsForwardTest(testSpec) {
+
+    @Before
+    override fun setup() {
+        // This test class should be removed after b/213867585 is fixed.
+        Assume.assumeTrue(isShellTransitionsEnabled)
+    }
+
+    /** {@inheritDoc}  */
+    @FlakyTest(bugId = 214452854)
+    @Test
+    override fun startsWithApp1WindowsCoverFullScreen() =
+            super.startsWithApp1WindowsCoverFullScreen()
+
+    /** {@inheritDoc}  */
+    @FlakyTest(bugId = 214452854)
+    @Test
+    override fun startsWithApp1LayersCoverFullScreen() = super.startsWithApp1LayersCoverFullScreen()
+
+    /** {@inheritDoc}  */
+    @FlakyTest(bugId = 214452854)
+    @Test
+    override fun startsWithApp1WindowBeingOnTop() = super.startsWithApp1WindowBeingOnTop()
+
+    /** {@inheritDoc}  */
+    @FlakyTest(bugId = 214452854)
+    @Test
+    override fun endsWithApp2WindowsCoveringFullScreen() =
+            super.endsWithApp2WindowsCoveringFullScreen()
+
+    /** {@inheritDoc}  */
+    @FlakyTest(bugId = 214452854)
+    @Test
+    override fun endsWithApp2LayersCoveringFullScreen() =
+            super.endsWithApp2LayersCoveringFullScreen()
+
+    /** {@inheritDoc}  */
+    @FlakyTest(bugId = 214452854)
+    @Test
+    override fun endsWithApp2BeingOnTop() = super.endsWithApp2BeingOnTop()
+
+    /** {@inheritDoc}  */
+    @FlakyTest(bugId = 214452854)
+    @Test
+    override fun app2WindowBecomesAndStaysVisible() = super.app2WindowBecomesAndStaysVisible()
+
+    /** {@inheritDoc}  */
+    @FlakyTest(bugId = 214452854)
+    @Test
+    override fun app2LayerBecomesAndStaysVisible() = super.app2LayerBecomesAndStaysVisible()
+
+    /** {@inheritDoc}  */
+    @FlakyTest(bugId = 214452854)
+    @Test
+    override fun app1WindowBecomesAndStaysInvisible() = super.app1WindowBecomesAndStaysInvisible()
+
+    /** {@inheritDoc}  */
+    @FlakyTest(bugId = 214452854)
+    @Test
+    override fun app1LayerBecomesAndStaysInvisible() = super.app1LayerBecomesAndStaysInvisible()
+
+    /** {@inheritDoc}  */
+    @FlakyTest(bugId = 214452854)
+    @Test
+    override fun app2WindowIsVisibleOnceApp1WindowIsInvisible() =
+            super.app2WindowIsVisibleOnceApp1WindowIsInvisible()
+
+    /** {@inheritDoc}  */
+    @FlakyTest(bugId = 214452854)
+    @Test
+    override fun app2LayerIsVisibleOnceApp1LayerIsInvisible() =
+            super.app2LayerIsVisibleOnceApp1LayerIsInvisible()
+
+    /** {@inheritDoc}  */
+    @FlakyTest(bugId = 214452854)
+    @Test
+    override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
+
+    /** {@inheritDoc}  */
+    @FlakyTest(bugId = 214452854)
+    @Test
+    override fun navBarLayerAlwaysIsVisible() = super.navBarLayerAlwaysIsVisible()
+
+    /** {@inheritDoc}  */
+    @FlakyTest(bugId = 214452854)
+    @Test
+    override fun navbarIsAlwaysInRightPosition() = super.navbarIsAlwaysInRightPosition()
+
+    /** {@inheritDoc}  */
+    @FlakyTest(bugId = 214452854)
+    @Test
+    override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
+
+    /** {@inheritDoc}  */
+    @FlakyTest(bugId = 214452854)
+    @Test
+    override fun statusBarLayerIsAlwaysVisible() = super.statusBarLayerIsAlwaysVisible()
+}
\ No newline at end of file