Merge "Remove color management configuration in VTS" into main
diff --git a/audio/aidl/common/StreamWorker.cpp b/audio/aidl/common/StreamWorker.cpp
index 0d2121c..8107655 100644
--- a/audio/aidl/common/StreamWorker.cpp
+++ b/audio/aidl/common/StreamWorker.cpp
@@ -106,6 +106,9 @@
         std::lock_guard<std::mutex> lock(mWorkerLock);
         mWorkerState = error.empty() ? WorkerState::RUNNING : WorkerState::STOPPED;
         mError = error;
+#if defined(__ANDROID__)
+        mTid = pthread_gettid_np(pthread_self());
+#endif
     }
     mWorkerCv.notify_one();
     if (!error.empty()) return;
diff --git a/audio/aidl/common/include/StreamWorker.h b/audio/aidl/common/include/StreamWorker.h
index e9c1070..efdcc81 100644
--- a/audio/aidl/common/include/StreamWorker.h
+++ b/audio/aidl/common/include/StreamWorker.h
@@ -16,6 +16,8 @@
 
 #pragma once
 
+#include <sys/types.h>
+
 #include <atomic>
 #include <condition_variable>
 #include <mutex>
@@ -52,6 +54,10 @@
         std::lock_guard<std::mutex> lock(mWorkerLock);
         return mError;
     }
+    pid_t getTid() {
+        std::lock_guard<std::mutex> lock(mWorkerLock);
+        return mTid;
+    }
     void stop();
     // Direct use of 'join' assumes that the StreamLogic is not intended
     // to run forever, and is guaranteed to exit by itself. This normally
@@ -78,6 +84,7 @@
     std::condition_variable mWorkerCv;
     WorkerState mWorkerState GUARDED_BY(mWorkerLock) = WorkerState::INITIAL;
     std::string mError GUARDED_BY(mWorkerLock);
+    pid_t mTid GUARDED_BY(mWorkerLock) = -1;
     // The atomic lock-free variable is used to prevent priority inversions
     // that can occur when a high priority worker tries to acquire the lock
     // which has been taken by a lower priority control thread which in its turn
@@ -143,6 +150,7 @@
     void resume() { mThread.resume(); }
     bool hasError() { return mThread.hasError(); }
     std::string getError() { return mThread.getError(); }
+    pid_t getTid() { return mThread.getTid(); }
     void stop() { mThread.stop(); }
     void join() { mThread.join(); }
     bool waitForAtLeastOneCycle() { return mThread.waitForAtLeastOneCycle(); }
diff --git a/audio/aidl/common/tests/streamworker_tests.cpp b/audio/aidl/common/tests/streamworker_tests.cpp
index f7a30b9..2b65740 100644
--- a/audio/aidl/common/tests/streamworker_tests.cpp
+++ b/audio/aidl/common/tests/streamworker_tests.cpp
@@ -87,6 +87,7 @@
 TEST_P(StreamWorkerInvalidTest, Uninitialized) {
     EXPECT_FALSE(worker.hasWorkerCycleCalled());
     EXPECT_FALSE(worker.hasError());
+    EXPECT_LE(worker.getTid(), 0);
 }
 
 TEST_P(StreamWorkerInvalidTest, UninitializedPauseIgnored) {
@@ -105,6 +106,9 @@
     EXPECT_FALSE(worker.start());
     EXPECT_FALSE(worker.hasWorkerCycleCalled());
     EXPECT_TRUE(worker.hasError());
+#if defined(__ANDROID__)
+    EXPECT_GT(worker.getTid(), 0);
+#endif
 }
 
 TEST_P(StreamWorkerInvalidTest, PauseIgnored) {
@@ -136,12 +140,16 @@
 TEST_P(StreamWorkerTest, Uninitialized) {
     EXPECT_FALSE(worker.hasWorkerCycleCalled());
     EXPECT_FALSE(worker.hasError());
+    EXPECT_LE(worker.getTid(), 0);
 }
 
 TEST_P(StreamWorkerTest, Start) {
     ASSERT_TRUE(worker.start());
     EXPECT_TRUE(worker.waitForAtLeastOneCycle());
     EXPECT_FALSE(worker.hasError());
+#if defined(__ANDROID__)
+    EXPECT_GT(worker.getTid(), 0);
+#endif
 }
 
 TEST_P(StreamWorkerTest, StartStop) {
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index b6cfc13..8596466 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -85,6 +85,8 @@
         "bluetooth/DevicePortProxy.cpp",
         "bluetooth/ModuleBluetooth.cpp",
         "bluetooth/StreamBluetooth.cpp",
+        "primary/PrimaryMixer.cpp",
+        "primary/StreamPrimary.cpp",
         "r_submix/ModuleRemoteSubmix.cpp",
         "r_submix/RemoteSubmixUtils.cpp",
         "r_submix/SubmixRoute.cpp",
diff --git a/audio/aidl/default/Configuration.cpp b/audio/aidl/default/Configuration.cpp
index 385ffbf..0fbf55b 100644
--- a/audio/aidl/default/Configuration.cpp
+++ b/audio/aidl/default/Configuration.cpp
@@ -136,7 +136,7 @@
 // Device ports:
 //  * "Speaker", OUT_SPEAKER, default
 //    - no profiles specified
-//  * "Built-in Mic", IN_MICROPHONE, default
+//  * "Built-In Mic", IN_MICROPHONE, default
 //    - no profiles specified
 //  * "Telephony Tx", OUT_TELEPHONY_TX
 //    - no profiles specified
@@ -148,46 +148,35 @@
 // Mix ports:
 //  * "primary output", PRIMARY, 1 max open, 1 max active stream
 //    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
-//    - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
-//  * "compressed offload", DIRECT|COMPRESS_OFFLOAD|NON_BLOCKING, 1 max open, 1 max active stream
-//    - profile MP3; MONO, STEREO; 44100, 48000
-//  * "primary input", 2 max open, 2 max active streams
-//    - profile PCM 16-bit; MONO, STEREO, FRONT_BACK;
-//        8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
-//    - profile PCM 24-bit; MONO, STEREO, FRONT_BACK;
-//        8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
+//  * "primary input", 1 max open, 1 max active stream
+//    - profile PCM 16-bit; MONO, STEREO;
+//        8000, 11025, 16000, 32000, 44100, 48000
 //  * "telephony_tx", 1 max open, 1 max active stream
 //    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
-//    - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
 //  * "telephony_rx", 1 max open, 1 max active stream
 //    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
-//    - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
 //  * "fm_tuner", 1 max open, 1 max active stream
 //    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
-//    - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
 //
 // Routes:
-//  "primary out", "compressed offload" -> "Speaker"
-//  "Built-in Mic" -> "primary input"
-//  "telephony_tx" -> "Telephony Tx"
+//  "primary out" -> "Speaker"
+//  "Built-In Mic" -> "primary input"
 //  "Telephony Rx" -> "telephony_rx"
+//  "telephony_tx" -> "Telephony Tx"
 //  "FM Tuner" -> "fm_tuner"
 //
 // Initial port configs:
-//  * "Speaker" device port: PCM 24-bit; STEREO; 48000
-//  * "Built-in Mic" device port: PCM 24-bit; MONO; 48000
-//  * "Telephony Tx" device port: PCM 24-bit; MONO; 48000
-//  * "Telephony Rx" device port: PCM 24-bit; MONO; 48000
-//  * "FM Tuner" device port: PCM 24-bit; STEREO; 48000
+//  * "Speaker" device port: PCM 16-bit; STEREO; 48000
+//  * "Built-In Mic" device port: PCM 16-bit; MONO; 48000
+//  * "Telephony Tx" device port: PCM 16-bit; MONO; 48000
+//  * "Telephony Rx" device port: PCM 16-bit; MONO; 48000
+//  * "FM Tuner" device port: PCM 16-bit; STEREO; 48000
 //
 std::unique_ptr<Configuration> getPrimaryConfiguration() {
     static const Configuration configuration = []() {
         const std::vector<AudioProfile> standardPcmAudioProfiles = {
                 createProfile(PcmType::INT_16_BIT,
                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
-                              {8000, 11025, 16000, 32000, 44100, 48000}),
-                createProfile(PcmType::INT_24_BIT,
-                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
                               {8000, 11025, 16000, 32000, 44100, 48000})};
         Configuration c;
 
@@ -199,17 +188,17 @@
                                            1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE));
         c.ports.push_back(speakerOutDevice);
         c.initialConfigs.push_back(
-                createPortConfig(speakerOutDevice.id, speakerOutDevice.id, PcmType::INT_24_BIT,
+                createPortConfig(speakerOutDevice.id, speakerOutDevice.id, PcmType::INT_16_BIT,
                                  AudioChannelLayout::LAYOUT_STEREO, 48000, 0, false,
                                  createDeviceExt(AudioDeviceType::OUT_SPEAKER, 0)));
 
         AudioPort micInDevice =
-                createPort(c.nextPortId++, "Built-in Mic", 0, true,
+                createPort(c.nextPortId++, "Built-In Mic", 0, true,
                            createDeviceExt(AudioDeviceType::IN_MICROPHONE,
                                            1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE));
         c.ports.push_back(micInDevice);
         c.initialConfigs.push_back(
-                createPortConfig(micInDevice.id, micInDevice.id, PcmType::INT_24_BIT,
+                createPortConfig(micInDevice.id, micInDevice.id, PcmType::INT_16_BIT,
                                  AudioChannelLayout::LAYOUT_MONO, 48000, 0, true,
                                  createDeviceExt(AudioDeviceType::IN_MICROPHONE, 0)));
 
@@ -219,7 +208,7 @@
         c.ports.push_back(telephonyTxOutDevice);
         c.initialConfigs.push_back(
                 createPortConfig(telephonyTxOutDevice.id, telephonyTxOutDevice.id,
-                                 PcmType::INT_24_BIT, AudioChannelLayout::LAYOUT_MONO, 48000, 0,
+                                 PcmType::INT_16_BIT, AudioChannelLayout::LAYOUT_MONO, 48000, 0,
                                  false, createDeviceExt(AudioDeviceType::OUT_TELEPHONY_TX, 0)));
 
         AudioPort telephonyRxInDevice =
@@ -228,14 +217,14 @@
         c.ports.push_back(telephonyRxInDevice);
         c.initialConfigs.push_back(
                 createPortConfig(telephonyRxInDevice.id, telephonyRxInDevice.id,
-                                 PcmType::INT_24_BIT, AudioChannelLayout::LAYOUT_MONO, 48000, 0,
+                                 PcmType::INT_16_BIT, AudioChannelLayout::LAYOUT_MONO, 48000, 0,
                                  true, createDeviceExt(AudioDeviceType::IN_TELEPHONY_RX, 0)));
 
         AudioPort fmTunerInDevice = createPort(c.nextPortId++, "FM Tuner", 0, true,
                                                createDeviceExt(AudioDeviceType::IN_FM_TUNER, 0));
         c.ports.push_back(fmTunerInDevice);
         c.initialConfigs.push_back(
-                createPortConfig(fmTunerInDevice.id, fmTunerInDevice.id, PcmType::INT_24_BIT,
+                createPortConfig(fmTunerInDevice.id, fmTunerInDevice.id, PcmType::INT_16_BIT,
                                  AudioChannelLayout::LAYOUT_STEREO, 48000, 0, true,
                                  createDeviceExt(AudioDeviceType::IN_FM_TUNER, 0)));
 
@@ -249,30 +238,12 @@
                                       standardPcmAudioProfiles.end());
         c.ports.push_back(primaryOutMix);
 
-        AudioPort compressedOffloadOutMix =
-                createPort(c.nextPortId++, "compressed offload",
-                           makeBitPositionFlagMask({AudioOutputFlags::DIRECT,
-                                                    AudioOutputFlags::COMPRESS_OFFLOAD,
-                                                    AudioOutputFlags::NON_BLOCKING}),
-                           false, createPortMixExt(1, 1));
-        compressedOffloadOutMix.profiles.push_back(
-                createProfile(::android::MEDIA_MIMETYPE_AUDIO_MPEG,
-                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
-                              {44100, 48000}));
-        c.ports.push_back(compressedOffloadOutMix);
-
         AudioPort primaryInMix =
-                createPort(c.nextPortId++, "primary input", 0, true, createPortMixExt(2, 2));
+                createPort(c.nextPortId++, "primary input", 0, true, createPortMixExt(1, 1));
         primaryInMix.profiles.push_back(
                 createProfile(PcmType::INT_16_BIT,
-                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
-                               AudioChannelLayout::LAYOUT_FRONT_BACK},
-                              {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000}));
-        primaryInMix.profiles.push_back(
-                createProfile(PcmType::INT_24_BIT,
-                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
-                               AudioChannelLayout::LAYOUT_FRONT_BACK},
-                              {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000}));
+                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
+                              {8000, 11025, 16000, 32000, 44100, 48000}));
         c.ports.push_back(primaryInMix);
 
         AudioPort telephonyTxOutMix =
@@ -296,10 +267,10 @@
                                      standardPcmAudioProfiles.end());
         c.ports.push_back(fmTunerInMix);
 
-        c.routes.push_back(createRoute({primaryOutMix, compressedOffloadOutMix}, speakerOutDevice));
+        c.routes.push_back(createRoute({primaryOutMix}, speakerOutDevice));
         c.routes.push_back(createRoute({micInDevice}, primaryInMix));
-        c.routes.push_back(createRoute({telephonyTxOutMix}, telephonyTxOutDevice));
         c.routes.push_back(createRoute({telephonyRxInDevice}, telephonyRxInMix));
+        c.routes.push_back(createRoute({telephonyTxOutMix}, telephonyTxOutDevice));
         c.routes.push_back(createRoute({fmTunerInDevice}, fmTunerInMix));
 
         c.portConfigs.insert(c.portConfigs.end(), c.initialConfigs.begin(), c.initialConfigs.end());
@@ -320,15 +291,15 @@
 //
 // Device ports:
 //  * "Remote Submix Out", OUT_SUBMIX
-//    - profile PCM 24-bit; STEREO; 48000
+//    - profile PCM 16-bit; STEREO; 48000
 //  * "Remote Submix In", IN_SUBMIX
-//    - profile PCM 24-bit; STEREO; 48000
+//    - profile PCM 16-bit; STEREO; 48000
 //
 // Mix ports:
-//  * "r_submix output", stream count unlimited
-//    - profile PCM 24-bit; STEREO; 48000
-//  * "r_submix input", stream count unlimited
-//    - profile PCM 24-bit; STEREO; 48000
+//  * "r_submix output", 1 max open, 1 max active stream
+//    - profile PCM 16-bit; STEREO; 48000
+//  * "r_submix input", 1 max open, 1 max active stream
+//    - profile PCM 16-bit; STEREO; 48000
 //
 // Routes:
 //  "r_submix output" -> "Remote Submix Out"
@@ -345,27 +316,27 @@
                            createDeviceExt(AudioDeviceType::OUT_SUBMIX, 0,
                                            AudioDeviceDescription::CONNECTION_VIRTUAL));
         rsubmixOutDevice.profiles.push_back(
-                createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
+                createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
         c.ports.push_back(rsubmixOutDevice);
 
         AudioPort rsubmixInDevice = createPort(c.nextPortId++, "Remote Submix In", 0, true,
                                                createDeviceExt(AudioDeviceType::IN_SUBMIX, 0));
         rsubmixInDevice.profiles.push_back(
-                createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
+                createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
         c.ports.push_back(rsubmixInDevice);
 
         // Mix ports
 
         AudioPort rsubmixOutMix =
-                createPort(c.nextPortId++, "r_submix output", 0, false, createPortMixExt(0, 0));
+                createPort(c.nextPortId++, "r_submix output", 0, false, createPortMixExt(1, 1));
         rsubmixOutMix.profiles.push_back(
-                createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
+                createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
         c.ports.push_back(rsubmixOutMix);
 
         AudioPort rsubmixInMix =
-                createPort(c.nextPortId++, "r_submix input", 0, true, createPortMixExt(0, 0));
+                createPort(c.nextPortId++, "r_submix input", 0, true, createPortMixExt(1, 1));
         rsubmixInMix.profiles.push_back(
-                createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
+                createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
         c.ports.push_back(rsubmixInMix);
 
         c.routes.push_back(createRoute({rsubmixOutMix}, rsubmixOutDevice));
@@ -479,14 +450,17 @@
 // Mix ports:
 //  * "test output", 1 max open, 1 max active stream
 //    - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
-//  * "compressed offload", DIRECT|COMPRESS_OFFLOAD|NON_BLOCKING, 1 max open, 1 max active stream
+//  * "test fast output", 1 max open, 1 max active stream
+//    - profile PCM 24-bit; STEREO; 44100, 48000
+//  * "test compressed offload", DIRECT|COMPRESS_OFFLOAD|NON_BLOCKING, 1 max open, 1 max active
+//  stream
 //    - profile MP3; MONO, STEREO; 44100, 48000
 //  * "test input", 2 max open, 2 max active streams
 //    - profile PCM 24-bit; MONO, STEREO, FRONT_BACK;
-//        8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
+//        8000, 11025, 16000, 22050, 32000, 44100, 48000
 //
 // Routes:
-//  "test output", "compressed offload" -> "Test Out"
+//  "test output", "test fast output", "test compressed offload" -> "Test Out"
 //  "Test In" -> "test input"
 //
 // Initial port configs:
@@ -525,8 +499,15 @@
                               {8000, 11025, 16000, 32000, 44100, 48000}));
         c.ports.push_back(testOutMix);
 
+        AudioPort testFastOutMix = createPort(c.nextPortId++, "test fast output",
+                                              makeBitPositionFlagMask({AudioOutputFlags::FAST}),
+                                              false, createPortMixExt(1, 1));
+        testFastOutMix.profiles.push_back(createProfile(
+                PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {44100, 48000}));
+        c.ports.push_back(testFastOutMix);
+
         AudioPort compressedOffloadOutMix =
-                createPort(c.nextPortId++, "compressed offload",
+                createPort(c.nextPortId++, "test compressed offload",
                            makeBitPositionFlagMask({AudioOutputFlags::DIRECT,
                                                     AudioOutputFlags::COMPRESS_OFFLOAD,
                                                     AudioOutputFlags::NON_BLOCKING}),
@@ -543,15 +524,16 @@
                 createProfile(PcmType::INT_16_BIT,
                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
                                AudioChannelLayout::LAYOUT_FRONT_BACK},
-                              {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000}));
+                              {8000, 11025, 16000, 22050, 32000, 44100, 48000}));
         testInMIx.profiles.push_back(
                 createProfile(PcmType::INT_24_BIT,
                               {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
                                AudioChannelLayout::LAYOUT_FRONT_BACK},
-                              {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000}));
+                              {8000, 11025, 16000, 22050, 32000, 44100, 48000}));
         c.ports.push_back(testInMIx);
 
-        c.routes.push_back(createRoute({testOutMix, compressedOffloadOutMix}, testOutDevice));
+        c.routes.push_back(
+                createRoute({testOutMix, testFastOutMix, compressedOffloadOutMix}, testOutDevice));
         c.routes.push_back(createRoute({testInDevice}, testInMIx));
 
         c.portConfigs.insert(c.portConfigs.end(), c.initialConfigs.begin(), c.initialConfigs.end());
@@ -566,7 +548,7 @@
 // Device ports:
 //  * "BT A2DP Out", OUT_DEVICE, CONNECTION_BT_A2DP
 //    - profile PCM 16-bit; STEREO; 44100, 48000, 88200, 96000
-//  * "BT A2DP Headphones", OUT_HEADSET, CONNECTION_BT_A2DP
+//  * "BT A2DP Headphones", OUT_HEADPHONE, CONNECTION_BT_A2DP
 //    - profile PCM 16-bit; STEREO; 44100, 48000, 88200, 96000
 //  * "BT A2DP Speaker", OUT_SPEAKER, CONNECTION_BT_A2DP
 //    - profile PCM 16-bit; STEREO; 44100, 48000, 88200, 96000
@@ -597,13 +579,18 @@
                 createPort(c.nextPortId++, "BT A2DP Out", 0, false,
                            createDeviceExt(AudioDeviceType::OUT_DEVICE, 0,
                                            AudioDeviceDescription::CONNECTION_BT_A2DP));
+        btOutDevice.profiles.insert(btOutDevice.profiles.begin(), standardPcmAudioProfiles.begin(),
+                                    standardPcmAudioProfiles.end());
         c.ports.push_back(btOutDevice);
         c.connectedProfiles[btOutDevice.id] = standardPcmAudioProfiles;
 
         AudioPort btOutHeadphone =
                 createPort(c.nextPortId++, "BT A2DP Headphones", 0, false,
-                           createDeviceExt(AudioDeviceType::OUT_HEADSET, 0,
+                           createDeviceExt(AudioDeviceType::OUT_HEADPHONE, 0,
                                            AudioDeviceDescription::CONNECTION_BT_A2DP));
+        btOutHeadphone.profiles.insert(btOutHeadphone.profiles.begin(),
+                                       standardPcmAudioProfiles.begin(),
+                                       standardPcmAudioProfiles.end());
         c.ports.push_back(btOutHeadphone);
         c.connectedProfiles[btOutHeadphone.id] = standardPcmAudioProfiles;
 
@@ -611,6 +598,9 @@
                 createPort(c.nextPortId++, "BT A2DP Speaker", 0, false,
                            createDeviceExt(AudioDeviceType::OUT_SPEAKER, 0,
                                            AudioDeviceDescription::CONNECTION_BT_A2DP));
+        btOutSpeaker.profiles.insert(btOutSpeaker.profiles.begin(),
+                                     standardPcmAudioProfiles.begin(),
+                                     standardPcmAudioProfiles.end());
         c.ports.push_back(btOutSpeaker);
         c.connectedProfiles[btOutSpeaker.id] = standardPcmAudioProfiles;
 
@@ -623,20 +613,20 @@
                 {createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {16000})});
 
         // Mix ports
-        AudioPort btInMix =
-                createPort(c.nextPortId++, "a2dp output", 0, true, createPortMixExt(1, 1));
-        c.ports.push_back(btInMix);
+        AudioPort btOutMix =
+                createPort(c.nextPortId++, "a2dp output", 0, false, createPortMixExt(1, 1));
+        c.ports.push_back(btOutMix);
 
-        AudioPort btHeadsetInMix =
-                createPort(c.nextPortId++, "hearing aid output", 0, true, createPortMixExt(1, 1));
-        btHeadsetInMix.profiles.push_back(createProfile(
+        AudioPort btHearingOutMix =
+                createPort(c.nextPortId++, "hearing aid output", 0, false, createPortMixExt(1, 1));
+        btHearingOutMix.profiles.push_back(createProfile(
                 PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {16000, 24000}));
-        c.ports.push_back(btHeadsetInMix);
+        c.ports.push_back(btHearingOutMix);
 
-        c.routes.push_back(createRoute({btInMix}, btOutDevice));
-        c.routes.push_back(createRoute({btInMix}, btOutHeadphone));
-        c.routes.push_back(createRoute({btInMix}, btOutSpeaker));
-        c.routes.push_back(createRoute({btHeadsetInMix}, btOutHearingAid));
+        c.routes.push_back(createRoute({btOutMix}, btOutDevice));
+        c.routes.push_back(createRoute({btOutMix}, btOutHeadphone));
+        c.routes.push_back(createRoute({btOutMix}, btOutSpeaker));
+        c.routes.push_back(createRoute({btHearingOutMix}, btOutHearingAid));
 
         return c;
     }();
diff --git a/audio/aidl/default/ModulePrimary.cpp b/audio/aidl/default/ModulePrimary.cpp
index 29e8126..9919c7f 100644
--- a/audio/aidl/default/ModulePrimary.cpp
+++ b/audio/aidl/default/ModulePrimary.cpp
@@ -21,7 +21,7 @@
 #include <android-base/logging.h>
 
 #include "core-impl/ModulePrimary.h"
-#include "core-impl/StreamStub.h"
+#include "core-impl/StreamPrimary.h"
 #include "core-impl/Telephony.h"
 
 using aidl::android::hardware::audio::common::SinkMetadata;
@@ -47,15 +47,15 @@
                                                     const SinkMetadata& sinkMetadata,
                                                     const std::vector<MicrophoneInfo>& microphones,
                                                     std::shared_ptr<StreamIn>* result) {
-    return createStreamInstance<StreamInStub>(result, std::move(context), sinkMetadata,
-                                              microphones);
+    return createStreamInstance<StreamInPrimary>(result, std::move(context), sinkMetadata,
+                                                 microphones);
 }
 
 ndk::ScopedAStatus ModulePrimary::createOutputStream(
         StreamContext&& context, const SourceMetadata& sourceMetadata,
         const std::optional<AudioOffloadInfo>& offloadInfo, std::shared_ptr<StreamOut>* result) {
-    return createStreamInstance<StreamOutStub>(result, std::move(context), sourceMetadata,
-                                               offloadInfo);
+    return createStreamInstance<StreamOutPrimary>(result, std::move(context), sourceMetadata,
+                                                  offloadInfo);
 }
 
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/Stream.cpp b/audio/aidl/default/Stream.cpp
index 7a617c9..af89f5f 100644
--- a/audio/aidl/default/Stream.cpp
+++ b/audio/aidl/default/Stream.cpp
@@ -27,12 +27,16 @@
 using aidl::android::hardware::audio::common::AudioOffloadMetadata;
 using aidl::android::hardware::audio::common::getChannelCount;
 using aidl::android::hardware::audio::common::getFrameSizeInBytes;
+using aidl::android::hardware::audio::common::isBitPositionFlagSet;
 using aidl::android::hardware::audio::common::SinkMetadata;
 using aidl::android::hardware::audio::common::SourceMetadata;
 using aidl::android::media::audio::common::AudioDevice;
 using aidl::android::media::audio::common::AudioDualMonoMode;
+using aidl::android::media::audio::common::AudioInputFlags;
+using aidl::android::media::audio::common::AudioIoFlags;
 using aidl::android::media::audio::common::AudioLatencyMode;
 using aidl::android::media::audio::common::AudioOffloadInfo;
+using aidl::android::media::audio::common::AudioOutputFlags;
 using aidl::android::media::audio::common::AudioPlaybackRate;
 using aidl::android::media::audio::common::MicrophoneDynamicInfo;
 using aidl::android::media::audio::common::MicrophoneInfo;
@@ -238,8 +242,8 @@
             break;
         case Tag::standby:
             if (mState == StreamDescriptor::State::IDLE) {
+                populateReply(&reply, mIsConnected);
                 if (::android::status_t status = mDriver->standby(); status == ::android::OK) {
-                    populateReply(&reply, mIsConnected);
                     mState = StreamDescriptor::State::STANDBY;
                 } else {
                     LOG(ERROR) << __func__ << ": standby failed: " << status;
@@ -492,8 +496,8 @@
             break;
         case Tag::standby:
             if (mState == StreamDescriptor::State::IDLE) {
+                populateReply(&reply, mIsConnected);
                 if (::android::status_t status = mDriver->standby(); status == ::android::OK) {
-                    populateReply(&reply, mIsConnected);
                     mState = StreamDescriptor::State::STANDBY;
                 } else {
                     LOG(ERROR) << __func__ << ": standby failed: " << status;
@@ -610,8 +614,30 @@
 ndk::ScopedAStatus StreamCommonImpl::initInstance(
         const std::shared_ptr<StreamCommonInterface>& delegate) {
     mCommon = ndk::SharedRefBase::make<StreamCommonDelegator>(delegate);
-    return mWorker->start() ? ndk::ScopedAStatus::ok()
-                            : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    if (!mWorker->start()) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+    }
+    if (auto flags = getContext().getFlags();
+        (flags.getTag() == AudioIoFlags::Tag::input &&
+         isBitPositionFlagSet(flags.template get<AudioIoFlags::Tag::input>(),
+                              AudioInputFlags::FAST)) ||
+        (flags.getTag() == AudioIoFlags::Tag::output &&
+         isBitPositionFlagSet(flags.template get<AudioIoFlags::Tag::output>(),
+                              AudioOutputFlags::FAST))) {
+        // FAST workers should be run with a SCHED_FIFO scheduler, however the host process
+        // might be lacking the capability to request it, thus a failure to set is not an error.
+        pid_t workerTid = mWorker->getTid();
+        if (workerTid > 0) {
+            struct sched_param param;
+            param.sched_priority = 3;  // Must match SchedulingPolicyService.PRIORITY_MAX (Java).
+            if (sched_setscheduler(workerTid, SCHED_FIFO | SCHED_RESET_ON_FORK, &param) != 0) {
+                PLOG(WARNING) << __func__ << ": failed to set FIFO scheduler for a fast thread";
+            }
+        } else {
+            LOG(WARNING) << __func__ << ": invalid worker tid: " << workerTid;
+        }
+    }
+    return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus StreamCommonImpl::getStreamCommonCommon(
@@ -799,6 +825,32 @@
     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
 }
 
+StreamInHwGainHelper::StreamInHwGainHelper(const StreamContext* context)
+    : mChannelCount(getChannelCount(context->getChannelLayout())) {}
+
+ndk::ScopedAStatus StreamInHwGainHelper::getHwGainImpl(std::vector<float>* _aidl_return) {
+    *_aidl_return = mHwGains;
+    LOG(DEBUG) << __func__ << ": returning " << ::android::internal::ToString(*_aidl_return);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StreamInHwGainHelper::setHwGainImpl(const std::vector<float>& in_channelGains) {
+    LOG(DEBUG) << __func__ << ": gains " << ::android::internal::ToString(in_channelGains);
+    if (in_channelGains.size() != mChannelCount) {
+        LOG(ERROR) << __func__
+                   << ": channel count does not match stream channel count: " << mChannelCount;
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    for (float gain : in_channelGains) {
+        if (gain < StreamIn::HW_GAIN_MIN || gain > StreamIn::HW_GAIN_MAX) {
+            LOG(ERROR) << __func__ << ": gain value out of range: " << gain;
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        }
+    }
+    mHwGains = in_channelGains;
+    return ndk::ScopedAStatus::ok();
+}
+
 StreamOut::StreamOut(StreamContext&& context, const std::optional<AudioOffloadInfo>& offloadInfo)
     : mContextInstance(std::move(context)), mOffloadInfo(offloadInfo) {
     LOG(DEBUG) << __func__;
@@ -904,4 +956,31 @@
     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
 }
 
+StreamOutHwVolumeHelper::StreamOutHwVolumeHelper(const StreamContext* context)
+    : mChannelCount(getChannelCount(context->getChannelLayout())) {}
+
+ndk::ScopedAStatus StreamOutHwVolumeHelper::getHwVolumeImpl(std::vector<float>* _aidl_return) {
+    *_aidl_return = mHwVolumes;
+    LOG(DEBUG) << __func__ << ": returning " << ::android::internal::ToString(*_aidl_return);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StreamOutHwVolumeHelper::setHwVolumeImpl(
+        const std::vector<float>& in_channelVolumes) {
+    LOG(DEBUG) << __func__ << ": volumes " << ::android::internal::ToString(in_channelVolumes);
+    if (in_channelVolumes.size() != mChannelCount) {
+        LOG(ERROR) << __func__
+                   << ": channel count does not match stream channel count: " << mChannelCount;
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    for (float volume : in_channelVolumes) {
+        if (volume < StreamOut::HW_VOLUME_MIN || volume > StreamOut::HW_VOLUME_MAX) {
+            LOG(ERROR) << __func__ << ": volume value out of range: " << volume;
+            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+        }
+    }
+    mHwVolumes = in_channelVolumes;
+    return ndk::ScopedAStatus::ok();
+}
+
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/alsa/StreamAlsa.cpp b/audio/aidl/default/alsa/StreamAlsa.cpp
index 1d22a60..0605d6f 100644
--- a/audio/aidl/default/alsa/StreamAlsa.cpp
+++ b/audio/aidl/default/alsa/StreamAlsa.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <cmath>
 #include <limits>
 
 #define LOG_TAG "AHAL_StreamAlsa"
@@ -29,7 +30,9 @@
 
 StreamAlsa::StreamAlsa(StreamContext* context, const Metadata& metadata, int readWriteRetries)
     : StreamCommonImpl(context, metadata),
+      mBufferSizeFrames(getContext().getBufferSizeInFrames()),
       mFrameSizeBytes(getContext().getFrameSize()),
+      mSampleRate(getContext().getSampleRate()),
       mIsInput(isInput(metadata)),
       mConfig(alsa::getPcmConfig(getContext(), mIsInput)),
       mReadWriteRetries(readWriteRetries) {}
@@ -39,17 +42,20 @@
 }
 
 ::android::status_t StreamAlsa::drain(StreamDescriptor::DrainMode) {
-    usleep(1000);
+    if (!mIsInput) {
+        static constexpr float kMicrosPerSecond = MICROS_PER_SECOND;
+        const size_t delayUs = static_cast<size_t>(
+                std::roundf(mBufferSizeFrames * kMicrosPerSecond / mSampleRate));
+        usleep(delayUs);
+    }
     return ::android::OK;
 }
 
 ::android::status_t StreamAlsa::flush() {
-    usleep(1000);
     return ::android::OK;
 }
 
 ::android::status_t StreamAlsa::pause() {
-    usleep(1000);
     return ::android::OK;
 }
 
@@ -59,6 +65,10 @@
 }
 
 ::android::status_t StreamAlsa::start() {
+    if (!mAlsaDeviceProxies.empty()) {
+        // This is a resume after a pause.
+        return ::android::OK;
+    }
     decltype(mAlsaDeviceProxies) alsaDeviceProxies;
     for (const auto& device : getDeviceProfiles()) {
         alsa::DeviceProxy proxy;
@@ -71,8 +81,7 @@
                     true /*require_exact_match*/);
         } else {
             proxy = alsa::openProxyForAttachedDevice(
-                    device, const_cast<struct pcm_config*>(&mConfig.value()),
-                    getContext().getBufferSizeInFrames());
+                    device, const_cast<struct pcm_config*>(&mConfig.value()), mBufferSizeFrames);
         }
         if (!proxy) {
             return ::android::NO_INIT;
@@ -85,13 +94,13 @@
 
 ::android::status_t StreamAlsa::transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
                                          int32_t* latencyMs) {
+    if (mAlsaDeviceProxies.empty()) {
+        LOG(FATAL) << __func__ << ": no opened devices";
+        return ::android::NO_INIT;
+    }
     const size_t bytesToTransfer = frameCount * mFrameSizeBytes;
     unsigned maxLatency = 0;
     if (mIsInput) {
-        if (mAlsaDeviceProxies.empty()) {
-            LOG(FATAL) << __func__ << ": no input devices";
-            return ::android::NO_INIT;
-        }
         // For input case, only support single device.
         proxy_read_with_retries(mAlsaDeviceProxies[0].get(), buffer, bytesToTransfer,
                                 mReadWriteRetries);
@@ -110,9 +119,12 @@
 
 ::android::status_t StreamAlsa::refinePosition(StreamDescriptor::Position* position) {
     if (mAlsaDeviceProxies.empty()) {
-        LOG(FATAL) << __func__ << ": no input devices";
+        LOG(FATAL) << __func__ << ": no opened devices";
         return ::android::NO_INIT;
     }
+    // Since the proxy can only count transferred frames since its creation,
+    // we override its counter value with ours and let it to correct for buffered frames.
+    alsa::resetTransferredFrames(mAlsaDeviceProxies[0], position->frames);
     if (mIsInput) {
         if (int ret = proxy_get_capture_position(mAlsaDeviceProxies[0].get(), &position->frames,
                                                  &position->timeNs);
diff --git a/audio/aidl/default/alsa/Utils.cpp b/audio/aidl/default/alsa/Utils.cpp
index 20f7797..9dcd024 100644
--- a/audio/aidl/default/alsa/Utils.cpp
+++ b/audio/aidl/default/alsa/Utils.cpp
@@ -262,12 +262,14 @@
 }
 
 DeviceProxy makeDeviceProxy() {
-    return DeviceProxy(new alsa_device_proxy, [](alsa_device_proxy* proxy) {
+    DeviceProxy proxy(new alsa_device_proxy, [](alsa_device_proxy* proxy) {
         if (proxy != nullptr) {
             proxy_close(proxy);
             delete proxy;
         }
     });
+    memset(proxy.get(), 0, sizeof(alsa_device_proxy));
+    return proxy;
 }
 
 DeviceProxy openProxyForAttachedDevice(const DeviceProfile& deviceProfile,
@@ -334,6 +336,12 @@
     return profile;
 }
 
+void resetTransferredFrames(DeviceProxy& proxy, uint64_t frames) {
+    if (proxy != nullptr) {
+        proxy->transferred = frames;
+    }
+}
+
 AudioFormatDescription c2aidl_pcm_format_AudioFormatDescription(enum pcm_format legacy) {
     return findValueOrDefault(getPcmFormatToAudioFormatDescMap(), legacy, AudioFormatDescription());
 }
diff --git a/audio/aidl/default/alsa/Utils.h b/audio/aidl/default/alsa/Utils.h
index 615e657..37414b3 100644
--- a/audio/aidl/default/alsa/Utils.h
+++ b/audio/aidl/default/alsa/Utils.h
@@ -66,6 +66,7 @@
 DeviceProxy openProxyForExternalDevice(const DeviceProfile& deviceProfile,
                                        struct pcm_config* pcmConfig, bool requireExactMatch);
 std::optional<alsa_device_profile> readAlsaDeviceInfo(const DeviceProfile& deviceProfile);
+void resetTransferredFrames(DeviceProxy& proxy, uint64_t frames);
 
 ::aidl::android::media::audio::common::AudioFormatDescription
 c2aidl_pcm_format_AudioFormatDescription(enum pcm_format legacy);
diff --git a/audio/aidl/default/android.hardware.audio.service-aidl.example.rc b/audio/aidl/default/android.hardware.audio.service-aidl.example.rc
index 2068735..757976f 100644
--- a/audio/aidl/default/android.hardware.audio.service-aidl.example.rc
+++ b/audio/aidl/default/android.hardware.audio.service-aidl.example.rc
@@ -3,7 +3,7 @@
     user audioserver
     # media gid needed for /dev/fm (radio) and for /data/misc/media (tee)
     group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct wakelock context_hub
-    capabilities BLOCK_SUSPEND
+    capabilities BLOCK_SUSPEND SYS_NICE
     # setting RLIMIT_RTPRIO allows binder RT priority inheritance
     rlimit rtprio 10 10
     ioprio rt 4
diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h
index a2edb6f..a02655f 100644
--- a/audio/aidl/default/include/core-impl/Stream.h
+++ b/audio/aidl/default/include/core-impl/Stream.h
@@ -262,6 +262,7 @@
     virtual void setIsConnected(bool isConnected) = 0;
     virtual StreamDescriptor::State setClosed() = 0;
     virtual bool start() = 0;
+    virtual pid_t getTid() = 0;
     virtual void stop() = 0;
 };
 
@@ -277,8 +278,10 @@
     void setIsConnected(bool isConnected) override { WorkerImpl::setIsConnected(isConnected); }
     StreamDescriptor::State setClosed() override { return WorkerImpl::setClosed(); }
     bool start() override {
-        return WorkerImpl::start(WorkerImpl::kThreadName, ANDROID_PRIORITY_AUDIO);
+        // This is an "audio service thread," must have elevated priority.
+        return WorkerImpl::start(WorkerImpl::kThreadName, ANDROID_PRIORITY_URGENT_AUDIO);
     }
+    pid_t getTid() override { return WorkerImpl::getTid(); }
     void stop() override { return WorkerImpl::stop(); }
 };
 
@@ -511,6 +514,17 @@
     const std::map<::aidl::android::media::audio::common::AudioDevice, std::string> mMicrophones;
 };
 
+class StreamInHwGainHelper {
+  protected:
+    explicit StreamInHwGainHelper(const StreamContext* context);
+
+    ndk::ScopedAStatus getHwGainImpl(std::vector<float>* _aidl_return);
+    ndk::ScopedAStatus setHwGainImpl(const std::vector<float>& in_channelGains);
+
+    const size_t mChannelCount;
+    std::vector<float> mHwGains;
+};
+
 class StreamOut : virtual public StreamCommonInterface, public BnStreamOut {
   protected:
     void defaultOnClose();
@@ -557,6 +571,17 @@
     std::optional<::aidl::android::hardware::audio::common::AudioOffloadMetadata> mOffloadMetadata;
 };
 
+class StreamOutHwVolumeHelper {
+  protected:
+    explicit StreamOutHwVolumeHelper(const StreamContext* context);
+
+    ndk::ScopedAStatus getHwVolumeImpl(std::vector<float>* _aidl_return);
+    ndk::ScopedAStatus setHwVolumeImpl(const std::vector<float>& in_channelVolumes);
+
+    const size_t mChannelCount;
+    std::vector<float> mHwVolumes;
+};
+
 // The recommended way to create a stream instance.
 // 'StreamImpl' is the concrete stream implementation, 'StreamInOrOut' is either 'StreamIn' or
 // 'StreamOut', the rest are the arguments forwarded to the constructor of 'StreamImpl'.
diff --git a/audio/aidl/default/include/core-impl/StreamAlsa.h b/audio/aidl/default/include/core-impl/StreamAlsa.h
index 555b27a..2c3b284 100644
--- a/audio/aidl/default/include/core-impl/StreamAlsa.h
+++ b/audio/aidl/default/include/core-impl/StreamAlsa.h
@@ -48,7 +48,9 @@
     // Called from 'start' to initialize 'mAlsaDeviceProxies', the vector must be non-empty.
     virtual std::vector<alsa::DeviceProfile> getDeviceProfiles() = 0;
 
+    const size_t mBufferSizeFrames;
     const size_t mFrameSizeBytes;
+    const int mSampleRate;
     const bool mIsInput;
     const std::optional<struct pcm_config> mConfig;
     const int mReadWriteRetries;
diff --git a/audio/aidl/default/include/core-impl/StreamPrimary.h b/audio/aidl/default/include/core-impl/StreamPrimary.h
new file mode 100644
index 0000000..b3ddd0b
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/StreamPrimary.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <vector>
+
+#include "StreamAlsa.h"
+#include "StreamSwitcher.h"
+
+namespace aidl::android::hardware::audio::core {
+
+class StreamPrimary : public StreamAlsa {
+  public:
+    StreamPrimary(StreamContext* context, const Metadata& metadata);
+
+  protected:
+    std::vector<alsa::DeviceProfile> getDeviceProfiles() override;
+
+    const bool mIsInput;
+};
+
+class StreamInPrimary final : public StreamIn, public StreamSwitcher, public StreamInHwGainHelper {
+  public:
+    friend class ndk::SharedRefBase;
+    StreamInPrimary(
+            StreamContext&& context,
+            const ::aidl::android::hardware::audio::common::SinkMetadata& sinkMetadata,
+            const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
+
+  private:
+    static bool useStubStream(const ::aidl::android::media::audio::common::AudioDevice& device);
+
+    DeviceSwitchBehavior switchCurrentStream(
+            const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
+            override;
+    std::unique_ptr<StreamCommonInterfaceEx> createNewStream(
+            const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
+            StreamContext* context, const Metadata& metadata) override;
+    void onClose(StreamDescriptor::State) override { defaultOnClose(); }
+
+    ndk::ScopedAStatus getHwGain(std::vector<float>* _aidl_return) override;
+    ndk::ScopedAStatus setHwGain(const std::vector<float>& in_channelGains) override;
+};
+
+class StreamOutPrimary final : public StreamOut,
+                               public StreamSwitcher,
+                               public StreamOutHwVolumeHelper {
+  public:
+    friend class ndk::SharedRefBase;
+    StreamOutPrimary(StreamContext&& context,
+                     const ::aidl::android::hardware::audio::common::SourceMetadata& sourceMetadata,
+                     const std::optional<::aidl::android::media::audio::common::AudioOffloadInfo>&
+                             offloadInfo);
+
+  private:
+    static bool useStubStream(const ::aidl::android::media::audio::common::AudioDevice& device);
+
+    DeviceSwitchBehavior switchCurrentStream(
+            const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
+            override;
+    std::unique_ptr<StreamCommonInterfaceEx> createNewStream(
+            const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
+            StreamContext* context, const Metadata& metadata) override;
+    void onClose(StreamDescriptor::State) override { defaultOnClose(); }
+
+    ndk::ScopedAStatus getHwVolume(std::vector<float>* _aidl_return) override;
+    ndk::ScopedAStatus setHwVolume(const std::vector<float>& in_channelVolumes) override;
+};
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/StreamStub.h b/audio/aidl/default/include/core-impl/StreamStub.h
index a8a3fc4..3857e0e 100644
--- a/audio/aidl/default/include/core-impl/StreamStub.h
+++ b/audio/aidl/default/include/core-impl/StreamStub.h
@@ -35,6 +35,7 @@
     void shutdown() override;
 
   private:
+    const size_t mBufferSizeFrames;
     const size_t mFrameSizeBytes;
     const int mSampleRate;
     const bool mIsAsynchronous;
diff --git a/audio/aidl/default/include/core-impl/StreamUsb.h b/audio/aidl/default/include/core-impl/StreamUsb.h
index 74e30ff..608f27d 100644
--- a/audio/aidl/default/include/core-impl/StreamUsb.h
+++ b/audio/aidl/default/include/core-impl/StreamUsb.h
@@ -59,7 +59,7 @@
             override;
 };
 
-class StreamOutUsb final : public StreamOut, public StreamUsb {
+class StreamOutUsb final : public StreamOut, public StreamUsb, public StreamOutHwVolumeHelper {
   public:
     friend class ndk::SharedRefBase;
     StreamOutUsb(StreamContext&& context,
@@ -71,9 +71,6 @@
     void onClose(StreamDescriptor::State) override { defaultOnClose(); }
     ndk::ScopedAStatus getHwVolume(std::vector<float>* _aidl_return) override;
     ndk::ScopedAStatus setHwVolume(const std::vector<float>& in_channelVolumes) override;
-
-    const int mChannelCount;
-    std::vector<float> mHwVolumes;
 };
 
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/primary/PrimaryMixer.cpp b/audio/aidl/default/primary/PrimaryMixer.cpp
new file mode 100644
index 0000000..577d010
--- /dev/null
+++ b/audio/aidl/default/primary/PrimaryMixer.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_PrimaryMixer"
+
+#include "PrimaryMixer.h"
+
+namespace aidl::android::hardware::audio::core::primary {
+
+// static
+PrimaryMixer& PrimaryMixer::getInstance() {
+    static PrimaryMixer gInstance;
+    return gInstance;
+}
+
+}  // namespace aidl::android::hardware::audio::core::primary
diff --git a/audio/aidl/default/primary/PrimaryMixer.h b/audio/aidl/default/primary/PrimaryMixer.h
new file mode 100644
index 0000000..3806428
--- /dev/null
+++ b/audio/aidl/default/primary/PrimaryMixer.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include <map>
+#include <memory>
+#include <mutex>
+#include <vector>
+
+#include <android-base/thread_annotations.h>
+#include <android/binder_auto_utils.h>
+
+#include "alsa/Mixer.h"
+
+namespace aidl::android::hardware::audio::core::primary {
+
+class PrimaryMixer : public alsa::Mixer {
+  public:
+    static constexpr int kAlsaCard = 0;
+    static constexpr int kAlsaDevice = 0;
+
+    static PrimaryMixer& getInstance();
+
+  private:
+    PrimaryMixer() : alsa::Mixer(kAlsaCard) {}
+};
+
+}  // namespace aidl::android::hardware::audio::core::primary
diff --git a/audio/aidl/default/primary/StreamPrimary.cpp b/audio/aidl/default/primary/StreamPrimary.cpp
new file mode 100644
index 0000000..e01be8a
--- /dev/null
+++ b/audio/aidl/default/primary/StreamPrimary.cpp
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <limits>
+
+#define LOG_TAG "AHAL_StreamPrimary"
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <error/expected_utils.h>
+
+#include "PrimaryMixer.h"
+#include "core-impl/StreamPrimary.h"
+#include "core-impl/StreamStub.h"
+
+using aidl::android::hardware::audio::common::SinkMetadata;
+using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::media::audio::common::AudioDevice;
+using aidl::android::media::audio::common::AudioDeviceDescription;
+using aidl::android::media::audio::common::AudioDeviceType;
+using aidl::android::media::audio::common::AudioOffloadInfo;
+using aidl::android::media::audio::common::MicrophoneInfo;
+using android::base::GetBoolProperty;
+
+namespace aidl::android::hardware::audio::core {
+
+StreamPrimary::StreamPrimary(StreamContext* context, const Metadata& metadata)
+    : StreamAlsa(context, metadata, 3 /*readWriteRetries*/), mIsInput(isInput(metadata)) {}
+
+std::vector<alsa::DeviceProfile> StreamPrimary::getDeviceProfiles() {
+    static const std::vector<alsa::DeviceProfile> kBuiltInSource{
+            alsa::DeviceProfile{.card = primary::PrimaryMixer::kAlsaCard,
+                                .device = primary::PrimaryMixer::kAlsaDevice,
+                                .direction = PCM_IN,
+                                .isExternal = false}};
+    static const std::vector<alsa::DeviceProfile> kBuiltInSink{
+            alsa::DeviceProfile{.card = primary::PrimaryMixer::kAlsaCard,
+                                .device = primary::PrimaryMixer::kAlsaDevice,
+                                .direction = PCM_OUT,
+                                .isExternal = false}};
+    return mIsInput ? kBuiltInSource : kBuiltInSink;
+}
+
+StreamInPrimary::StreamInPrimary(StreamContext&& context, const SinkMetadata& sinkMetadata,
+                                 const std::vector<MicrophoneInfo>& microphones)
+    : StreamIn(std::move(context), microphones),
+      StreamSwitcher(&mContextInstance, sinkMetadata),
+      StreamInHwGainHelper(&mContextInstance) {}
+
+bool StreamInPrimary::useStubStream(const AudioDevice& device) {
+    static const bool kSimulateInput =
+            GetBoolProperty("ro.boot.audio.tinyalsa.simulate_input", false);
+    return kSimulateInput || device.type.type == AudioDeviceType::IN_TELEPHONY_RX ||
+           device.type.type == AudioDeviceType::IN_FM_TUNER ||
+           device.type.connection == AudioDeviceDescription::CONNECTION_BUS;
+}
+
+StreamSwitcher::DeviceSwitchBehavior StreamInPrimary::switchCurrentStream(
+        const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
+    LOG(DEBUG) << __func__;
+    if (devices.size() > 1) {
+        LOG(ERROR) << __func__ << ": primary stream can only be connected to one device, got: "
+                   << devices.size();
+        return DeviceSwitchBehavior::UNSUPPORTED_DEVICES;
+    }
+    if (devices.empty() || useStubStream(devices[0]) == isStubStream()) {
+        return DeviceSwitchBehavior::USE_CURRENT_STREAM;
+    }
+    return DeviceSwitchBehavior::CREATE_NEW_STREAM;
+}
+
+std::unique_ptr<StreamCommonInterfaceEx> StreamInPrimary::createNewStream(
+        const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
+        StreamContext* context, const Metadata& metadata) {
+    if (devices.empty()) {
+        LOG(FATAL) << __func__ << ": called with empty devices";  // see 'switchCurrentStream'
+    }
+    if (useStubStream(devices[0])) {
+        return std::unique_ptr<StreamCommonInterfaceEx>(
+                new InnerStreamWrapper<StreamStub>(context, metadata));
+    }
+    return std::unique_ptr<StreamCommonInterfaceEx>(
+            new InnerStreamWrapper<StreamPrimary>(context, metadata));
+}
+
+ndk::ScopedAStatus StreamInPrimary::getHwGain(std::vector<float>* _aidl_return) {
+    if (isStubStream()) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+    }
+    return getHwGainImpl(_aidl_return);
+}
+
+ndk::ScopedAStatus StreamInPrimary::setHwGain(const std::vector<float>& in_channelGains) {
+    if (isStubStream()) {
+        LOG(DEBUG) << __func__ << ": gains " << ::android::internal::ToString(in_channelGains);
+        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+    }
+    auto currentGains = mHwGains;
+    RETURN_STATUS_IF_ERROR(setHwGainImpl(in_channelGains));
+    if (in_channelGains.size() < 1) {
+        LOG(FATAL) << __func__ << ": unexpected gain vector size: " << in_channelGains.size();
+    }
+    if (auto status = primary::PrimaryMixer::getInstance().setMicGain(in_channelGains[0]);
+        !status.isOk()) {
+        mHwGains = currentGains;
+        return status;
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+StreamOutPrimary::StreamOutPrimary(StreamContext&& context, const SourceMetadata& sourceMetadata,
+                                   const std::optional<AudioOffloadInfo>& offloadInfo)
+    : StreamOut(std::move(context), offloadInfo),
+      StreamSwitcher(&mContextInstance, sourceMetadata),
+      StreamOutHwVolumeHelper(&mContextInstance) {}
+
+bool StreamOutPrimary::useStubStream(const AudioDevice& device) {
+    static const bool kSimulateOutput =
+            GetBoolProperty("ro.boot.audio.tinyalsa.ignore_output", false);
+    return kSimulateOutput || device.type.type == AudioDeviceType::OUT_TELEPHONY_TX ||
+           device.type.connection == AudioDeviceDescription::CONNECTION_BUS;
+}
+
+StreamSwitcher::DeviceSwitchBehavior StreamOutPrimary::switchCurrentStream(
+        const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
+    LOG(DEBUG) << __func__;
+    if (devices.size() > 1) {
+        LOG(ERROR) << __func__ << ": primary stream can only be connected to one device, got: "
+                   << devices.size();
+        return DeviceSwitchBehavior::UNSUPPORTED_DEVICES;
+    }
+    if (devices.empty() || useStubStream(devices[0]) == isStubStream()) {
+        return DeviceSwitchBehavior::USE_CURRENT_STREAM;
+    }
+    return DeviceSwitchBehavior::CREATE_NEW_STREAM;
+}
+
+std::unique_ptr<StreamCommonInterfaceEx> StreamOutPrimary::createNewStream(
+        const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
+        StreamContext* context, const Metadata& metadata) {
+    if (devices.empty()) {
+        LOG(FATAL) << __func__ << ": called with empty devices";  // see 'switchCurrentStream'
+    }
+    if (useStubStream(devices[0])) {
+        return std::unique_ptr<StreamCommonInterfaceEx>(
+                new InnerStreamWrapper<StreamStub>(context, metadata));
+    }
+    return std::unique_ptr<StreamCommonInterfaceEx>(
+            new InnerStreamWrapper<StreamPrimary>(context, metadata));
+}
+
+ndk::ScopedAStatus StreamOutPrimary::getHwVolume(std::vector<float>* _aidl_return) {
+    if (isStubStream()) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+    }
+    return getHwVolumeImpl(_aidl_return);
+}
+
+ndk::ScopedAStatus StreamOutPrimary::setHwVolume(const std::vector<float>& in_channelVolumes) {
+    if (isStubStream()) {
+        LOG(DEBUG) << __func__ << ": volumes " << ::android::internal::ToString(in_channelVolumes);
+        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+    }
+    auto currentVolumes = mHwVolumes;
+    RETURN_STATUS_IF_ERROR(setHwVolumeImpl(in_channelVolumes));
+    if (auto status = primary::PrimaryMixer::getInstance().setVolumes(in_channelVolumes);
+        !status.isOk()) {
+        mHwVolumes = currentVolumes;
+        return status;
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/stub/StreamStub.cpp b/audio/aidl/default/stub/StreamStub.cpp
index 9b6a759..660a51e 100644
--- a/audio/aidl/default/stub/StreamStub.cpp
+++ b/audio/aidl/default/stub/StreamStub.cpp
@@ -33,6 +33,7 @@
 
 StreamStub::StreamStub(StreamContext* context, const Metadata& metadata)
     : StreamCommonImpl(context, metadata),
+      mBufferSizeFrames(getContext().getBufferSizeInFrames()),
       mFrameSizeBytes(getContext().getFrameSize()),
       mSampleRate(getContext().getSampleRate()),
       mIsAsynchronous(!!getContext().getAsyncCallback()),
@@ -40,7 +41,6 @@
 
 ::android::status_t StreamStub::init() {
     mIsInitialized = true;
-    usleep(500);
     return ::android::OK;
 }
 
@@ -48,7 +48,16 @@
     if (!mIsInitialized) {
         LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
     }
-    usleep(500);
+    if (!mIsInput) {
+        if (!mIsAsynchronous) {
+            static constexpr float kMicrosPerSecond = MICROS_PER_SECOND;
+            const size_t delayUs = static_cast<size_t>(
+                    std::roundf(mBufferSizeFrames * kMicrosPerSecond / mSampleRate));
+            usleep(delayUs);
+        } else {
+            usleep(500);
+        }
+    }
     return ::android::OK;
 }
 
@@ -56,7 +65,6 @@
     if (!mIsInitialized) {
         LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
     }
-    usleep(500);
     return ::android::OK;
 }
 
@@ -64,7 +72,6 @@
     if (!mIsInitialized) {
         LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
     }
-    usleep(500);
     return ::android::OK;
 }
 
diff --git a/audio/aidl/default/usb/StreamUsb.cpp b/audio/aidl/default/usb/StreamUsb.cpp
index 4efe0d8..b60b4fd 100644
--- a/audio/aidl/default/usb/StreamUsb.cpp
+++ b/audio/aidl/default/usb/StreamUsb.cpp
@@ -18,14 +18,11 @@
 
 #define LOG_TAG "AHAL_StreamUsb"
 #include <android-base/logging.h>
-
-#include <Utils.h>
 #include <error/expected_utils.h>
 
 #include "UsbAlsaMixerControl.h"
 #include "core-impl/StreamUsb.h"
 
-using aidl::android::hardware::audio::common::getChannelCount;
 using aidl::android::hardware::audio::common::SinkMetadata;
 using aidl::android::hardware::audio::common::SourceMetadata;
 using aidl::android::media::audio::common::AudioDevice;
@@ -97,14 +94,15 @@
                            const std::optional<AudioOffloadInfo>& offloadInfo)
     : StreamOut(std::move(context), offloadInfo),
       StreamUsb(&mContextInstance, sourceMetadata),
-      mChannelCount(getChannelCount(getContext().getChannelLayout())) {}
+      StreamOutHwVolumeHelper(&mContextInstance) {}
 
 ndk::ScopedAStatus StreamOutUsb::getHwVolume(std::vector<float>* _aidl_return) {
-    *_aidl_return = mHwVolumes;
-    return ndk::ScopedAStatus::ok();
+    return getHwVolumeImpl(_aidl_return);
 }
 
 ndk::ScopedAStatus StreamOutUsb::setHwVolume(const std::vector<float>& in_channelVolumes) {
+    auto currentVolumes = mHwVolumes;
+    RETURN_STATUS_IF_ERROR(setHwVolumeImpl(in_channelVolumes));
     // Avoid using mConnectedDeviceProfiles because it requires a lock.
     for (const auto& device : getConnectedDevices()) {
         if (auto deviceProfile = alsa::getDeviceProfile(device, mIsInput);
@@ -114,11 +112,11 @@
                 !result.isOk()) {
                 LOG(ERROR) << __func__
                            << ": failed to set volume for device address=" << *deviceProfile;
+                mHwVolumes = currentVolumes;
                 return result;
             }
         }
     }
-    mHwVolumes = in_channelVolumes;
     return ndk::ScopedAStatus::ok();
 }
 
diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp
index 852255d..f7cf4ce 100644
--- a/audio/aidl/vts/Android.bp
+++ b/audio/aidl/vts/Android.bp
@@ -55,6 +55,7 @@
         "VtsHalAudioCoreConfigTargetTest.cpp",
         "VtsHalAudioCoreModuleTargetTest.cpp",
     ],
+    test_config: "VtsHalAudioCoreTargetTest.xml",
 }
 
 cc_test {
diff --git a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
index 0012cd5..b680373 100644
--- a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
@@ -3189,10 +3189,17 @@
     std::string mUnexpectedTransition;
 };
 
-enum { NAMED_CMD_NAME, NAMED_CMD_DELAY_MS, NAMED_CMD_STREAM_TYPE, NAMED_CMD_CMDS };
+enum {
+    NAMED_CMD_NAME,
+    NAMED_CMD_DELAY_MS,
+    NAMED_CMD_STREAM_TYPE,
+    NAMED_CMD_CMDS,
+    NAMED_CMD_VALIDATE_POS_INCREASE
+};
 enum class StreamTypeFilter { ANY, SYNC, ASYNC };
 using NamedCommandSequence =
-        std::tuple<std::string, int, StreamTypeFilter, std::shared_ptr<StateSequence>>;
+        std::tuple<std::string, int /*cmdDelayMs*/, StreamTypeFilter,
+                   std::shared_ptr<StateSequence>, bool /*validatePositionIncrease*/>;
 enum { PARAM_MODULE_NAME, PARAM_CMD_SEQ, PARAM_SETUP_SEQ };
 using StreamIoTestParameters =
         std::tuple<std::string /*moduleName*/, NamedCommandSequence, bool /*useSetupSequence2*/>;
@@ -3236,10 +3243,14 @@
             ASSERT_NO_FATAL_FAILURE(delayTransientStates.SetUp(module.get()));
             const auto& commandsAndStates =
                     std::get<NAMED_CMD_CMDS>(std::get<PARAM_CMD_SEQ>(GetParam()));
+            const bool validatePositionIncrease =
+                    std::get<NAMED_CMD_VALIDATE_POS_INCREASE>(std::get<PARAM_CMD_SEQ>(GetParam()));
             if (!std::get<PARAM_SETUP_SEQ>(GetParam())) {
-                ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq1(portConfig, commandsAndStates));
+                ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq1(portConfig, commandsAndStates,
+                                                                    validatePositionIncrease));
             } else {
-                ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq2(portConfig, commandsAndStates));
+                ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq2(portConfig, commandsAndStates,
+                                                                    validatePositionIncrease));
             }
             if (isNonBlocking) {
                 // Also try running the same sequence with "aosp.forceTransientBurst" set.
@@ -3250,11 +3261,11 @@
                 if (forceTransientBurst.SetUpNoChecks(module.get(), true /*failureExpected*/)
                             .isOk()) {
                     if (!std::get<PARAM_SETUP_SEQ>(GetParam())) {
-                        ASSERT_NO_FATAL_FAILURE(
-                                RunStreamIoCommandsImplSeq1(portConfig, commandsAndStates));
+                        ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq1(
+                                portConfig, commandsAndStates, validatePositionIncrease));
                     } else {
-                        ASSERT_NO_FATAL_FAILURE(
-                                RunStreamIoCommandsImplSeq2(portConfig, commandsAndStates));
+                        ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq2(
+                                portConfig, commandsAndStates, validatePositionIncrease));
                     }
                 }
             } else if (!IOTraits<Stream>::is_input) {
@@ -3267,11 +3278,11 @@
                 if (forceSynchronousDrain.SetUpNoChecks(module.get(), true /*failureExpected*/)
                             .isOk()) {
                     if (!std::get<PARAM_SETUP_SEQ>(GetParam())) {
-                        ASSERT_NO_FATAL_FAILURE(
-                                RunStreamIoCommandsImplSeq1(portConfig, commandsAndStates));
+                        ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq1(
+                                portConfig, commandsAndStates, validatePositionIncrease));
                     } else {
-                        ASSERT_NO_FATAL_FAILURE(
-                                RunStreamIoCommandsImplSeq2(portConfig, commandsAndStates));
+                        ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq2(
+                                portConfig, commandsAndStates, validatePositionIncrease));
                     }
                 }
             }
@@ -3285,11 +3296,13 @@
 
     // Set up a patch first, then open a stream.
     void RunStreamIoCommandsImplSeq1(const AudioPortConfig& portConfig,
-                                     std::shared_ptr<StateSequence> commandsAndStates) {
+                                     std::shared_ptr<StateSequence> commandsAndStates,
+                                     bool validatePositionIncrease) {
         auto devicePorts = moduleConfig->getAttachedDevicesPortsForMixPort(
                 IOTraits<Stream>::is_input, portConfig);
         ASSERT_FALSE(devicePorts.empty());
         auto devicePortConfig = moduleConfig->getSingleConfigForDevicePort(devicePorts[0]);
+        SCOPED_TRACE(devicePortConfig.toString());
         WithAudioPatch patch(IOTraits<Stream>::is_input, portConfig, devicePortConfig);
         ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
 
@@ -3307,14 +3320,17 @@
         EXPECT_FALSE(worker.hasError()) << worker.getError();
         EXPECT_EQ("", driver.getUnexpectedStateTransition());
         if (ValidateObservablePosition(devicePortConfig)) {
-            EXPECT_TRUE(driver.hasObservablePositionIncrease());
+            if (validatePositionIncrease) {
+                EXPECT_TRUE(driver.hasObservablePositionIncrease());
+            }
             EXPECT_FALSE(driver.hasRetrogradeObservablePosition());
         }
     }
 
     // Open a stream, then set up a patch for it.
     void RunStreamIoCommandsImplSeq2(const AudioPortConfig& portConfig,
-                                     std::shared_ptr<StateSequence> commandsAndStates) {
+                                     std::shared_ptr<StateSequence> commandsAndStates,
+                                     bool validatePositionIncrease) {
         WithStream<Stream> stream(portConfig);
         ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
         StreamLogicDefaultDriver driver(commandsAndStates,
@@ -3326,6 +3342,7 @@
                 IOTraits<Stream>::is_input, portConfig);
         ASSERT_FALSE(devicePorts.empty());
         auto devicePortConfig = moduleConfig->getSingleConfigForDevicePort(devicePorts[0]);
+        SCOPED_TRACE(devicePortConfig.toString());
         WithAudioPatch patch(IOTraits<Stream>::is_input, stream.getPortConfig(), devicePortConfig);
         ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
 
@@ -3336,7 +3353,9 @@
         EXPECT_FALSE(worker.hasError()) << worker.getError();
         EXPECT_EQ("", driver.getUnexpectedStateTransition());
         if (ValidateObservablePosition(devicePortConfig)) {
-            EXPECT_TRUE(driver.hasObservablePositionIncrease());
+            if (validatePositionIncrease) {
+                EXPECT_TRUE(driver.hasObservablePositionIncrease());
+            }
             EXPECT_FALSE(driver.hasRetrogradeObservablePosition());
         }
     }
@@ -3673,22 +3692,28 @@
     using State = StreamDescriptor::State;
     auto d = std::make_unique<StateDag>();
     StateDag::Node last = d->makeFinalNode(State::ACTIVE);
-    StateDag::Node active = d->makeNode(State::ACTIVE, kBurstCommand, last);
+    // Use a couple of bursts to ensure that the driver starts reporting the position.
+    StateDag::Node active2 = d->makeNode(State::ACTIVE, kBurstCommand, last);
+    StateDag::Node active = d->makeNode(State::ACTIVE, kBurstCommand, active2);
     StateDag::Node idle = d->makeNode(State::IDLE, kBurstCommand, active);
     if (!isSync) {
         // Allow optional routing via the TRANSFERRING state on bursts.
-        active.children().push_back(d->makeNode(State::TRANSFERRING, kTransferReadyEvent, last));
+        active2.children().push_back(d->makeNode(State::TRANSFERRING, kTransferReadyEvent, last));
+        active.children().push_back(d->makeNode(State::TRANSFERRING, kTransferReadyEvent, active2));
         idle.children().push_back(d->makeNode(State::TRANSFERRING, kTransferReadyEvent, active));
     }
     d->makeNode(State::STANDBY, kStartCommand, idle);
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
 static const NamedCommandSequence kReadSeq =
-        std::make_tuple(std::string("Read"), 0, StreamTypeFilter::ANY, makeBurstCommands(true));
+        std::make_tuple(std::string("Read"), 0, StreamTypeFilter::ANY, makeBurstCommands(true),
+                        true /*validatePositionIncrease*/);
 static const NamedCommandSequence kWriteSyncSeq =
-        std::make_tuple(std::string("Write"), 0, StreamTypeFilter::SYNC, makeBurstCommands(true));
+        std::make_tuple(std::string("Write"), 0, StreamTypeFilter::SYNC, makeBurstCommands(true),
+                        true /*validatePositionIncrease*/);
 static const NamedCommandSequence kWriteAsyncSeq =
-        std::make_tuple(std::string("Write"), 0, StreamTypeFilter::ASYNC, makeBurstCommands(false));
+        std::make_tuple(std::string("Write"), 0, StreamTypeFilter::ASYNC, makeBurstCommands(false),
+                        true /*validatePositionIncrease*/);
 
 std::shared_ptr<StateSequence> makeAsyncDrainCommands(bool isInput) {
     using State = StreamDescriptor::State;
@@ -3716,11 +3741,12 @@
     }
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
-static const NamedCommandSequence kWriteDrainAsyncSeq =
-        std::make_tuple(std::string("WriteDrain"), kStreamTransientStateTransitionDelayMs,
-                        StreamTypeFilter::ASYNC, makeAsyncDrainCommands(false));
-static const NamedCommandSequence kDrainInSeq = std::make_tuple(
-        std::string("Drain"), 0, StreamTypeFilter::ANY, makeAsyncDrainCommands(true));
+static const NamedCommandSequence kWriteDrainAsyncSeq = std::make_tuple(
+        std::string("WriteDrain"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
+        makeAsyncDrainCommands(false), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kDrainInSeq =
+        std::make_tuple(std::string("Drain"), 0, StreamTypeFilter::ANY,
+                        makeAsyncDrainCommands(true), false /*validatePositionIncrease*/);
 
 std::shared_ptr<StateSequence> makeDrainOutCommands(bool isSync) {
     using State = StreamDescriptor::State;
@@ -3740,10 +3766,12 @@
     d->makeNode(State::STANDBY, kStartCommand, idle);
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
-static const NamedCommandSequence kDrainOutSyncSeq = std::make_tuple(
-        std::string("Drain"), 0, StreamTypeFilter::SYNC, makeDrainOutCommands(true));
-static const NamedCommandSequence kDrainOutAsyncSeq = std::make_tuple(
-        std::string("Drain"), 0, StreamTypeFilter::ASYNC, makeDrainOutCommands(false));
+static const NamedCommandSequence kDrainOutSyncSeq =
+        std::make_tuple(std::string("Drain"), 0, StreamTypeFilter::SYNC, makeDrainOutCommands(true),
+                        false /*validatePositionIncrease*/);
+static const NamedCommandSequence kDrainOutAsyncSeq =
+        std::make_tuple(std::string("Drain"), 0, StreamTypeFilter::ASYNC,
+                        makeDrainOutCommands(false), false /*validatePositionIncrease*/);
 
 std::shared_ptr<StateSequence> makeDrainPauseOutCommands(bool isSync) {
     using State = StreamDescriptor::State;
@@ -3764,12 +3792,12 @@
     d->makeNode(State::STANDBY, kStartCommand, idle);
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
-static const NamedCommandSequence kDrainPauseOutSyncSeq =
-        std::make_tuple(std::string("DrainPause"), kStreamTransientStateTransitionDelayMs,
-                        StreamTypeFilter::SYNC, makeDrainPauseOutCommands(true));
-static const NamedCommandSequence kDrainPauseOutAsyncSeq =
-        std::make_tuple(std::string("DrainPause"), kStreamTransientStateTransitionDelayMs,
-                        StreamTypeFilter::ASYNC, makeDrainPauseOutCommands(false));
+static const NamedCommandSequence kDrainPauseOutSyncSeq = std::make_tuple(
+        std::string("DrainPause"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::SYNC,
+        makeDrainPauseOutCommands(true), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kDrainPauseOutAsyncSeq = std::make_tuple(
+        std::string("DrainPause"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
+        makeDrainPauseOutCommands(false), false /*validatePositionIncrease*/);
 
 // This sequence also verifies that the capture / presentation position is not reset on standby.
 std::shared_ptr<StateSequence> makeStandbyCommands(bool isInput, bool isSync) {
@@ -3810,13 +3838,15 @@
     }
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
-static const NamedCommandSequence kStandbyInSeq = std::make_tuple(
-        std::string("Standby"), 0, StreamTypeFilter::ANY, makeStandbyCommands(true, false));
-static const NamedCommandSequence kStandbyOutSyncSeq = std::make_tuple(
-        std::string("Standby"), 0, StreamTypeFilter::SYNC, makeStandbyCommands(false, true));
-static const NamedCommandSequence kStandbyOutAsyncSeq =
-        std::make_tuple(std::string("Standby"), kStreamTransientStateTransitionDelayMs,
-                        StreamTypeFilter::ASYNC, makeStandbyCommands(false, false));
+static const NamedCommandSequence kStandbyInSeq =
+        std::make_tuple(std::string("Standby"), 0, StreamTypeFilter::ANY,
+                        makeStandbyCommands(true, false), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kStandbyOutSyncSeq =
+        std::make_tuple(std::string("Standby"), 0, StreamTypeFilter::SYNC,
+                        makeStandbyCommands(false, true), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kStandbyOutAsyncSeq = std::make_tuple(
+        std::string("Standby"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
+        makeStandbyCommands(false, false), false /*validatePositionIncrease*/);
 
 std::shared_ptr<StateSequence> makePauseCommands(bool isInput, bool isSync) {
     using State = StreamDescriptor::State;
@@ -3851,13 +3881,15 @@
     }
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
-static const NamedCommandSequence kPauseInSeq = std::make_tuple(
-        std::string("Pause"), 0, StreamTypeFilter::ANY, makePauseCommands(true, false));
-static const NamedCommandSequence kPauseOutSyncSeq = std::make_tuple(
-        std::string("Pause"), 0, StreamTypeFilter::SYNC, makePauseCommands(false, true));
-static const NamedCommandSequence kPauseOutAsyncSeq =
-        std::make_tuple(std::string("Pause"), kStreamTransientStateTransitionDelayMs,
-                        StreamTypeFilter::ASYNC, makePauseCommands(false, false));
+static const NamedCommandSequence kPauseInSeq =
+        std::make_tuple(std::string("Pause"), 0, StreamTypeFilter::ANY,
+                        makePauseCommands(true, false), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kPauseOutSyncSeq =
+        std::make_tuple(std::string("Pause"), 0, StreamTypeFilter::SYNC,
+                        makePauseCommands(false, true), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kPauseOutAsyncSeq = std::make_tuple(
+        std::string("Pause"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
+        makePauseCommands(false, false), false /*validatePositionIncrease*/);
 
 std::shared_ptr<StateSequence> makeFlushCommands(bool isInput, bool isSync) {
     using State = StreamDescriptor::State;
@@ -3884,13 +3916,15 @@
     }
     return std::make_shared<StateSequenceFollower>(std::move(d));
 }
-static const NamedCommandSequence kFlushInSeq = std::make_tuple(
-        std::string("Flush"), 0, StreamTypeFilter::ANY, makeFlushCommands(true, false));
-static const NamedCommandSequence kFlushOutSyncSeq = std::make_tuple(
-        std::string("Flush"), 0, StreamTypeFilter::SYNC, makeFlushCommands(false, true));
-static const NamedCommandSequence kFlushOutAsyncSeq =
-        std::make_tuple(std::string("Flush"), kStreamTransientStateTransitionDelayMs,
-                        StreamTypeFilter::ASYNC, makeFlushCommands(false, false));
+static const NamedCommandSequence kFlushInSeq =
+        std::make_tuple(std::string("Flush"), 0, StreamTypeFilter::ANY,
+                        makeFlushCommands(true, false), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kFlushOutSyncSeq =
+        std::make_tuple(std::string("Flush"), 0, StreamTypeFilter::SYNC,
+                        makeFlushCommands(false, true), false /*validatePositionIncrease*/);
+static const NamedCommandSequence kFlushOutAsyncSeq = std::make_tuple(
+        std::string("Flush"), kStreamTransientStateTransitionDelayMs, StreamTypeFilter::ASYNC,
+        makeFlushCommands(false, false), false /*validatePositionIncrease*/);
 
 std::shared_ptr<StateSequence> makeDrainPauseFlushOutCommands(bool isSync) {
     using State = StreamDescriptor::State;
@@ -3911,10 +3945,12 @@
 }
 static const NamedCommandSequence kDrainPauseFlushOutSyncSeq =
         std::make_tuple(std::string("DrainPauseFlush"), kStreamTransientStateTransitionDelayMs,
-                        StreamTypeFilter::SYNC, makeDrainPauseFlushOutCommands(true));
+                        StreamTypeFilter::SYNC, makeDrainPauseFlushOutCommands(true),
+                        false /*validatePositionIncrease*/);
 static const NamedCommandSequence kDrainPauseFlushOutAsyncSeq =
         std::make_tuple(std::string("DrainPauseFlush"), kStreamTransientStateTransitionDelayMs,
-                        StreamTypeFilter::ASYNC, makeDrainPauseFlushOutCommands(false));
+                        StreamTypeFilter::ASYNC, makeDrainPauseFlushOutCommands(false),
+                        false /*validatePositionIncrease*/);
 
 // Note, this isn't the "official" enum printer, it is only used to make the test name suffix.
 std::string PrintStreamFilterToString(StreamTypeFilter filter) {
diff --git a/audio/aidl/vts/VtsHalAudioCoreTargetTest.xml b/audio/aidl/vts/VtsHalAudioCoreTargetTest.xml
index dfc1039..9d3adc1 100644
--- a/audio/aidl/vts/VtsHalAudioCoreTargetTest.xml
+++ b/audio/aidl/vts/VtsHalAudioCoreTargetTest.xml
@@ -25,6 +25,11 @@
         <option name="teardown-command" value="setprop vts.native_server.on 0"/>
     </target_preparer>
 
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="VtsHalAudioCoreTargetTest->/data/local/tmp/VtsHalAudioCoreTargetTest" />
+    </target_preparer>
+
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="VtsHalAudioCoreTargetTest" />
diff --git a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
index ec28846..54076c8 100644
--- a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
+++ b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
@@ -385,6 +385,11 @@
         cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
         return;
     }
+    clearLockout(cb);
+    isLockoutTimerAborted = true;
+}
+
+void FakeFingerprintEngine::clearLockout(ISessionCallback* cb) {
     FingerprintHalProperties::lockout(false);
     cb->onLockoutCleared();
     mLockoutTracker.reset();
@@ -574,13 +579,34 @@
     if (lockoutMode == FakeLockoutTracker::LockoutMode::kPermanent) {
         LOG(ERROR) << "Fail: lockout permanent";
         cb->onLockoutPermanent();
+        isLockoutTimerAborted = true;
         return true;
     } else if (lockoutMode == FakeLockoutTracker::LockoutMode::kTimed) {
         int64_t timeLeft = mLockoutTracker.getLockoutTimeLeft();
         LOG(ERROR) << "Fail: lockout timed " << timeLeft;
         cb->onLockoutTimed(timeLeft);
+        if (isLockoutTimerSupported && !isLockoutTimerStarted) startLockoutTimer(timeLeft, cb);
         return true;
     }
     return false;
 }
+
+void FakeFingerprintEngine::startLockoutTimer(int64_t timeout, ISessionCallback* cb) {
+    BEGIN_OP(0);
+    std::function<void(ISessionCallback*)> action =
+            std::bind(&FakeFingerprintEngine::lockoutTimerExpired, this, std::placeholders::_1);
+    std::thread([timeout, action, cb]() {
+        std::this_thread::sleep_for(std::chrono::milliseconds(timeout));
+        action(cb);
+    }).detach();
+
+    isLockoutTimerStarted = true;
+}
+void FakeFingerprintEngine::lockoutTimerExpired(ISessionCallback* cb) {
+    if (!isLockoutTimerAborted) {
+        clearLockout(cb);
+    }
+    isLockoutTimerStarted = false;
+    isLockoutTimerAborted = false;
+}
 }  // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/FakeFingerprintEngineSide.cpp b/biometrics/fingerprint/aidl/default/FakeFingerprintEngineSide.cpp
index 6982072..a78cdcd 100644
--- a/biometrics/fingerprint/aidl/default/FakeFingerprintEngineSide.cpp
+++ b/biometrics/fingerprint/aidl/default/FakeFingerprintEngineSide.cpp
@@ -27,6 +27,10 @@
 
 namespace aidl::android::hardware::biometrics::fingerprint {
 
+FakeFingerprintEngineSide::FakeFingerprintEngineSide() : FakeFingerprintEngine() {
+    isLockoutTimerSupported = true;
+}
+
 SensorLocation FakeFingerprintEngineSide::defaultSensorLocation() {
     return SensorLocation{.sensorLocationX = defaultSensorLocationX,
                           .sensorLocationY = defaultSensorLocationY,
diff --git a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
index a06b786..2450115 100644
--- a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
+++ b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
@@ -114,8 +114,20 @@
                                       std::vector<std::vector<int32_t>>& res);
     int32_t getRandomInRange(int32_t bound1, int32_t bound2);
     bool checkSensorLockout(ISessionCallback*);
+    void clearLockout(ISessionCallback* cb);
 
     FakeLockoutTracker mLockoutTracker;
+
+  protected:
+    // lockout timer
+    void lockoutTimerExpired(ISessionCallback* cb);
+    bool isLockoutTimerSupported;
+    bool isLockoutTimerStarted;
+    bool isLockoutTimerAborted;
+
+  public:
+    void startLockoutTimer(int64_t timeout, ISessionCallback* cb);
+    bool getLockoutTimerStarted() { return isLockoutTimerStarted; }
 };
 
 }  // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineSide.h b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineSide.h
index c2fc005..67a3ebc 100644
--- a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineSide.h
+++ b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineSide.h
@@ -28,7 +28,7 @@
     static constexpr int32_t defaultSensorLocationY = 600;
     static constexpr int32_t defaultSensorRadius = 150;
 
-    FakeFingerprintEngineSide() : FakeFingerprintEngine() {}
+    FakeFingerprintEngineSide();
     ~FakeFingerprintEngineSide() {}
 
     virtual SensorLocation defaultSensorLocation() override;
diff --git a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
index bc235a6..fe405f4 100644
--- a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
+++ b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
@@ -93,9 +93,13 @@
         return ndk::ScopedAStatus::ok();
     };
     ndk::ScopedAStatus onLockoutTimed(int64_t /* timeout */) override {
+        mLockoutTimed = true;
         return ndk::ScopedAStatus::ok();
     }
-    ndk::ScopedAStatus onLockoutCleared() override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus onLockoutCleared() override {
+        mLockoutCleared = true;
+        return ndk::ScopedAStatus::ok();
+    }
     ndk::ScopedAStatus onSessionClosed() override { return ndk::ScopedAStatus::ok(); }
 
     Error mError = Error::UNKNOWN;
@@ -110,6 +114,8 @@
     bool mAuthenticateFailed = false;
     bool mAuthenticatorIdInvalidated = false;
     bool mLockoutPermanent = false;
+    bool mLockoutTimed = false;
+    bool mLockoutCleared = false;
     int mInteractionDetectedCount = 0;
     int32_t mLastAcquiredInfo = -1;
     int32_t mLastAcquiredVendorCode = -1;
@@ -499,6 +505,13 @@
     ASSERT_TRUE(latencySet.size() > 95);
 }
 
+TEST_F(FakeFingerprintEngineTest, lockoutTimer) {
+    mEngine.startLockoutTimer(200, mCallback.get());
+    ASSERT_TRUE(mEngine.getLockoutTimerStarted());
+    std::this_thread::sleep_for(std::chrono::milliseconds(210));
+    ASSERT_FALSE(mEngine.getLockoutTimerStarted());
+    ASSERT_TRUE(mCallback->mLockoutCleared);
+}
 }  // namespace aidl::android::hardware::biometrics::fingerprint
 
 int main(int argc, char** argv) {
diff --git a/bluetooth/aidl/default/BluetoothHci.cpp b/bluetooth/aidl/default/BluetoothHci.cpp
index 782122f..013ab7f 100644
--- a/bluetooth/aidl/default/BluetoothHci.cpp
+++ b/bluetooth/aidl/default/BluetoothHci.cpp
@@ -55,6 +55,19 @@
 
 void OnDeath(void* cookie);
 
+std::optional<std::string> GetSystemProperty(const std::string& property) {
+  std::array<char, PROPERTY_VALUE_MAX> value_array{0};
+  auto value_len = property_get(property.c_str(), value_array.data(), nullptr);
+  if (value_len <= 0) {
+    return std::nullopt;
+  }
+  return std::string(value_array.data(), value_len);
+}
+
+bool starts_with(const std::string& str, const std::string& prefix) {
+  return str.compare(0, prefix.length(), prefix) == 0;
+}
+
 class BluetoothDeathRecipient {
  public:
   BluetoothDeathRecipient(BluetoothHci* hci) : mHci(hci) {}
@@ -232,8 +245,19 @@
 
   mDeathRecipient->LinkToDeath(mCb);
 
-  // TODO: This should not be necessary when the device implements rfkill.
-  reset();
+  // TODO: HCI Reset on emulators since the bluetooth controller
+  // cannot be powered on/off during the HAL setup; and the stack
+  // might received spurious packets/events during boottime.
+  // Proper solution would be to use bt-virtio or vsock to better
+  // control the link to rootcanal and the controller lifetime.
+  const std::string kBoardProperty = "ro.product.board";
+  const std::string kCuttlefishBoard = "cutf";
+  auto board_name = GetSystemProperty(kBoardProperty);
+  if (board_name.has_value() && (
+        starts_with(board_name.value(), "cutf") ||
+        starts_with(board_name.value(), "goldfish"))) {
+    reset();
+  }
 
   mH4 = std::make_shared<H4Protocol>(
       mFd,
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
index c99478f..0bcafa3 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
@@ -441,6 +441,16 @@
 void BluetoothAudioSession::ReportLowLatencyModeAllowedChanged(bool allowed) {
   std::lock_guard<std::recursive_mutex> guard(mutex_);
   low_latency_allowed_ = allowed;
+  // TODO(b/294498919): Remove this after there is API to update latency mode
+  // after audio session started. If low_latency_allowed_ is true, the session
+  // can support LOW_LATENCY and FREE LatencyMode.
+  if (low_latency_allowed_) {
+    if (std::find(latency_modes_.begin(), latency_modes_.end(),
+                  LatencyMode::LOW_LATENCY) == latency_modes_.end()) {
+      LOG(INFO) << __func__ << " - insert LOW_LATENCY LatencyMode";
+      latency_modes_.push_back(LatencyMode::LOW_LATENCY);
+    }
+  }
   if (observers_.empty()) {
     LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
                  << " has NO port state observer";
diff --git a/camera/device/default/ExternalCameraDeviceSession.cpp b/camera/device/default/ExternalCameraDeviceSession.cpp
index c962974..95a36f0 100644
--- a/camera/device/default/ExternalCameraDeviceSession.cpp
+++ b/camera/device/default/ExternalCameraDeviceSession.cpp
@@ -224,10 +224,6 @@
 }
 
 void ExternalCameraDeviceSession::closeOutputThread() {
-    closeOutputThreadImpl();
-}
-
-void ExternalCameraDeviceSession::closeOutputThreadImpl() {
     if (mOutputThread != nullptr) {
         mOutputThread->flush();
         mOutputThread->requestExitAndWait();
@@ -235,6 +231,13 @@
     }
 }
 
+void ExternalCameraDeviceSession::closeBufferRequestThread() {
+    if (mBufferRequestThread != nullptr) {
+        mBufferRequestThread->requestExitAndWait();
+        mBufferRequestThread.reset();
+    }
+}
+
 Status ExternalCameraDeviceSession::initStatus() const {
     Mutex::Autolock _l(mLock);
     Status status = Status::OK;
@@ -248,7 +251,7 @@
 ExternalCameraDeviceSession::~ExternalCameraDeviceSession() {
     if (!isClosed()) {
         ALOGE("ExternalCameraDeviceSession deleted before close!");
-        close(/*callerIsDtor*/ true);
+        closeImpl();
     }
 }
 
@@ -1411,19 +1414,16 @@
 }
 
 ScopedAStatus ExternalCameraDeviceSession::close() {
-    close(false);
+    closeImpl();
     return fromStatus(Status::OK);
 }
 
-void ExternalCameraDeviceSession::close(bool callerIsDtor) {
+void ExternalCameraDeviceSession::closeImpl() {
     Mutex::Autolock _il(mInterfaceLock);
     bool closed = isClosed();
     if (!closed) {
-        if (callerIsDtor) {
-            closeOutputThreadImpl();
-        } else {
-            closeOutputThread();
-        }
+        closeOutputThread();
+        closeBufferRequestThread();
 
         Mutex::Autolock _l(mLock);
         // free all buffers
diff --git a/camera/device/default/ExternalCameraDeviceSession.h b/camera/device/default/ExternalCameraDeviceSession.h
index e7eb799..836266f 100644
--- a/camera/device/default/ExternalCameraDeviceSession.h
+++ b/camera/device/default/ExternalCameraDeviceSession.h
@@ -240,9 +240,9 @@
     // To init/close different version of output thread
     void initOutputThread();
     void closeOutputThread();
-    void closeOutputThreadImpl();
+    void closeBufferRequestThread();
 
-    void close(bool callerIsDtor);
+    void closeImpl();
     Status initStatus() const;
     status_t initDefaultRequests();
 
diff --git a/cas/1.0/default/android.hardware.cas@1.0-service-lazy.rc b/cas/1.0/default/android.hardware.cas@1.0-service-lazy.rc
index 622ee8f..1a08ebc 100644
--- a/cas/1.0/default/android.hardware.cas@1.0-service-lazy.rc
+++ b/cas/1.0/default/android.hardware.cas@1.0-service-lazy.rc
@@ -5,5 +5,6 @@
     class hal
     user media
     group mediadrm drmrpc
+    capabilities SYS_NICE
     ioprio rt 4
     task_profiles ProcessCapacityHigh
diff --git a/cas/1.0/default/android.hardware.cas@1.0-service.rc b/cas/1.0/default/android.hardware.cas@1.0-service.rc
index 5df4825..a65160a 100644
--- a/cas/1.0/default/android.hardware.cas@1.0-service.rc
+++ b/cas/1.0/default/android.hardware.cas@1.0-service.rc
@@ -2,5 +2,6 @@
     class hal
     user media
     group mediadrm drmrpc
+    capabilities SYS_NICE
     ioprio rt 4
     task_profiles ProcessCapacityHigh
diff --git a/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc b/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc
index 0721dc3..9fca8fd 100644
--- a/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc
+++ b/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc
@@ -6,5 +6,6 @@
     class hal
     user media
     group mediadrm drmrpc
+    capabilities SYS_NICE
     ioprio rt 4
     task_profiles ProcessCapacityHigh
diff --git a/cas/1.1/default/android.hardware.cas@1.1-service.rc b/cas/1.1/default/android.hardware.cas@1.1-service.rc
index 132d943..19fd031 100644
--- a/cas/1.1/default/android.hardware.cas@1.1-service.rc
+++ b/cas/1.1/default/android.hardware.cas@1.1-service.rc
@@ -2,5 +2,6 @@
     class hal
     user media
     group mediadrm drmrpc
+    capabilities SYS_NICE
     ioprio rt 4
     task_profiles ProcessCapacityHigh
diff --git a/cas/1.2/default/android.hardware.cas@1.2-service-lazy.rc b/cas/1.2/default/android.hardware.cas@1.2-service-lazy.rc
index d91fdce..8c2a894 100644
--- a/cas/1.2/default/android.hardware.cas@1.2-service-lazy.rc
+++ b/cas/1.2/default/android.hardware.cas@1.2-service-lazy.rc
@@ -7,5 +7,6 @@
     class hal
     user media
     group mediadrm drmrpc
+    capabilities SYS_NICE
     ioprio rt 4
     task_profiles ProcessCapacityHigh
diff --git a/cas/1.2/default/android.hardware.cas@1.2-service.rc b/cas/1.2/default/android.hardware.cas@1.2-service.rc
index b22971a..4b638bc 100644
--- a/cas/1.2/default/android.hardware.cas@1.2-service.rc
+++ b/cas/1.2/default/android.hardware.cas@1.2-service.rc
@@ -2,5 +2,6 @@
     class hal
     user media
     group mediadrm drmrpc
+    capabilities SYS_NICE
     ioprio rt 4
     task_profiles ProcessCapacityHigh
diff --git a/cas/aidl/default/cas-default-lazy.rc b/cas/aidl/default/cas-default-lazy.rc
index 60b59ca..7321cf0 100644
--- a/cas/aidl/default/cas-default-lazy.rc
+++ b/cas/aidl/default/cas-default-lazy.rc
@@ -3,6 +3,7 @@
     class hal
     user media
     group mediadrm drmrpc
+    capabilities SYS_NICE
     ioprio rt 4
     task_profiles ProcessCapacityHigh
     oneshot
diff --git a/cas/aidl/default/cas-default.rc b/cas/aidl/default/cas-default.rc
index e00b9c5..5a60368 100644
--- a/cas/aidl/default/cas-default.rc
+++ b/cas/aidl/default/cas-default.rc
@@ -3,5 +3,6 @@
     class hal
     user media
     group mediadrm drmrpc
+    capabilities SYS_NICE
     ioprio rt 4
     task_profiles ProcessCapacityHigh
diff --git a/compatibility_matrices/compatibility_matrix.7.xml b/compatibility_matrices/compatibility_matrix.7.xml
index 33c3148..14c330e 100644
--- a/compatibility_matrices/compatibility_matrix.7.xml
+++ b/compatibility_matrices/compatibility_matrix.7.xml
@@ -43,6 +43,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.automotive.audiocontrol</name>
+        <version>1-2</version>
         <interface>
             <name>IAudioControl</name>
             <instance>default</instance>
@@ -262,22 +263,6 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
-        <name>android.hardware.gnss.visibility_control</name>
-        <version>1</version>
-        <interface>
-            <name>IGnssVisibilityControl</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="aidl" optional="true">
-        <name>android.hardware.gnss.measurement_corrections</name>
-        <version>1</version>
-        <interface>
-            <name>IMeasurementCorrectionsInterface</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.graphics.allocator</name>
         <!-- New, non-Go devices should use 4.0 or the AIDL hal. -->
diff --git a/compatibility_matrices/compatibility_matrix.8.xml b/compatibility_matrices/compatibility_matrix.8.xml
index 04a4674..67c21c8 100644
--- a/compatibility_matrices/compatibility_matrix.8.xml
+++ b/compatibility_matrices/compatibility_matrix.8.xml
@@ -231,22 +231,6 @@
         </interface>
     </hal>
     <hal format="aidl" optional="true">
-        <name>android.hardware.gnss.visibility_control</name>
-        <version>1</version>
-        <interface>
-            <name>IGnssVisibilityControl</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="aidl" optional="true">
-        <name>android.hardware.gnss.measurement_corrections</name>
-        <version>1</version>
-        <interface>
-            <name>IMeasurementCorrectionsInterface</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="aidl" optional="true">
         <name>android.hardware.graphics.allocator</name>
         <version>1-2</version>
         <interface>
diff --git a/compatibility_matrices/compatibility_matrix.9.xml b/compatibility_matrices/compatibility_matrix.9.xml
index 0928f14..e8ceebe 100644
--- a/compatibility_matrices/compatibility_matrix.9.xml
+++ b/compatibility_matrices/compatibility_matrix.9.xml
@@ -223,22 +223,6 @@
         </interface>
     </hal>
     <hal format="aidl" optional="true">
-        <name>android.hardware.gnss.visibility_control</name>
-        <version>1</version>
-        <interface>
-            <name>IGnssVisibilityControl</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="aidl" optional="true">
-        <name>android.hardware.gnss.measurement_corrections</name>
-        <version>1</version>
-        <interface>
-            <name>IMeasurementCorrectionsInterface</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="aidl" optional="true">
         <name>android.hardware.graphics.allocator</name>
         <version>1-2</version>
         <interface>
@@ -318,7 +302,7 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
+    <hal format="aidl" optional="true" updatable-via-apex="true">
         <name>android.hardware.security.keymint</name>
         <version>1-3</version>
         <interface>
@@ -327,7 +311,7 @@
             <instance>strongbox</instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
+    <hal format="aidl" optional="true" updatable-via-apex="true">
         <name>android.hardware.security.keymint</name>
         <version>1-3</version>
         <interface>
@@ -397,7 +381,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.power</name>
-        <version>4</version>
+        <version>5</version>
         <interface>
             <name>IPower</name>
             <instance>default</instance>
@@ -534,7 +518,7 @@
             <regex-instance>SIM[1-9][0-9]*</regex-instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
+    <hal format="aidl" optional="true" updatable-via-apex="true">
         <name>android.hardware.security.secureclock</name>
         <version>1</version>
         <interface>
@@ -542,7 +526,7 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
+    <hal format="aidl" optional="true" updatable-via-apex="true">
         <name>android.hardware.security.sharedsecret</name>
         <version>1</version>
         <interface>
diff --git a/compatibility_matrices/exclude/fcm_exclude.cpp b/compatibility_matrices/exclude/fcm_exclude.cpp
index ccce449..d92c0b9 100644
--- a/compatibility_matrices/exclude/fcm_exclude.cpp
+++ b/compatibility_matrices/exclude/fcm_exclude.cpp
@@ -24,9 +24,7 @@
 namespace android::vintf::details {
 
 // The predicate to VintfObject::checkMissingHalsInMatrices.
-bool ShouldCheckMissingHalsInFcm(const std::string& package) {
-    using std::placeholders::_1;
-
+bool ShouldCheckMissingHidlHalsInFcm(const std::string& packageAndVersion) {
     static std::vector<std::string> included_prefixes{
             // Other AOSP HALs (e.g. android.frameworks.*) are not added because only framework
             // matrix is checked.
@@ -51,28 +49,11 @@
             "android.hardware.media.bufferpool@1.0",
             "android.hardware.media.bufferpool@2.0",
             "android.hardware.radio.config@1.2",
-            // AIDL
-            "android.hardware.audio.common",
-            "android.hardware.audio.core.sounddose",
-            "android.hardware.biometrics.common",
-            "android.hardware.camera.metadata",
-            "android.hardware.camera.device",
-            "android.hardware.camera.common",
-            "android.hardware.common",
-            "android.hardware.common.fmq",
-            "android.hardware.graphics.common",
-            "android.hardware.input.common",
-            "android.hardware.keymaster",
-            "android.hardware.media.bufferpool2",
-            "android.hardware.radio",
-            "android.hardware.uwb.fira_android",
 
             // Fastboot HAL is only used by recovery. Recovery is owned by OEM. Framework
             // does not depend on this HAL, hence it is not declared in any manifests or matrices.
             "android.hardware.fastboot@1.0",
             "android.hardware.fastboot@1.1",
-            // Fastboot AIDL
-            "android.hardware.fastboot",
 
             // Deprecated HALs.
             // HIDL
@@ -106,7 +87,7 @@
     };
 
     auto package_has_prefix = [&](const std::string& prefix) {
-        return android::base::StartsWith(package, prefix);
+        return android::base::StartsWith(packageAndVersion, prefix);
     };
 
     // Only check packageAndVersions that are in the include list and not in the exclude list.
@@ -114,7 +95,69 @@
         return false;
     }
 
-    if (std::find(excluded_exact.begin(), excluded_exact.end(), package) != excluded_exact.end()) {
+    if (std::find(excluded_exact.begin(), excluded_exact.end(), packageAndVersion) !=
+        excluded_exact.end()) {
+        return false;
+    }
+
+    return !std::any_of(excluded_prefixes.begin(), excluded_prefixes.end(), package_has_prefix);
+}
+
+// The predicate to VintfObject::checkMissingHalsInMatrices.
+bool ShouldCheckMissingAidlHalsInFcm(const std::string& packageAndVersion) {
+    static std::vector<std::string> included_prefixes{
+            // Other AOSP HALs (e.g. android.frameworks.*) are not added because only framework
+            // matrix is checked.
+            "android.hardware.",
+    };
+
+    static std::vector<std::string> excluded_prefixes{
+            // Packages without top level interfaces (including types-only packages) are exempted.
+            "android.hardware.audio.common@",
+            "android.hardware.biometrics.common@",
+            "android.hardware.camera.metadata@",
+            "android.hardware.camera.device@",
+            "android.hardware.camera.common@",
+            "android.hardware.common@",
+            "android.hardware.common.fmq@",
+            "android.hardware.gnss.measurement_corrections@",
+            "android.hardware.gnss.visibility_control@",
+            "android.hardware.graphics.common@",
+            "android.hardware.input.common@",
+            "android.hardware.keymaster@",
+            "android.hardware.media.bufferpool2@",
+            "android.hardware.radio@",
+            "android.hardware.uwb.fira_android@",
+
+            // Test packages are exempted.
+            "android.hardware.tests.",
+
+            // Fastboot HAL is only used by recovery. Recovery is owned by OEM. Framework
+            // does not depend on this HAL, hence it is not declared in any manifests or matrices.
+            "android.hardware.fastboot@",
+    };
+
+    static std::vector<std::string> excluded_exact{
+            // Packages without top level interfaces (including types-only packages) are exempted.
+
+            // AIDL
+            "android.hardware.audio.core.sounddose@1",
+
+            // Deprecated HALs.
+            "android.hardware.bluetooth.audio@1",
+    };
+
+    auto package_has_prefix = [&](const std::string& prefix) {
+        return android::base::StartsWith(packageAndVersion, prefix);
+    };
+
+    // Only check packageAndVersions that are in the include list and not in the exclude list.
+    if (!std::any_of(included_prefixes.begin(), included_prefixes.end(), package_has_prefix)) {
+        return false;
+    }
+
+    if (std::find(excluded_exact.begin(), excluded_exact.end(), packageAndVersion) !=
+        excluded_exact.end()) {
         return false;
     }
 
diff --git a/compatibility_matrices/exclude/include/vintf/fcm_exclude.h b/compatibility_matrices/exclude/include/vintf/fcm_exclude.h
index f74c217..e7ef4a0 100644
--- a/compatibility_matrices/exclude/include/vintf/fcm_exclude.h
+++ b/compatibility_matrices/exclude/include/vintf/fcm_exclude.h
@@ -24,7 +24,8 @@
 // Determine whether VINTF checks |package| is missing from FCMs.
 // |package| can be a HIDL package and version like
 // "android.hardware.foo@1.0", or an AIDL package name like
-// "android.hardware.foo".
-bool ShouldCheckMissingHalsInFcm(const std::string& package);
+// "android.hardware.foo@1".
+bool ShouldCheckMissingHidlHalsInFcm(const std::string& packageAndVersion);
+bool ShouldCheckMissingAidlHalsInFcm(const std::string& packageAndVersion);
 
 }  // namespace android::vintf::details
diff --git a/gatekeeper/aidl/vts/functional/VtsHalGatekeeperTargetTest.cpp b/gatekeeper/aidl/vts/functional/VtsHalGatekeeperTargetTest.cpp
index c89243b..032f7e2 100644
--- a/gatekeeper/aidl/vts/functional/VtsHalGatekeeperTargetTest.cpp
+++ b/gatekeeper/aidl/vts/functional/VtsHalGatekeeperTargetTest.cpp
@@ -221,6 +221,47 @@
 }
 
 /**
+ * Ensure that passwords containing a NUL byte aren't truncated
+ */
+TEST_P(GatekeeperAidlTest, PasswordIsBinaryData) {
+    GatekeeperEnrollResponse enrollRsp;
+    GatekeeperVerifyResponse verifyRsp;
+    std::vector<uint8_t> rightPassword = {'A', 'B', 'C', '\0', 'D', 'E', 'F'};
+    std::vector<uint8_t> wrongPassword = {'A', 'B', 'C', '\0', '\0', '\0', '\0'};
+
+    ALOGI("Testing Enroll+Verify of password with embedded NUL (expected success)");
+    enrollNewPassword(rightPassword, enrollRsp, true);
+    verifyPassword(rightPassword, enrollRsp.data, 1, verifyRsp, true);
+
+    ALOGI("Testing Verify of wrong password (expected failure)");
+    verifyPassword(wrongPassword, enrollRsp.data, 1, verifyRsp, false);
+
+    ALOGI("PasswordIsBinaryData test done");
+}
+
+/**
+ * Ensure that long passwords aren't truncated
+ */
+TEST_P(GatekeeperAidlTest, LongPassword) {
+    GatekeeperEnrollResponse enrollRsp;
+    GatekeeperVerifyResponse verifyRsp;
+    std::vector<uint8_t> password;
+
+    password.resize(64);  // maximum length used by Android
+    memset(password.data(), 'A', password.size());
+
+    ALOGI("Testing Enroll+Verify of long password (expected success)");
+    enrollNewPassword(password, enrollRsp, true);
+    verifyPassword(password, enrollRsp.data, 1, verifyRsp, true);
+
+    ALOGI("Testing Verify of wrong password (expected failure)");
+    password[password.size() - 1] ^= 1;
+    verifyPassword(password, enrollRsp.data, 1, verifyRsp, false);
+
+    ALOGI("LongPassword test done");
+}
+
+/**
  * Ensure we can securely update password (keep the same
  * secure user_id) if we prove we know old password
  */
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index 03d9041..bae362f 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -2223,11 +2223,14 @@
     // Keep optional metadata types below and populate the encoded metadata vec
     // with some arbitrary different metadata because the common gralloc4::decode*()
     // functions do not distinguish between an empty vec and bad value.
-    ASSERT_EQ(NO_ERROR, gralloc4::encodeDataspace(Dataspace::SRGB_LINEAR, &vec));
-    ASSERT_EQ(Error::UNSUPPORTED,
-              mGralloc->set(bufferHandle, gralloc4::MetadataType_Smpte2086, vec));
-    ASSERT_EQ(Error::UNSUPPORTED,
-              mGralloc->set(bufferHandle, gralloc4::MetadataType_Cta861_3, vec));
+    if (base::GetIntProperty("ro.vendor.api_level", __ANDROID_API_FUTURE__) >= __ANDROID_API_T__) {
+        // Some old grallocs shipped with broken validation.
+        ASSERT_EQ(NO_ERROR, gralloc4::encodeDataspace(Dataspace::SRGB_LINEAR, &vec));
+        ASSERT_EQ(Error::UNSUPPORTED,
+                  mGralloc->set(bufferHandle, gralloc4::MetadataType_Smpte2086, vec));
+        ASSERT_EQ(Error::UNSUPPORTED,
+                  mGralloc->set(bufferHandle, gralloc4::MetadataType_Cta861_3, vec));
+    }
 }
 
 /**
diff --git a/power/aidl/Android.bp b/power/aidl/Android.bp
index 082572d..7643926 100644
--- a/power/aidl/Android.bp
+++ b/power/aidl/Android.bp
@@ -55,6 +55,44 @@
         },
 
     ],
-    frozen: true,
+    frozen: false,
 
 }
+
+cc_defaults {
+    name: "android.hardware.power-ndk_shared",
+    shared_libs: [
+        "android.hardware.power-V5-ndk",
+    ],
+}
+
+cc_defaults {
+    name: "android.hardware.power-ndk_export_shared",
+    shared_libs: [
+        "android.hardware.power-V5-ndk",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.power-V5-ndk",
+    ],
+}
+
+cc_defaults {
+    name: "android.hardware.power-ndk_static",
+    static_libs: [
+        "android.hardware.power-V5-ndk",
+    ],
+}
+
+java_defaults {
+    name: "android.hardware.power-java_shared",
+    libs: [
+        "android.hardware.power-V5-java",
+    ],
+}
+
+java_defaults {
+    name: "android.hardware.power-java_static",
+    static_libs: [
+        "android.hardware.power-V5-java",
+    ],
+}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Boost.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Boost.aidl
index c792d4e..8ee15ef 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Boost.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Boost.aidl
@@ -34,10 +34,10 @@
 package android.hardware.power;
 @Backing(type="int") @VintfStability
 enum Boost {
-  INTERACTION = 0,
-  DISPLAY_UPDATE_IMMINENT = 1,
-  ML_ACC = 2,
-  AUDIO_LAUNCH = 3,
-  CAMERA_LAUNCH = 4,
-  CAMERA_SHOT = 5,
+  INTERACTION,
+  DISPLAY_UPDATE_IMMINENT,
+  ML_ACC,
+  AUDIO_LAUNCH,
+  CAMERA_LAUNCH,
+  CAMERA_SHOT,
 }
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl
index e6809da..6bc663e 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl
@@ -41,4 +41,5 @@
   oneway void close();
   oneway void sendHint(android.hardware.power.SessionHint hint);
   void setThreads(in int[] threadIds);
+  oneway void setMode(android.hardware.power.SessionMode type, boolean enabled);
 }
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl
index f38426b..efbb300 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/Mode.aidl
@@ -34,21 +34,21 @@
 package android.hardware.power;
 @Backing(type="int") @VintfStability
 enum Mode {
-  DOUBLE_TAP_TO_WAKE = 0,
-  LOW_POWER = 1,
-  SUSTAINED_PERFORMANCE = 2,
-  FIXED_PERFORMANCE = 3,
-  VR = 4,
-  LAUNCH = 5,
-  EXPENSIVE_RENDERING = 6,
-  INTERACTIVE = 7,
-  DEVICE_IDLE = 8,
-  DISPLAY_INACTIVE = 9,
-  AUDIO_STREAMING_LOW_LATENCY = 10,
-  CAMERA_STREAMING_SECURE = 11,
-  CAMERA_STREAMING_LOW = 12,
-  CAMERA_STREAMING_MID = 13,
-  CAMERA_STREAMING_HIGH = 14,
-  GAME = 15,
-  GAME_LOADING = 16,
+  DOUBLE_TAP_TO_WAKE,
+  LOW_POWER,
+  SUSTAINED_PERFORMANCE,
+  FIXED_PERFORMANCE,
+  VR,
+  LAUNCH,
+  EXPENSIVE_RENDERING,
+  INTERACTIVE,
+  DEVICE_IDLE,
+  DISPLAY_INACTIVE,
+  AUDIO_STREAMING_LOW_LATENCY,
+  CAMERA_STREAMING_SECURE,
+  CAMERA_STREAMING_LOW,
+  CAMERA_STREAMING_MID,
+  CAMERA_STREAMING_HIGH,
+  GAME,
+  GAME_LOADING,
 }
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionMode.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionMode.aidl
new file mode 100644
index 0000000..d0ae0ba
--- /dev/null
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionMode.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.power;
+@Backing(type="int") @VintfStability
+enum SessionMode {
+  POWER_EFFICIENCY,
+}
diff --git a/power/aidl/android/hardware/power/IPowerHintSession.aidl b/power/aidl/android/hardware/power/IPowerHintSession.aidl
index 7db0ea1..62263c8 100644
--- a/power/aidl/android/hardware/power/IPowerHintSession.aidl
+++ b/power/aidl/android/hardware/power/IPowerHintSession.aidl
@@ -17,6 +17,7 @@
 package android.hardware.power;
 
 import android.hardware.power.SessionHint;
+import android.hardware.power.SessionMode;
 import android.hardware.power.WorkDuration;
 
 @VintfStability
@@ -81,4 +82,13 @@
      *    must be thrown.
      */
     void setThreads(in int[] threadIds);
+
+    /**
+     * Called to enable or disable special modes for the hint session, which may
+     * adjust the power or performance of the session.
+     *
+     * @param type The mode being set
+     * @param enabled True to enable the mode, false to disable it
+     */
+    oneway void setMode(SessionMode type, boolean enabled);
 }
diff --git a/power/aidl/android/hardware/power/SessionMode.aidl b/power/aidl/android/hardware/power/SessionMode.aidl
new file mode 100644
index 0000000..f1ee64e
--- /dev/null
+++ b/power/aidl/android/hardware/power/SessionMode.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.power;
+
+@VintfStability
+@Backing(type="int")
+enum SessionMode {
+    /**
+     * This mode indicates that the work of this hint session is not
+     * critical to perceived performance, despite its CPU intensity,
+     * and can be safely scheduled to prefer power efficiency.
+     */
+    POWER_EFFICIENCY,
+}
diff --git a/power/aidl/default/Android.bp b/power/aidl/default/Android.bp
index da91ee6..c0bfbe8 100644
--- a/power/aidl/default/Android.bp
+++ b/power/aidl/default/Android.bp
@@ -23,6 +23,7 @@
 
 cc_binary {
     name: "android.hardware.power-service.example",
+    defaults: ["android.hardware.power-ndk_shared"],
     relative_install_path: "hw",
     init_rc: [":android.hardware.power.rc"],
     vintf_fragments: [":android.hardware.power.xml"],
@@ -30,7 +31,6 @@
     shared_libs: [
         "libbase",
         "libbinder_ndk",
-        "android.hardware.power-V4-ndk",
     ],
     srcs: [
         "main.cpp",
diff --git a/power/aidl/default/PowerHintSession.cpp b/power/aidl/default/PowerHintSession.cpp
index f395800..452e435 100644
--- a/power/aidl/default/PowerHintSession.cpp
+++ b/power/aidl/default/PowerHintSession.cpp
@@ -59,4 +59,8 @@
     return ScopedAStatus::ok();
 }
 
+ScopedAStatus PowerHintSession::setMode(SessionMode /* mode */, bool /* enabled */) {
+    return ScopedAStatus::ok();
+}
+
 }  // namespace aidl::android::hardware::power::impl::example
diff --git a/power/aidl/default/PowerHintSession.h b/power/aidl/default/PowerHintSession.h
index 1d74716..b488bf1 100644
--- a/power/aidl/default/PowerHintSession.h
+++ b/power/aidl/default/PowerHintSession.h
@@ -18,6 +18,7 @@
 
 #include <aidl/android/hardware/power/BnPowerHintSession.h>
 #include <aidl/android/hardware/power/SessionHint.h>
+#include <aidl/android/hardware/power/SessionMode.h>
 #include <aidl/android/hardware/power/WorkDuration.h>
 
 namespace aidl::android::hardware::power::impl::example {
@@ -33,6 +34,7 @@
     ndk::ScopedAStatus close() override;
     ndk::ScopedAStatus sendHint(SessionHint hint) override;
     ndk::ScopedAStatus setThreads(const std::vector<int32_t>& threadIds) override;
+    ndk::ScopedAStatus setMode(SessionMode mode, bool enabled) override;
 };
 
 }  // namespace aidl::android::hardware::power::impl::example
diff --git a/power/aidl/default/power-default.xml b/power/aidl/default/power-default.xml
index f5dd6b9..418fb83 100644
--- a/power/aidl/default/power-default.xml
+++ b/power/aidl/default/power-default.xml
@@ -1,7 +1,7 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.power</name>
-        <version>4</version>
+        <version>5</version>
         <fqname>IPower/default</fqname>
     </hal>
 </manifest>
diff --git a/power/aidl/vts/Android.bp b/power/aidl/vts/Android.bp
index 56c98bd..eb98b8b 100644
--- a/power/aidl/vts/Android.bp
+++ b/power/aidl/vts/Android.bp
@@ -26,14 +26,12 @@
     defaults: [
         "VtsHalTargetTestDefaults",
         "use_libaidlvintf_gtest_helper_static",
+        "android.hardware.power-ndk_static",
     ],
     srcs: ["VtsHalPowerTargetTest.cpp"],
     shared_libs: [
         "libbinder_ndk",
     ],
-    static_libs: [
-        "android.hardware.power-V4-ndk",
-    ],
     test_suites: [
         "general-tests",
         "vts",
diff --git a/power/aidl/vts/VtsHalPowerTargetTest.cpp b/power/aidl/vts/VtsHalPowerTargetTest.cpp
index c2216f8..96995a0 100644
--- a/power/aidl/vts/VtsHalPowerTargetTest.cpp
+++ b/power/aidl/vts/VtsHalPowerTargetTest.cpp
@@ -29,12 +29,12 @@
 namespace aidl::android::hardware::power {
 namespace {
 
-using ::android::base::GetUintProperty;
 using android::hardware::power::Boost;
 using android::hardware::power::IPower;
 using android::hardware::power::IPowerHintSession;
 using android::hardware::power::Mode;
 using android::hardware::power::SessionHint;
+using android::hardware::power::SessionMode;
 using android::hardware::power::WorkDuration;
 
 const std::vector<Boost> kBoosts{ndk::enum_range<Boost>().begin(), ndk::enum_range<Boost>().end()};
@@ -44,6 +44,9 @@
 const std::vector<SessionHint> kSessionHints{ndk::enum_range<SessionHint>().begin(),
                                              ndk::enum_range<SessionHint>().end()};
 
+const std::vector<SessionMode> kSessionModes{ndk::enum_range<SessionMode>().begin(),
+                                             ndk::enum_range<SessionMode>().end()};
+
 const std::vector<Boost> kInvalidBoosts = {
         static_cast<Boost>(static_cast<int32_t>(kBoosts.front()) - 1),
         static_cast<Boost>(static_cast<int32_t>(kBoosts.back()) + 1),
@@ -59,6 +62,11 @@
         static_cast<SessionHint>(static_cast<int32_t>(kSessionHints.back()) + 1),
 };
 
+const std::vector<SessionMode> kInvalidSessionModes = {
+        static_cast<SessionMode>(static_cast<int32_t>(kSessionModes.front()) - 1),
+        static_cast<SessionMode>(static_cast<int32_t>(kSessionModes.back()) + 1),
+};
+
 class DurationWrapper : public WorkDuration {
   public:
     DurationWrapper(int64_t dur, int64_t time) {
@@ -92,36 +100,33 @@
         DurationWrapper(1000000000L, 4L),
 };
 
-// DEVICEs launching with Android 11 MUST meet the requirements for the
-// target-level=5 compatibility_matrix file.
-const uint64_t kCompatibilityMatrix5ApiLevel = 30;
-
-// DEVICEs launching with Android 13 MUST meet the requirements for the
-// target-level=7 compatibility_matrix file.
-const uint64_t kCompatibilityMatrix7ApiLevel = 33;
-
-// DEVICEs launching with Android 14 MUST meet the requirements for the
-// target-level=8 compatibility_matrix file.
-const uint64_t kCompatibilityMatrix8ApiLevel = 34;
-
-inline bool isUnknownOrUnsupported(const ndk::ScopedAStatus& status) {
-    return status.getStatus() == STATUS_UNKNOWN_TRANSACTION ||
-           status.getExceptionCode() == EX_UNSUPPORTED_OPERATION;
-}
-
 class PowerAidl : public testing::TestWithParam<std::string> {
   public:
     virtual void SetUp() override {
         AIBinder* binder = AServiceManager_waitForService(GetParam().c_str());
         ASSERT_NE(binder, nullptr);
         power = IPower::fromBinder(ndk::SpAIBinder(binder));
-
-        mApiLevel = GetUintProperty<uint64_t>("ro.vendor.api_level", 0);
-        ASSERT_NE(mApiLevel, 0);
+        auto status = power->getInterfaceVersion(&mServiceVersion);
+        ASSERT_TRUE(status.isOk());
     }
 
     std::shared_ptr<IPower> power;
-    uint64_t mApiLevel;
+    int32_t mServiceVersion;
+};
+
+class HintSessionAidl : public PowerAidl {
+  public:
+    virtual void SetUp() override {
+        PowerAidl::SetUp();
+        if (mServiceVersion < 2) {
+            GTEST_SKIP() << "DEVICE not launching with Power V2 and beyond.";
+        }
+
+        auto status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &mSession);
+        ASSERT_TRUE(status.isOk());
+        ASSERT_NE(nullptr, mSession);
+    }
+    std::shared_ptr<IPowerHintSession> mSession;
 };
 
 TEST_P(PowerAidl, setMode) {
@@ -175,113 +180,95 @@
 }
 
 TEST_P(PowerAidl, getHintSessionPreferredRate) {
-    int64_t rate = -1;
-    auto status = power->getHintSessionPreferredRate(&rate);
-    if (mApiLevel < kCompatibilityMatrix7ApiLevel && !status.isOk()) {
-        EXPECT_TRUE(isUnknownOrUnsupported(status));
-        GTEST_SKIP() << "DEVICE not launching with Android 13 and beyond.";
+    if (mServiceVersion < 2) {
+        GTEST_SKIP() << "DEVICE not launching with Power V2 and beyond.";
     }
-    ASSERT_TRUE(status.isOk());
+
+    int64_t rate = -1;
+    ASSERT_TRUE(power->getHintSessionPreferredRate(&rate).isOk());
     // At least 1ms rate limit from HAL
     ASSERT_GE(rate, 1000000);
 }
 
-TEST_P(PowerAidl, createAndCloseHintSession) {
-    std::shared_ptr<IPowerHintSession> session;
-    auto status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &session);
-    if (mApiLevel < kCompatibilityMatrix7ApiLevel && !status.isOk()) {
-        EXPECT_TRUE(isUnknownOrUnsupported(status));
-        GTEST_SKIP() << "DEVICE not launching with Android 13 and beyond.";
-    }
-    ASSERT_TRUE(status.isOk());
-    ASSERT_NE(nullptr, session);
-    ASSERT_TRUE(session->pause().isOk());
-    ASSERT_TRUE(session->resume().isOk());
+TEST_P(HintSessionAidl, createAndCloseHintSession) {
+    ASSERT_TRUE(mSession->pause().isOk());
+    ASSERT_TRUE(mSession->resume().isOk());
     // Test normal destroy operation
-    ASSERT_TRUE(session->close().isOk());
-    session.reset();
+    ASSERT_TRUE(mSession->close().isOk());
+    mSession.reset();
 }
 
-TEST_P(PowerAidl, createHintSessionFailed) {
+TEST_P(HintSessionAidl, createHintSessionFailed) {
     std::shared_ptr<IPowerHintSession> session;
     auto status = power->createHintSession(getpid(), getuid(), kEmptyTids, 16666666L, &session);
 
     // Regardless of whether V2 and beyond is supported, the status is always not STATUS_OK.
     ASSERT_FALSE(status.isOk());
-
-    // If device not launching with Android 13 and beyond, check whether it's supported,
-    // if not, skip the test.
-    if (mApiLevel < kCompatibilityMatrix7ApiLevel && isUnknownOrUnsupported(status)) {
-        GTEST_SKIP() << "DEVICE not launching with Android 13 and beyond.";
-    }
     ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
 }
 
-TEST_P(PowerAidl, updateAndReportDurations) {
-    std::shared_ptr<IPowerHintSession> session;
-    auto status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &session);
-    if (mApiLevel < kCompatibilityMatrix7ApiLevel && !status.isOk()) {
-        EXPECT_TRUE(isUnknownOrUnsupported(status));
-        GTEST_SKIP() << "DEVICE not launching with Android 13 and beyond.";
-    }
-    ASSERT_TRUE(status.isOk());
-    ASSERT_NE(nullptr, session);
-
-    ASSERT_TRUE(session->updateTargetWorkDuration(16666667LL).isOk());
-    ASSERT_TRUE(session->reportActualWorkDuration(kDurations).isOk());
+TEST_P(HintSessionAidl, updateAndReportDurations) {
+    ASSERT_TRUE(mSession->updateTargetWorkDuration(16666667LL).isOk());
+    ASSERT_TRUE(mSession->reportActualWorkDuration(kDurations).isOk());
 }
 
-TEST_P(PowerAidl, sendSessionHint) {
-    std::shared_ptr<IPowerHintSession> session;
-    auto status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &session);
-    if (!status.isOk()) {
-        EXPECT_TRUE(isUnknownOrUnsupported(status));
-        return;
+TEST_P(HintSessionAidl, sendSessionHint) {
+    if (mServiceVersion < 4) {
+        GTEST_SKIP() << "DEVICE not launching with Power V4 and beyond.";
     }
+
     for (const auto& sessionHint : kSessionHints) {
-        ASSERT_TRUE(session->sendHint(sessionHint).isOk());
+        ASSERT_TRUE(mSession->sendHint(sessionHint).isOk());
     }
     for (const auto& sessionHint : kInvalidSessionHints) {
-        ASSERT_TRUE(session->sendHint(sessionHint).isOk());
+        ASSERT_TRUE(mSession->sendHint(sessionHint).isOk());
     }
 }
 
-TEST_P(PowerAidl, setThreads) {
-    std::shared_ptr<IPowerHintSession> session;
-    auto status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &session);
-    if (mApiLevel < kCompatibilityMatrix7ApiLevel && !status.isOk()) {
-        EXPECT_TRUE(isUnknownOrUnsupported(status));
-        GTEST_SKIP() << "DEVICE not launching with Android 13 and beyond.";
+TEST_P(HintSessionAidl, setThreads) {
+    if (mServiceVersion < 4) {
+        GTEST_SKIP() << "DEVICE not launching with Power V4 and beyond.";
     }
-    ASSERT_TRUE(status.isOk());
 
-    status = session->setThreads(kEmptyTids);
-    if (mApiLevel < kCompatibilityMatrix8ApiLevel && isUnknownOrUnsupported(status)) {
-        GTEST_SKIP() << "DEVICE not launching with Android 14 and beyond.";
-    }
+    auto status = mSession->setThreads(kEmptyTids);
     ASSERT_FALSE(status.isOk());
     ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
 
-    status = session->setThreads(kSelfTids);
-    ASSERT_TRUE(status.isOk());
+    ASSERT_TRUE(mSession->setThreads(kSelfTids).isOk());
+}
+
+TEST_P(HintSessionAidl, setSessionMode) {
+    if (mServiceVersion < 5) {
+        GTEST_SKIP() << "DEVICE not launching with Power V5 and beyond.";
+    }
+
+    for (const auto& sessionMode : kSessionModes) {
+        ASSERT_TRUE(mSession->setMode(sessionMode, true).isOk());
+        ASSERT_TRUE(mSession->setMode(sessionMode, false).isOk());
+    }
+    for (const auto& sessionMode : kInvalidSessionModes) {
+        ASSERT_TRUE(mSession->setMode(sessionMode, true).isOk());
+        ASSERT_TRUE(mSession->setMode(sessionMode, false).isOk());
+    }
 }
 
 // FIXED_PERFORMANCE mode is required for all devices which ship on Android 11
 // or later
 TEST_P(PowerAidl, hasFixedPerformance) {
-    if (mApiLevel < kCompatibilityMatrix5ApiLevel) {
-        GTEST_SKIP() << "FIXED_PERFORMANCE mode is only required for all devices launching Android "
-                        "11 or later.";
-    }
     bool supported;
     ASSERT_TRUE(power->isModeSupported(Mode::FIXED_PERFORMANCE, &supported).isOk());
     ASSERT_TRUE(supported);
 }
 
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PowerAidl);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HintSessionAidl);
+
 INSTANTIATE_TEST_SUITE_P(Power, PowerAidl,
                          testing::ValuesIn(::android::getAidlHalInstanceNames(IPower::descriptor)),
                          ::android::PrintInstanceNameToString);
+INSTANTIATE_TEST_SUITE_P(Power, HintSessionAidl,
+                         testing::ValuesIn(::android::getAidlHalInstanceNames(IPower::descriptor)),
+                         ::android::PrintInstanceNameToString);
 
 }  // namespace
 }  // namespace aidl::android::hardware::power
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
index d1a831b..cbc1e30 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
@@ -82,5 +82,4 @@
   oneway void isNullCipherAndIntegrityEnabled(in int serial);
   oneway void isN1ModeEnabled(in int serial);
   oneway void setN1ModeEnabled(in int serial, boolean enable);
-  oneway void setSatellitePlmn(in int serial, in List<String> plmnList);
 }
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
index bf43d7c..c86bebc 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -81,5 +81,4 @@
   oneway void isNullCipherAndIntegrityEnabledResponse(in android.hardware.radio.RadioResponseInfo info, in boolean isEnabled);
   oneway void isN1ModeEnabledResponse(in android.hardware.radio.RadioResponseInfo info, boolean isEnabled);
   oneway void setN1ModeEnabledResponse(in android.hardware.radio.RadioResponseInfo info);
-  oneway void setSatellitePlmnResponse(in android.hardware.radio.RadioResponseInfo info);
 }
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
index 2f40bd6..e4c3856 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
@@ -556,18 +556,4 @@
      * Response function is IRadioNetworkResponse.setN1ModeEnabledResponse()
      */
     void setN1ModeEnabled(in int serial, boolean enable);
-
-    /**
-     * Set the non-terrestrial PLMN with lower priority than terrestrial networks.
-     * MCC/MNC broadcast by the non-terrestrial networks may not be included in OPLMNwACT file on
-     * SIM profile. Acquisition of satellite based system is lower priority to terrestrial
-     * networks. UE shall make all attempts to acquire terrestrial service prior to camping on
-     * satellite LTE service.
-     *
-     * @param serial Serial number of request.
-     * @param plmnList The list of roaming PLMN used for connecting to satellite networks.
-     *
-     * Response function is IRadioNetworkResponse.setSatellitePlmnResponse()
-     */
-    void setSatellitePlmn(in int serial, in List<String> plmnList);
 }
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
index 9798944..db37a0e 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -668,21 +668,4 @@
      *   RadioError:INVALID_STATE
      */
     void setN1ModeEnabledResponse(in RadioResponseInfo info);
-
-    /**
-     * Response of setSatellitePlmn.
-     * This is an optional API.
-     *
-     * @param info Response info struct containing response type, serial no. and error.
-     *
-     * Valid errors returned:
-     *   RadioError:NONE
-     *   RadioError:INVALID_ARGUMENTS
-     *   RadioError:INVALID_MODEM_STATE
-     *   RadioError:MODEM_ERR
-     *   RadioError:NO_RESOURCES
-     *   RadioError:RADIO_NOT_AVAILABLE
-     *   RadioError:REQUEST_NOT_SUPPORTED
-     */
-    void setSatellitePlmnResponse(in RadioResponseInfo info);
 }
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
index ff3f10d..d57c83d 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
@@ -108,9 +108,6 @@
     ::ndk::ScopedAStatus setNullCipherAndIntegrityEnabled(int32_t serial, bool enabled) override;
     ::ndk::ScopedAStatus isNullCipherAndIntegrityEnabled(int32_t serial) override;
 
-    ::ndk::ScopedAStatus setSatellitePlmn(int32_t serial,
-                                          const std::vector<std::string>& plmnList) override;
-
   protected:
     std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkResponse> respond();
 
diff --git a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
index 1aa7c29..a379eec 100644
--- a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
+++ b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
@@ -372,12 +372,4 @@
     respond()->setN1ModeEnabledResponse(notSupported(serial));
     return ok();
 }
-
-ScopedAStatus RadioNetwork::setSatellitePlmn(int32_t serial,
-                                             const std::vector<std::string>& /*plmnList*/) {
-    LOG_CALL << serial;
-    LOG(ERROR) << " setSatellitePlmn is unsupported by HIDL HALs";
-    respond()->setSatellitePlmnResponse(notSupported(serial));
-    return ok();
-}
 }  // namespace android::hardware::radio::compat
diff --git a/radio/aidl/vts/radio_network_response.cpp b/radio/aidl/vts/radio_network_response.cpp
index eab9fac..25d45a5 100644
--- a/radio/aidl/vts/radio_network_response.cpp
+++ b/radio/aidl/vts/radio_network_response.cpp
@@ -320,9 +320,3 @@
     parent_network.notify(info.serial);
     return ndk::ScopedAStatus::ok();
 }
-
-ndk::ScopedAStatus RadioNetworkResponse::setSatellitePlmnResponse(const RadioResponseInfo& info) {
-    rspInfo = info;
-    parent_network.notify(info.serial);
-    return ndk::ScopedAStatus::ok();
-}
diff --git a/radio/aidl/vts/radio_network_test.cpp b/radio/aidl/vts/radio_network_test.cpp
index 9af2494..253ef82 100644
--- a/radio/aidl/vts/radio_network_test.cpp
+++ b/radio/aidl/vts/radio_network_test.cpp
@@ -106,7 +106,7 @@
                  RadioError::REQUEST_NOT_SUPPORTED, RadioError::NO_RESOURCES}));
         if (radioRsp_network->rspInfo.error == RadioError::NONE) {
             // verify we get the value we set
-            ASSERT_EQ(radioRsp_network->networkTypeBitmapResponse, allowedNetworkTypesBitmap);
+            EXPECT_EQ(radioRsp_network->networkTypeBitmapResponse, allowedNetworkTypesBitmap);
         }
     }
 
@@ -2076,37 +2076,3 @@
                                  {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
                                   RadioError::MODEM_ERR, RadioError::REQUEST_NOT_SUPPORTED}));
 }
-
-/**
- * Test IRadioNetwork.setSatellitePlmn() for the response returned.
- */
-TEST_P(RadioNetworkTest, setSatellitePlmn) {
-    int32_t aidl_version;
-    std::vector<std::string> plmnList = {"00101", "00102", "00103"};
-    ndk::ScopedAStatus aidl_status = radio_network->getInterfaceVersion(&aidl_version);
-    ASSERT_OK(aidl_status);
-    if (aidl_version < 3) {
-        ALOGI("Skipped the test since setSatellitePlmn is not supported on version < 3.");
-        GTEST_SKIP();
-    }
-
-    serial = GetRandomSerialNumber();
-
-    ndk::ScopedAStatus res = radio_network->setSatellitePlmn(serial, plmnList);
-    ASSERT_OK(res);
-
-    EXPECT_EQ(std::cv_status::no_timeout, wait());
-    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_network->rspInfo.type);
-    EXPECT_EQ(serial, radioRsp_network->rspInfo.serial);
-
-    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_network->rspInfo.error,
-                                 {
-                                         RadioError::NONE,
-                                         RadioError::INVALID_ARGUMENTS,
-                                         RadioError::INVALID_MODEM_STATE,
-                                         RadioError::MODEM_ERR,
-                                         RadioError::NO_RESOURCES,
-                                         RadioError::RADIO_NOT_AVAILABLE,
-                                         RadioError::REQUEST_NOT_SUPPORTED,
-                                 }));
-}
diff --git a/radio/aidl/vts/radio_network_utils.h b/radio/aidl/vts/radio_network_utils.h
index c2466ac..8f8f6b0 100644
--- a/radio/aidl/vts/radio_network_utils.h
+++ b/radio/aidl/vts/radio_network_utils.h
@@ -169,8 +169,6 @@
             const RadioResponseInfo& info, bool isEnabled) override;
 
     virtual ndk::ScopedAStatus setN1ModeEnabledResponse(const RadioResponseInfo& info) override;
-
-    virtual ndk::ScopedAStatus setSatellitePlmnResponse(const RadioResponseInfo& info) override;
 };
 
 /* Callback class for radio network indication */
diff --git a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
index 8a8eaa4..a2edd62 100644
--- a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
+++ b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
@@ -156,7 +156,7 @@
         vector<uint8_t> attested_key_blob;
         vector<KeyCharacteristics> attested_key_characteristics;
         vector<Certificate> attested_key_cert_chain;
-        EXPECT_EQ(ErrorCode::OK,
+        ASSERT_EQ(ErrorCode::OK,
                   GenerateKey(AuthorizationSetBuilder()
                                       .RsaSigningKey(2048, 65537)
                                       .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -167,9 +167,11 @@
                               &attested_key_cert_chain));
         KeyBlobDeleter attested_deleter(keymint_, attested_key_blob);
 
+        ASSERT_GT(attested_key_cert_chain.size(), 0);
+
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
-        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+        ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
                                               SecLevel(),
                                               attested_key_cert_chain[0].encodedCertificate));
 
@@ -186,7 +188,7 @@
          */
         attested_key_characteristics.resize(0);
         attested_key_cert_chain.resize(0);
-        EXPECT_EQ(ErrorCode::OK,
+        ASSERT_EQ(ErrorCode::OK,
                   GenerateKey(AuthorizationSetBuilder()
                                       .RsaEncryptionKey(2048, 65537)
                                       .Digest(Digest::NONE)
@@ -199,9 +201,11 @@
                               &attested_key_cert_chain));
         KeyBlobDeleter attested_deleter2(keymint_, attested_key_blob);
 
+        ASSERT_GT(attested_key_cert_chain.size(), 0);
+
         hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
         sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
-        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo2", "bar2", sw_enforced,
+        ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo2", "bar2", sw_enforced,
                                               hw_enforced, SecLevel(),
                                               attested_key_cert_chain[0].encodedCertificate));
 
@@ -219,7 +223,7 @@
         attested_key_characteristics.resize(0);
         attested_key_cert_chain.resize(0);
         uint64_t timestamp = 1619621648000;
-        EXPECT_EQ(ErrorCode::OK,
+        ASSERT_EQ(ErrorCode::OK,
                   GenerateKey(AuthorizationSetBuilder()
                                       .EcdsaSigningKey(EcCurve::P_256)
                                       .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -231,6 +235,8 @@
                               &attested_key_cert_chain));
         KeyBlobDeleter attested_deleter3(keymint_, attested_key_blob);
 
+        ASSERT_GT(attested_key_cert_chain.size(), 0);
+
         // The returned key characteristics will include CREATION_DATETIME (checked below)
         // in SecurityLevel::KEYSTORE; this will be stripped out in the CheckCharacteristics()
         // call below, to match what getKeyCharacteristics() returns (which doesn't include
@@ -246,7 +252,7 @@
         EXPECT_TRUE(sw_enforced.Contains(TAG_CREATION_DATETIME, timestamp))
                 << "expected CREATION_TIMESTAMP in sw_enforced:" << sw_enforced
                 << " not in hw_enforced:" << hw_enforced;
-        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+        ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
                                               SecLevel(),
                                               attested_key_cert_chain[0].encodedCertificate));
 
@@ -336,7 +342,7 @@
 
     AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attest_key_characteristics);
     AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attest_key_characteristics);
-    EXPECT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id,  //
+    ASSERT_TRUE(verify_attestation_record(AidlVersion(), challenge, app_id,  //
                                           sw_enforced, hw_enforced, SecLevel(),
                                           attest_key_cert_chain[0].encodedCertificate));
 
@@ -354,7 +360,7 @@
     uint64_t serial_int2 = 255;
     vector<uint8_t> serial_blob2(build_serial_blob(serial_int2));
 
-    EXPECT_EQ(ErrorCode::OK,
+    ASSERT_EQ(ErrorCode::OK,
               GenerateKey(AuthorizationSetBuilder()
                                   .RsaSigningKey(2048, 65537)
                                   .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -367,9 +373,11 @@
                           &attested_key_cert_chain));
     KeyBlobDeleter attested_deleter(keymint_, attested_key_blob);
 
+    ASSERT_GT(attested_key_cert_chain.size(), 0);
+
     AuthorizationSet hw_enforced2 = HwEnforcedAuthorizations(attested_key_characteristics);
     AuthorizationSet sw_enforced2 = SwEnforcedAuthorizations(attested_key_characteristics);
-    EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced2, hw_enforced2,
+    ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced2, hw_enforced2,
                                           SecLevel(),
                                           attested_key_cert_chain[0].encodedCertificate));
 
@@ -437,7 +445,7 @@
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
         ASSERT_GT(cert_chain_list[i].size(), 0);
-        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+        ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
                                               SecLevel(),
                                               cert_chain_list[i][0].encodedCertificate));
 
@@ -512,7 +520,7 @@
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
         ASSERT_GT(cert_chain_list[i].size(), 0);
-        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+        ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
                                               SecLevel(),
                                               cert_chain_list[i][0].encodedCertificate));
 
@@ -628,7 +636,7 @@
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
         ASSERT_GT(cert_chain_list[i].size(), 0);
-        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+        ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
                                               SecLevel(),
                                               cert_chain_list[i][0].encodedCertificate));
 
@@ -678,7 +686,7 @@
         vector<uint8_t> attested_key_blob;
         vector<KeyCharacteristics> attested_key_characteristics;
         vector<Certificate> attested_key_cert_chain;
-        EXPECT_EQ(ErrorCode::ATTESTATION_CHALLENGE_MISSING,
+        ASSERT_EQ(ErrorCode::ATTESTATION_CHALLENGE_MISSING,
                   GenerateKey(AuthorizationSetBuilder()
                                       .RsaSigningKey(2048, 65537)
                                       .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -687,7 +695,7 @@
                               attest_key, &attested_key_blob, &attested_key_characteristics,
                               &attested_key_cert_chain));
 
-        EXPECT_EQ(ErrorCode::ATTESTATION_CHALLENGE_MISSING,
+        ASSERT_EQ(ErrorCode::ATTESTATION_CHALLENGE_MISSING,
                   GenerateKey(AuthorizationSetBuilder()
                                       .EcdsaSigningKey(EcCurve::P_256)
                                       .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -725,7 +733,7 @@
         vector<uint8_t> attested_key_blob;
         vector<KeyCharacteristics> attested_key_characteristics;
         vector<Certificate> attested_key_cert_chain;
-        EXPECT_EQ(ErrorCode::OK,
+        ASSERT_EQ(ErrorCode::OK,
                   GenerateKey(AuthorizationSetBuilder()
                                       .RsaSigningKey(2048, 65537)
                                       .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -740,7 +748,7 @@
 
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
         AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
-        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+        ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
                                               SecLevel(),
                                               attested_key_cert_chain[0].encodedCertificate));
 
@@ -756,7 +764,7 @@
         /*
          * Use attestation key to sign EC key
          */
-        EXPECT_EQ(ErrorCode::OK,
+        ASSERT_EQ(ErrorCode::OK,
                   GenerateKey(AuthorizationSetBuilder()
                                       .EcdsaSigningKey(EcCurve::P_256)
                                       .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -771,7 +779,7 @@
 
         hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
         sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
-        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
+        ASSERT_TRUE(verify_attestation_record(AidlVersion(), "foo", "bar", sw_enforced, hw_enforced,
                                               SecLevel(),
                                               attested_key_cert_chain[0].encodedCertificate));
 
@@ -809,7 +817,7 @@
     vector<uint8_t> attested_key_blob;
     vector<KeyCharacteristics> attested_key_characteristics;
     vector<Certificate> attested_key_cert_chain;
-    EXPECT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE,
+    ASSERT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE,
               GenerateKey(AuthorizationSetBuilder()
                                   .EcdsaSigningKey(EcCurve::P_256)
                                   .Authorization(TAG_NO_AUTH_REQUIRED)
@@ -872,6 +880,7 @@
         }
 
         ASSERT_EQ(result, ErrorCode::OK);
+        ASSERT_GT(attested_key_cert_chain.size(), 0);
         KeyBlobDeleter attested_deleter(keymint_, attested_key_blob);
 
         AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
@@ -882,7 +891,7 @@
         // attestation extension should contain them, so make sure the extra tag is added.
         hw_enforced.push_back(tag);
 
-        EXPECT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
+        ASSERT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
                                               hw_enforced, SecLevel(),
                                               attested_key_cert_chain[0].encodedCertificate));
     }
@@ -919,7 +928,9 @@
                     .Authorization(TAG_ATTESTATION_ID_MODEL, "malicious-model");
 
     if (isSecondImeiIdAttestationRequired()) {
-        attestation_id_tags.Authorization(TAG_ATTESTATION_ID_SECOND_IMEI, "invalid-second-imei");
+        // Note: the invalid value here is < 16 bytes long to avoid triggering any implementation
+        // checks on valid IMEI lengths.
+        attestation_id_tags.Authorization(TAG_ATTESTATION_ID_SECOND_IMEI, "invalid-imei2");
     }
     vector<uint8_t> key_blob;
     vector<KeyCharacteristics> key_characteristics;
@@ -996,6 +1007,7 @@
     }
 
     ASSERT_EQ(result, ErrorCode::OK);
+    ASSERT_GT(attested_key_cert_chain.size(), 0);
     KeyBlobDeleter attested_deleter(keymint_, attested_key_blob);
 
     AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
@@ -1008,7 +1020,7 @@
     KeyParameter imei_tag = Authorization(TAG_ATTESTATION_ID_SECOND_IMEI, imei_blob);
     hw_enforced.push_back(imei_tag);
 
-    EXPECT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
+    ASSERT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
                                           hw_enforced, SecLevel(),
                                           attested_key_cert_chain[0].encodedCertificate));
 }
@@ -1067,6 +1079,7 @@
     }
 
     ASSERT_EQ(result, ErrorCode::OK);
+    ASSERT_GT(attested_key_cert_chain.size(), 0);
     KeyBlobDeleter attested_deleter(keymint_, attested_key_blob);
 
     AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
@@ -1082,7 +1095,7 @@
     KeyParameter sec_imei_tag = Authorization(TAG_ATTESTATION_ID_SECOND_IMEI, sec_imei_blob);
     hw_enforced.push_back(sec_imei_tag);
 
-    EXPECT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
+    ASSERT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
                                           hw_enforced, SecLevel(),
                                           attested_key_cert_chain[0].encodedCertificate));
 }
diff --git a/security/keymint/aidl/vts/functional/AuthTest.cpp b/security/keymint/aidl/vts/functional/AuthTest.cpp
index 290e8fc..ecaee11 100644
--- a/security/keymint/aidl/vts/functional/AuthTest.cpp
+++ b/security/keymint/aidl/vts/functional/AuthTest.cpp
@@ -453,8 +453,18 @@
     vector<uint8_t> keyblob;
     vector<KeyCharacteristics> key_characteristics;
     vector<Certificate> cert_chain;
-    ASSERT_EQ(ErrorCode::OK,
-              GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain));
+    auto result = GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain);
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) {
+            result = GenerateKeyWithSelfSignedAttestKey(AuthorizationSetBuilder()
+                                                                .EcdsaKey(EcCurve::P_256)
+                                                                .AttestKey()
+                                                                .SetDefaultValidity(),
+                                                        builder, &keyblob, &key_characteristics,
+                                                        &cert_chain);
+        }
+    }
+    ASSERT_EQ(ErrorCode::OK, result);
 
     // Verify first user to get a HAT that should work.
     const uint64_t challenge = 42;
diff --git a/sensors/common/vts/utils/GrallocWrapper.cpp b/sensors/common/vts/utils/GrallocWrapper.cpp
index e6e0888..a15e7fe 100644
--- a/sensors/common/vts/utils/GrallocWrapper.cpp
+++ b/sensors/common/vts/utils/GrallocWrapper.cpp
@@ -124,7 +124,8 @@
 
   private:
     static constexpr uint64_t kBufferUsage =
-            static_cast<uint64_t>(BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::CPU_READ_OFTEN);
+            static_cast<uint64_t>(BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::CPU_READ_OFTEN |
+                                  BufferUsage::CPU_WRITE_RARELY);
     AllocatorWrapperT<AllocatorT> mAllocator;
     sp<MapperT> mMapper;
 
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
index ff9c247..21951b6 100644
--- a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
+++ b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
@@ -45,6 +45,7 @@
   CCC_SUPPORTED_RAN_MULTIPLIER = 0xA7,
   CCC_SUPPORTED_MAX_RANGING_SESSION_NUMBER = 0xA8,
   CCC_SUPPORTED_MIN_UWB_INITIATION_TIME_MS = 0xA9,
+  CCC_PRIORITIZED_CHANNEL_LIST = 0xAA,
   RADAR_SUPPORT = 0xB0,
   SUPPORTED_AOA_RESULT_REQ_ANTENNA_INTERLEAVING = 0xE3,
   SUPPORTED_MIN_RANGING_INTERVAL_MS = 0xE4,
diff --git a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
index ceef1be..2141b5a 100644
--- a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
+++ b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
@@ -149,6 +149,11 @@
      */
     CCC_SUPPORTED_MIN_UWB_INITIATION_TIME_MS = 0xA9,
 
+    /**
+     * Byte array of channels supported by the device, ordered by priority from highest to lowest.
+     */
+    CCC_PRIORITIZED_CHANNEL_LIST = 0xAA,
+
     /*********************************************
      * RADAR specific
      ********************************************/