Merge "Test that the password isn't truncated (again)" 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, ¶m) != 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 a2e2ef7..6ad130e 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());
}
}
@@ -3668,22 +3687,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;
@@ -3711,11 +3736,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;
@@ -3735,10 +3761,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;
@@ -3759,12 +3787,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) {
@@ -3805,13 +3833,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;
@@ -3846,13 +3876,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;
@@ -3879,13 +3911,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;
@@ -3906,10 +3940,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/automotive/audiocontrol/aidl/default/audiocontrol-default.xml b/automotive/audiocontrol/aidl/default/audiocontrol-default.xml
index e82f6fa..3452ae9 100644
--- a/automotive/audiocontrol/aidl/default/audiocontrol-default.xml
+++ b/automotive/audiocontrol/aidl/default/audiocontrol-default.xml
@@ -1,5 +1,6 @@
<manifest version="2.0" type="device">
<hal format="aidl">
+ <version>2</version>
<name>android.hardware.automotive.audiocontrol</name>
<fqname>IAudioControl/default</fqname>
</hal>
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
index b46b62c..1777f77 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
@@ -503,6 +503,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/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..e20fcec 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>
diff --git a/compatibility_matrices/compatibility_matrix.8.xml b/compatibility_matrices/compatibility_matrix.8.xml
index 41d7ed1..09d3fda 100644
--- a/compatibility_matrices/compatibility_matrix.8.xml
+++ b/compatibility_matrices/compatibility_matrix.8.xml
@@ -62,6 +62,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.automotive.audiocontrol</name>
+ <version>2</version>
<interface>
<name>IAudioControl</name>
<instance>default</instance>
diff --git a/compatibility_matrices/compatibility_matrix.9.xml b/compatibility_matrices/compatibility_matrix.9.xml
index f616bdb..77e5cb4 100644
--- a/compatibility_matrices/compatibility_matrix.9.xml
+++ b/compatibility_matrices/compatibility_matrix.9.xml
@@ -70,6 +70,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.automotive.audiocontrol</name>
+ <version>2</version>
<interface>
<name>IAudioControl</name>
<instance>default</instance>
diff --git a/compatibility_matrices/exclude/fcm_exclude.cpp b/compatibility_matrices/exclude/fcm_exclude.cpp
index ccce449..cfc8345 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,6 +87,60 @@
};
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;
+ }
+
+ return !std::any_of(excluded_prefixes.begin(), excluded_prefixes.end(), package_has_prefix);
+}
+
+// The predicate to VintfObject::checkMissingHalsInMatrices.
+bool ShouldCheckMissingAidlHalsInFcm(const std::string& package) {
+ 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{
+ // Test packages are exempted.
+ "android.hardware.tests.",
+ };
+
+ static std::vector<std::string> excluded_exact{
+ // Packages without top level interfaces (including types-only packages) are exempted.
+
+ // 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",
+ };
+
+ auto package_has_prefix = [&](const std::string& prefix) {
return android::base::StartsWith(package, prefix);
};
diff --git a/compatibility_matrices/exclude/include/vintf/fcm_exclude.h b/compatibility_matrices/exclude/include/vintf/fcm_exclude.h
index f74c217..9ee057b 100644
--- a/compatibility_matrices/exclude/include/vintf/fcm_exclude.h
+++ b/compatibility_matrices/exclude/include/vintf/fcm_exclude.h
@@ -25,6 +25,7 @@
// |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);
+bool ShouldCheckMissingHidlHalsInFcm(const std::string& packageAndVersion);
+bool ShouldCheckMissingAidlHalsInFcm(const std::string& package);
} // namespace android::vintf::details
diff --git a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
index 8a8eaa4..8aef9d9 100644
--- a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
+++ b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
@@ -919,7 +919,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;
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
********************************************/