Merge "Camera muting via sensor test pattern" into sc-dev
diff --git a/METADATA b/METADATA
index d97975c..1fbda08 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,7 @@
+# *** THIS PACKAGE HAS SPECIAL LICENSING CONDITIONS. PLEASE
+# CONSULT THE OWNERS AND opensource-licensing@google.com BEFORE
+# DEPENDING ON IT IN YOUR PROJECT. ***
third_party {
- license_type: NOTICE
+ # would be NOTICE save for drm/mediadrm/plugins/clearkey/hidl/
+ license_type: BY_EXCEPTION_ONLY
}
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index c697b80..96af7cb 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -159,6 +159,10 @@
output->outputDelay = 0u;
output->numSlots = kSmoothnessFactor;
}
+ {
+ Mutexed<BlockPools>::Locked pools(mBlockPools);
+ pools->outputPoolId = C2BlockPool::BASIC_LINEAR;
+ }
}
CCodecBufferChannel::~CCodecBufferChannel() {
@@ -1092,10 +1096,13 @@
bool graphic = (oStreamFormat.value == C2BufferData::GRAPHIC);
C2BlockPool::local_id_t outputPoolId_;
+ C2BlockPool::local_id_t prevOutputPoolId;
{
Mutexed<BlockPools>::Locked pools(mBlockPools);
+ prevOutputPoolId = pools->outputPoolId;
+
// set default allocator ID.
pools->outputAllocatorId = (graphic) ? C2PlatformAllocatorStore::GRALLOC
: preferredLinearId;
@@ -1189,6 +1196,15 @@
outputPoolId_ = pools->outputPoolId;
}
+ if (prevOutputPoolId != C2BlockPool::BASIC_LINEAR
+ && prevOutputPoolId != C2BlockPool::BASIC_GRAPHIC) {
+ c2_status_t err = mComponent->destroyBlockPool(prevOutputPoolId);
+ if (err != C2_OK) {
+ ALOGW("Failed to clean up previous block pool %llu - %s (%d)\n",
+ (unsigned long long) prevOutputPoolId, asString(err), err);
+ }
+ }
+
Mutexed<Output>::Locked output(mOutput);
output->outputDelay = outputDelayValue;
output->numSlots = numOutputSlots;
diff --git a/media/codec2/vndk/C2Store.cpp b/media/codec2/vndk/C2Store.cpp
index dee3bf6..74ef9ea 100644
--- a/media/codec2/vndk/C2Store.cpp
+++ b/media/codec2/vndk/C2Store.cpp
@@ -102,16 +102,30 @@
}
static bool using_ion(void) {
- static int cached_result = -1;
-
- if (cached_result == -1) {
+ static int cached_result = []()->int {
struct stat buffer;
- cached_result = (stat("/dev/ion", &buffer) == 0);
- if (cached_result)
+ int ret = (stat("/dev/ion", &buffer) == 0);
+
+ if (property_get_int32("debug.c2.use_dmabufheaps", 0)) {
+ /*
+ * Double check that the system heap is present so we
+ * can gracefully fail back to ION if we cannot satisfy
+ * the override
+ */
+ ret = (stat("/dev/dma_heap/system", &buffer) != 0);
+ if (ret)
+ ALOGE("debug.c2.use_dmabufheaps set, but no system heap. Ignoring override!");
+ else
+ ALOGD("debug.c2.use_dmabufheaps set, forcing DMABUF Heaps");
+ }
+
+ if (ret)
ALOGD("Using ION\n");
else
ALOGD("Using DMABUF Heaps\n");
- }
+ return ret;
+ }();
+
return (cached_result == 1);
}
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 431f0fa..a4beaf4 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -56,6 +56,12 @@
ALOGE_IF(mHasThread, "%s() callback thread never join()ed", __func__);
+ if (!mMetricsId.empty()) {
+ android::mediametrics::LogItem(mMetricsId)
+ .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM)
+ .record();
+ }
+
// If the stream is deleted when OPEN or in use then audio resources will leak.
// This would indicate an internal error. So we want to find this ASAP.
LOG_ALWAYS_FATAL_IF(!(getState() == AAUDIO_STREAM_STATE_CLOSED
diff --git a/media/libmediametrics/include/MediaMetricsConstants.h b/media/libmediametrics/include/MediaMetricsConstants.h
index 84388c9..2af7eee 100644
--- a/media/libmediametrics/include/MediaMetricsConstants.h
+++ b/media/libmediametrics/include/MediaMetricsConstants.h
@@ -170,6 +170,7 @@
#define AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR "ctor"
#define AMEDIAMETRICS_PROP_EVENT_VALUE_DISCONNECT "disconnect"
#define AMEDIAMETRICS_PROP_EVENT_VALUE_DTOR "dtor"
+#define AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM "endAAudioStream" // AAudioStream
#define AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAUDIOINTERVALGROUP "endAudioIntervalGroup"
#define AMEDIAMETRICS_PROP_EVENT_VALUE_FLUSH "flush" // AudioTrack
#define AMEDIAMETRICS_PROP_EVENT_VALUE_INVALIDATE "invalidate" // server track, record
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index c0a8f9d..e721a78 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1064,8 +1064,7 @@
*output = AUDIO_IO_HANDLE_NONE;
if (!msdDevices.isEmpty()) {
*output = getOutputForDevices(msdDevices, session, *stream, config, flags);
- sp<DeviceDescriptor> device = outputDevices.isEmpty() ? nullptr : outputDevices.itemAt(0);
- if (*output != AUDIO_IO_HANDLE_NONE && setMsdPatch(device) == NO_ERROR) {
+ if (*output != AUDIO_IO_HANDLE_NONE && setMsdPatches(&outputDevices) == NO_ERROR) {
ALOGV("%s() Using MSD devices %s instead of devices %s",
__func__, msdDevices.toString().c_str(), outputDevices.toString().c_str());
} else {
@@ -1081,6 +1080,12 @@
}
*selectedDeviceId = getFirstDeviceId(outputDevices);
+ for (auto &outputDevice : outputDevices) {
+ if (outputDevice->getId() == getConfig().getDefaultOutputDevice()->getId()) {
+ *selectedDeviceId = outputDevice->getId();
+ break;
+ }
+ }
if (outputDevices.onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
*outputType = API_OUTPUT_TELEPHONY_TX;
@@ -1223,24 +1228,9 @@
sp<SwAudioOutputDescriptor> outputDesc =
new SwAudioOutputDescriptor(profile, mpClientInterface);
- String8 address = getFirstDeviceAddress(devices);
-
- // MSD patch may be using the only output stream that can service this request. Release
- // MSD patch to prioritize this request over any active output on MSD.
- AudioPatchCollection msdPatches = getMsdPatches();
- for (size_t i = 0; i < msdPatches.size(); i++) {
- const auto& patch = msdPatches[i];
- for (size_t j = 0; j < patch->mPatch.num_sinks; ++j) {
- const struct audio_port_config *sink = &patch->mPatch.sinks[j];
- if (sink->type == AUDIO_PORT_TYPE_DEVICE &&
- devices.containsDeviceWithType(sink->ext.device.type) &&
- (address.isEmpty() || strncmp(sink->ext.device.address, address.string(),
- AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0)) {
- releaseAudioPatch(patch->getHandle(), mUidCached);
- break;
- }
- }
- }
+ // An MSD patch may be using the only output stream that can service this request. Release
+ // all MSD patches to prioritize this request over any active output on MSD.
+ releaseMsdPatches(devices);
status_t status = outputDesc->open(config, devices, stream, flags, output);
@@ -1414,7 +1404,8 @@
}
AudioProfileVector deviceProfiles;
for (const auto &outProfile : outputProfiles) {
- if (hwAvSync == ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0)) {
+ if (hwAvSync == ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) &&
+ outProfile->supportsDevice(outputDevice)) {
appendAudioProfiles(deviceProfiles, outProfile->getAudioProfiles());
}
}
@@ -1482,40 +1473,85 @@
return patchBuilder;
}
-status_t AudioPolicyManager::setMsdPatch(const sp<DeviceDescriptor> &outputDevice) {
- sp<DeviceDescriptor> device = outputDevice;
- if (device == nullptr) {
+status_t AudioPolicyManager::setMsdPatches(const DeviceVector *outputDevices) {
+ DeviceVector devices;
+ if (outputDevices != nullptr && outputDevices->size() > 0) {
+ devices.add(*outputDevices);
+ } else {
// Use media strategy for unspecified output device. This should only
// occur on checkForDeviceAndOutputChanges(). Device connection events may
// therefore invalidate explicit routing requests.
- DeviceVector devices = mEngine->getOutputDevicesForAttributes(
+ devices = mEngine->getOutputDevicesForAttributes(
attributes_initializer(AUDIO_USAGE_MEDIA), nullptr, false /*fromCache*/);
- LOG_ALWAYS_FATAL_IF(devices.isEmpty(), "no outpudevice to set Msd Patch");
- device = devices.itemAt(0);
+ LOG_ALWAYS_FATAL_IF(devices.isEmpty(), "no output device to set MSD patch");
}
- ALOGV("%s() for device %s", __func__, device->toString().c_str());
- PatchBuilder patchBuilder = buildMsdPatch(device);
- const struct audio_patch* patch = patchBuilder.patch();
- const AudioPatchCollection msdPatches = getMsdPatches();
- if (!msdPatches.isEmpty()) {
- LOG_ALWAYS_FATAL_IF(msdPatches.size() > 1,
- "The current MSD prototype only supports one output patch");
- sp<AudioPatch> currentPatch = msdPatches.valueAt(0);
- if (audio_patches_are_equal(¤tPatch->mPatch, patch)) {
- return NO_ERROR;
+ std::vector<PatchBuilder> patchesToCreate;
+ for (auto i = 0u; i < devices.size(); ++i) {
+ ALOGV("%s() for device %s", __func__, devices[i]->toString().c_str());
+ patchesToCreate.push_back(buildMsdPatch(devices[i]));
+ }
+ // Retain only the MSD patches associated with outputDevices request.
+ // Tear down the others, and create new ones as needed.
+ AudioPatchCollection patchesToRemove = getMsdPatches();
+ for (auto it = patchesToCreate.begin(); it != patchesToCreate.end(); ) {
+ auto retainedPatch = false;
+ for (auto i = 0u; i < patchesToRemove.size(); ++i) {
+ if (audio_patches_are_equal(it->patch(), &patchesToRemove[i]->mPatch)) {
+ patchesToRemove.removeItemsAt(i);
+ retainedPatch = true;
+ break;
+ }
}
+ if (retainedPatch) {
+ it = patchesToCreate.erase(it);
+ continue;
+ }
+ ++it;
+ }
+ if (patchesToCreate.size() == 0 && patchesToRemove.size() == 0) {
+ return NO_ERROR;
+ }
+ for (auto i = 0u; i < patchesToRemove.size(); ++i) {
+ auto ¤tPatch = patchesToRemove.valueAt(i);
releaseAudioPatch(currentPatch->getHandle(), mUidCached);
}
- status_t status = installPatch(__func__, -1 /*index*/, nullptr /*patchHandle*/,
- patch, 0 /*delayMs*/, mUidCached, nullptr /*patchDescPtr*/);
- ALOGE_IF(status != NO_ERROR, "%s() error %d creating MSD audio patch", __func__, status);
- ALOGI_IF(status == NO_ERROR, "%s() Patch created from MSD_IN to "
- "device:%s (format:%#x channels:%#x samplerate:%d)", __func__,
- device->toString().c_str(), patch->sources[0].format,
- patch->sources[0].channel_mask, patch->sources[0].sample_rate);
+ status_t status = NO_ERROR;
+ for (const auto &p : patchesToCreate) {
+ auto currStatus = installPatch(__func__, -1 /*index*/, nullptr /*patchHandle*/,
+ p.patch(), 0 /*delayMs*/, mUidCached, nullptr /*patchDescPtr*/);
+ char message[256];
+ snprintf(message, sizeof(message), "%s() %s: creating MSD patch from device:IN_BUS to "
+ "device:%#x (format:%#x channels:%#x samplerate:%d)", __func__,
+ currStatus == NO_ERROR ? "Success" : "Error",
+ p.patch()->sinks[0].ext.device.type, p.patch()->sources[0].format,
+ p.patch()->sources[0].channel_mask, p.patch()->sources[0].sample_rate);
+ if (currStatus == NO_ERROR) {
+ ALOGD("%s", message);
+ } else {
+ ALOGE("%s", message);
+ if (status == NO_ERROR) {
+ status = currStatus;
+ }
+ }
+ }
return status;
}
+void AudioPolicyManager::releaseMsdPatches(const DeviceVector& devices) {
+ AudioPatchCollection msdPatches = getMsdPatches();
+ for (size_t i = 0; i < msdPatches.size(); i++) {
+ const auto& patch = msdPatches[i];
+ for (size_t j = 0; j < patch->mPatch.num_sinks; ++j) {
+ const struct audio_port_config *sink = &patch->mPatch.sinks[j];
+ if (sink->type == AUDIO_PORT_TYPE_DEVICE && devices.getDevice(sink->ext.device.type,
+ String8(sink->ext.device.address), AUDIO_FORMAT_DEFAULT) != nullptr) {
+ releaseAudioPatch(patch->getHandle(), mUidCached);
+ break;
+ }
+ }
+ }
+}
+
audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector<audio_io_handle_t>& outputs,
audio_output_flags_t flags,
audio_format_t format,
@@ -5319,8 +5355,13 @@
}
}
if (!directOutputOpen) {
- ALOGV("no direct outputs open, reset MSD patch");
- setMsdPatch();
+ ALOGV("no direct outputs open, reset MSD patches");
+ // TODO: The MSD patches to be established here may differ to current MSD patches due to
+ // how output devices for patching are resolved. Avoid by caching and reusing the
+ // arguments to mEngine->getOutputDevicesForAttributes() when resolving which output
+ // devices to patch to. This may be complicated by the fact that devices may become
+ // unavailable.
+ setMsdPatches();
}
}
}
@@ -5387,7 +5428,13 @@
if (onOutputsChecked != nullptr && onOutputsChecked()) checkA2dpSuspend();
updateDevicesAndOutputs();
if (mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD) != 0) {
- setMsdPatch();
+ // TODO: The MSD patches to be established here may differ to current MSD patches due to how
+ // output devices for patching are resolved. Nevertheless, AudioTracks affected by device
+ // configuration changes will ultimately be rerouted correctly. We can still avoid
+ // unnecessary rerouting by caching and reusing the arguments to
+ // mEngine->getOutputDevicesForAttributes() when resolving which output devices to patch to.
+ // This may be complicated by the fact that devices may become unavailable.
+ setMsdPatches();
}
// an event that changed routing likely occurred, inform upper layers
mpClientInterface->onRoutingUpdated();
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 3c55b63..d3ceb1b 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -848,13 +848,6 @@
// end point.
audio_port_handle_t mCallRxSourceClientPort = AUDIO_PORT_HANDLE_NONE;
-private:
- void onNewAudioModulesAvailableInt(DeviceVector *newDevices);
-
- // Add or remove AC3 DTS encodings based on user preferences.
- void modifySurroundFormats(const sp<DeviceDescriptor>& devDesc, FormatVector *formatsPtr);
- void modifySurroundChannelMasks(ChannelMaskSet *channelMasksPtr);
-
// Support for Multi-Stream Decoder (MSD) module
sp<DeviceDescriptor> getMsdAudioInDevice() const;
DeviceVector getMsdAudioOutDevices() const;
@@ -864,7 +857,14 @@
audio_port_config *sourceConfig,
audio_port_config *sinkConfig) const;
PatchBuilder buildMsdPatch(const sp<DeviceDescriptor> &outputDevice) const;
- status_t setMsdPatch(const sp<DeviceDescriptor> &outputDevice = nullptr);
+ status_t setMsdPatches(const DeviceVector *outputDevices = nullptr);
+ void releaseMsdPatches(const DeviceVector& devices);
+private:
+ void onNewAudioModulesAvailableInt(DeviceVector *newDevices);
+
+ // Add or remove AC3 DTS encodings based on user preferences.
+ void modifySurroundFormats(const sp<DeviceDescriptor>& devDesc, FormatVector *formatsPtr);
+ void modifySurroundChannelMasks(ChannelMaskSet *channelMasksPtr);
// If any, resolve any "dynamic" fields of an Audio Profiles collection
void updateAudioProfiles(const sp<DeviceDescriptor>& devDesc, audio_io_handle_t ioHandle,
diff --git a/services/audiopolicy/tests/AudioPolicyTestManager.h b/services/audiopolicy/tests/AudioPolicyTestManager.h
index be860e5..ea95364 100644
--- a/services/audiopolicy/tests/AudioPolicyTestManager.h
+++ b/services/audiopolicy/tests/AudioPolicyTestManager.h
@@ -29,6 +29,8 @@
using AudioPolicyManager::getOutputs;
using AudioPolicyManager::getAvailableOutputDevices;
using AudioPolicyManager::getAvailableInputDevices;
+ using AudioPolicyManager::releaseMsdPatches;
+ using AudioPolicyManager::setMsdPatches;
using AudioPolicyManager::setSurroundFormatEnabled;
uint32_t getAudioPortGeneration() const { return mAudioPortGeneration; }
};
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 3032589..684358f 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -349,7 +349,17 @@
// TODO: Add patch creation tests that involve already existing patch
-class AudioPolicyManagerTestMsd : public AudioPolicyManagerTest {
+enum
+{
+ MSD_AUDIO_PATCH_COUNT_NUM_AUDIO_PATCHES_INDEX = 0,
+ MSD_AUDIO_PATCH_COUNT_NAME_INDEX = 1
+};
+using MsdAudioPatchCountSpecification = std::tuple<size_t, std::string>;
+
+class AudioPolicyManagerTestMsd : public AudioPolicyManagerTest,
+ public ::testing::WithParamInterface<MsdAudioPatchCountSpecification> {
+ public:
+ AudioPolicyManagerTestMsd();
protected:
void SetUpManagerConfig() override;
void TearDown() override;
@@ -357,8 +367,26 @@
sp<DeviceDescriptor> mMsdOutputDevice;
sp<DeviceDescriptor> mMsdInputDevice;
sp<DeviceDescriptor> mDefaultOutputDevice;
+
+ const size_t mExpectedAudioPatchCount;
+ sp<DeviceDescriptor> mSpdifDevice;
};
+AudioPolicyManagerTestMsd::AudioPolicyManagerTestMsd()
+ : mExpectedAudioPatchCount(std::get<MSD_AUDIO_PATCH_COUNT_NUM_AUDIO_PATCHES_INDEX>(
+ GetParam())) {}
+
+INSTANTIATE_TEST_CASE_P(
+ MsdAudioPatchCount,
+ AudioPolicyManagerTestMsd,
+ ::testing::Values(
+ MsdAudioPatchCountSpecification(1u, "single"),
+ MsdAudioPatchCountSpecification(2u, "dual")
+ ),
+ [](const ::testing::TestParamInfo<MsdAudioPatchCountSpecification> &info) {
+ return std::get<MSD_AUDIO_PATCH_COUNT_NAME_INDEX>(info.param); }
+);
+
void AudioPolicyManagerTestMsd::SetUpManagerConfig() {
// TODO: Consider using Serializer to load part of the config from a string.
AudioPolicyManagerTest::SetUpManagerConfig();
@@ -378,6 +406,19 @@
config.addDevice(mMsdOutputDevice);
config.addDevice(mMsdInputDevice);
+ if (mExpectedAudioPatchCount == 2) {
+ // Add SPDIF device with PCM output profile as a second device for dual MSD audio patching.
+ mSpdifDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPDIF);
+ mSpdifDevice->addAudioProfile(pcmOutputProfile);
+ config.addDevice(mSpdifDevice);
+
+ sp<OutputProfile> spdifOutputProfile = new OutputProfile("spdif output");
+ spdifOutputProfile->addAudioProfile(pcmOutputProfile);
+ spdifOutputProfile->addSupportedDevice(mSpdifDevice);
+ config.getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
+ addOutputProfile(spdifOutputProfile);
+ }
+
sp<HwModule> msdModule = new HwModule(AUDIO_HARDWARE_MODULE_ID_MSD, 2 /*halVersionMajor*/);
HwModuleCollection modules = config.getHwModules();
modules.add(msdModule);
@@ -413,64 +454,88 @@
addOutputProfile(primaryEncodedOutputProfile);
mDefaultOutputDevice = config.getDefaultOutputDevice();
+ if (mExpectedAudioPatchCount == 2) {
+ mSpdifDevice->addAudioProfile(dtsOutputProfile);
+ primaryEncodedOutputProfile->addSupportedDevice(mSpdifDevice);
+ }
}
void AudioPolicyManagerTestMsd::TearDown() {
mMsdOutputDevice.clear();
mMsdInputDevice.clear();
mDefaultOutputDevice.clear();
+ mSpdifDevice.clear();
AudioPolicyManagerTest::TearDown();
}
-TEST_F(AudioPolicyManagerTestMsd, InitSuccess) {
+TEST_P(AudioPolicyManagerTestMsd, InitSuccess) {
ASSERT_TRUE(mMsdOutputDevice);
ASSERT_TRUE(mMsdInputDevice);
ASSERT_TRUE(mDefaultOutputDevice);
}
-TEST_F(AudioPolicyManagerTestMsd, Dump) {
+TEST_P(AudioPolicyManagerTestMsd, Dump) {
dumpToLog();
}
-TEST_F(AudioPolicyManagerTestMsd, PatchCreationOnSetForceUse) {
+TEST_P(AudioPolicyManagerTestMsd, PatchCreationOnSetForceUse) {
const PatchCountCheck patchCount = snapshotPatchCount();
mManager->setForceUse(AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND,
AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS);
- ASSERT_EQ(1, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
}
-TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrEncodedRoutesToMsd) {
+TEST_P(AudioPolicyManagerTestMsd, PatchCreationSetReleaseMsdPatches) {
+ const PatchCountCheck patchCount = snapshotPatchCount();
+ DeviceVector devices = mManager->getAvailableOutputDevices();
+ // Remove MSD output device to avoid patching to itself
+ devices.remove(mMsdOutputDevice);
+ ASSERT_EQ(mExpectedAudioPatchCount, devices.size());
+ mManager->setMsdPatches(&devices);
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
+ // Dual patch: exercise creating one new audio patch and reusing another existing audio patch.
+ DeviceVector singleDevice(devices[0]);
+ mManager->releaseMsdPatches(singleDevice);
+ ASSERT_EQ(mExpectedAudioPatchCount - 1, patchCount.deltaFromSnapshot());
+ mManager->setMsdPatches(&devices);
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
+ mManager->releaseMsdPatches(devices);
+ ASSERT_EQ(0, patchCount.deltaFromSnapshot());
+}
+
+TEST_P(AudioPolicyManagerTestMsd, GetOutputForAttrEncodedRoutesToMsd) {
const PatchCountCheck patchCount = snapshotPatchCount();
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
- ASSERT_EQ(1, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
}
-TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrPcmRoutesToMsd) {
+TEST_P(AudioPolicyManagerTestMsd, GetOutputForAttrPcmRoutesToMsd) {
const PatchCountCheck patchCount = snapshotPatchCount();
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000);
ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
- ASSERT_EQ(1, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
}
-TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrEncodedPlusPcmRoutesToMsd) {
+TEST_P(AudioPolicyManagerTestMsd, GetOutputForAttrEncodedPlusPcmRoutesToMsd) {
const PatchCountCheck patchCount = snapshotPatchCount();
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
- ASSERT_EQ(1, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
+ selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000);
ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
- ASSERT_EQ(1, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
}
-TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrUnsupportedFormatBypassesMsd) {
+TEST_P(AudioPolicyManagerTestMsd, GetOutputForAttrUnsupportedFormatBypassesMsd) {
const PatchCountCheck patchCount = snapshotPatchCount();
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
@@ -479,7 +544,7 @@
ASSERT_EQ(0, patchCount.deltaFromSnapshot());
}
-TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrFormatSwitching) {
+TEST_P(AudioPolicyManagerTestMsd, GetOutputForAttrFormatSwitching) {
// Switch between formats that are supported and not supported by MSD.
{
const PatchCountCheck patchCount = snapshotPatchCount();
@@ -489,9 +554,9 @@
AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT,
nullptr /*output*/, &portId);
ASSERT_EQ(selectedDeviceId, mDefaultOutputDevice->getId());
- ASSERT_EQ(1, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
mManager->releaseOutput(portId);
- ASSERT_EQ(1, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(mExpectedAudioPatchCount, patchCount.deltaFromSnapshot());
}
{
const PatchCountCheck patchCount = snapshotPatchCount();
@@ -501,7 +566,7 @@
AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT,
nullptr /*output*/, &portId);
ASSERT_NE(selectedDeviceId, mMsdOutputDevice->getId());
- ASSERT_EQ(-1, patchCount.deltaFromSnapshot());
+ ASSERT_EQ(-static_cast<int>(mExpectedAudioPatchCount), patchCount.deltaFromSnapshot());
mManager->releaseOutput(portId);
ASSERT_EQ(0, patchCount.deltaFromSnapshot());
}
diff --git a/services/mediametrics/AudioAnalytics.cpp b/services/mediametrics/AudioAnalytics.cpp
index d78d1e3..3b2de76 100644
--- a/services/mediametrics/AudioAnalytics.cpp
+++ b/services/mediametrics/AudioAnalytics.cpp
@@ -136,6 +136,25 @@
"connection_count",
};
+// static constexpr const char * const AAudioStreamFields[] {
+// "mediametrics_aaudiostream_reported",
+// "caller_name",
+// "path",
+// "direction",
+// "frames_per_burst",
+// "buffer_size",
+// "buffer_capacity",
+// "channel_count",
+// "total_frames_transferred",
+// "perf_mode_requested",
+// "perf_mode_actual",
+// "sharing",
+// "xrun_count",
+// "device_type",
+// "format_app",
+// "format_device",
+// };
+
/**
* sendToStatsd is a helper method that sends the arguments to statsd
* and returns a pair { result, summary_string }.
@@ -192,6 +211,24 @@
});
}));
+ // Handle legacy aaudio stream statistics
+ mActions.addAction(
+ AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "*." AMEDIAMETRICS_PROP_EVENT,
+ std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM),
+ std::make_shared<AnalyticsActions::Function>(
+ [this](const std::shared_ptr<const android::mediametrics::Item> &item) {
+ mAAudioStreamInfo.endAAudioStream(item, AAudioStreamInfo::CALLER_PATH_LEGACY);
+ }));
+
+ // Handle mmap aaudio stream statistics
+ mActions.addAction(
+ AMEDIAMETRICS_KEY_PREFIX_AUDIO_STREAM "*." AMEDIAMETRICS_PROP_EVENT,
+ std::string(AMEDIAMETRICS_PROP_EVENT_VALUE_ENDAAUDIOSTREAM),
+ std::make_shared<AnalyticsActions::Function>(
+ [this](const std::shared_ptr<const android::mediametrics::Item> &item) {
+ mAAudioStreamInfo.endAAudioStream(item, AAudioStreamInfo::CALLER_PATH_MMAP);
+ }));
+
// Handle device use record statistics
mActions.addAction(
AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "*." AMEDIAMETRICS_PROP_EVENT,
@@ -843,4 +880,109 @@
}
}
+void AudioAnalytics::AAudioStreamInfo::endAAudioStream(
+ const std::shared_ptr<const android::mediametrics::Item> &item, CallerPath path) const {
+ const std::string& key = item->getKey();
+
+ std::string callerNameStr;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_CALLERNAME, &callerNameStr);
+
+ const auto callerName = types::lookup<types::CALLER_NAME, int32_t>(callerNameStr);
+
+ std::string directionStr;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_DIRECTION, &directionStr);
+ const auto direction = types::lookup<types::AAUDIO_DIRECTION, int32_t>(directionStr);
+
+ int32_t framesPerBurst = -1;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_BURSTFRAMES, &framesPerBurst);
+
+ int32_t bufferSizeInFrames = -1;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_BUFFERSIZEFRAMES, &bufferSizeInFrames);
+
+ int32_t bufferCapacityInFrames = -1;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_BUFFERCAPACITYFRAMES, &bufferCapacityInFrames);
+
+ int32_t channelCount = -1;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_CHANNELCOUNT, &channelCount);
+
+ int64_t totalFramesTransferred = -1;
+ // TODO: log and get total frames transferred
+
+ std::string perfModeRequestedStr;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_PERFORMANCEMODE, &perfModeRequestedStr);
+ const auto perfModeRequested =
+ types::lookup<types::AAUDIO_PERFORMANCE_MODE, int32_t>(perfModeRequestedStr);
+
+ int32_t perfModeActual = 0;
+ // TODO: log and get actual performance mode
+
+ std::string sharingModeStr;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_SHARINGMODE, &sharingModeStr);
+ const auto sharingMode = types::lookup<types::AAUDIO_SHARING_MODE, int32_t>(sharingModeStr);
+
+ int32_t xrunCount = -1;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_UNDERRUN, &xrunCount);
+
+ std::string deviceType;
+ // TODO: only routed device id is logged, but no device type
+
+ int32_t formatApp = 0;
+ // TODO: log format from app
+
+ std::string formatDeviceStr;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_ENCODING, &formatDeviceStr);
+ const auto formatDevice = types::lookup<types::ENCODING, int32_t>(formatDeviceStr);
+
+ LOG(LOG_LEVEL) << "key:" << key
+ << " caller_name:" << callerName << "(" << callerNameStr << ")"
+ << " path:" << path
+ << " direction:" << direction << "(" << directionStr << ")"
+ << " frames_per_burst:" << framesPerBurst
+ << " buffer_size:" << bufferSizeInFrames
+ << " buffer_capacity:" << bufferCapacityInFrames
+ << " channel_count:" << channelCount
+ << " total_frames_transferred:" << totalFramesTransferred
+ << " perf_mode_requested:" << perfModeRequested << "(" << perfModeRequestedStr << ")"
+ << " perf_mode_actual:" << perfModeActual
+ << " sharing:" << sharingMode << "(" << sharingModeStr << ")"
+ << " xrun_count:" << xrunCount
+ << " device_type:" << deviceType
+ << " format_app:" << formatApp
+ << " format_device: " << formatDevice << "(" << formatDeviceStr << ")";
+
+ // TODO: send the metric to statsd when the proto is ready
+ // if (mAudioAnalytics.mDeliverStatistics) {
+ // const auto [ result, str ] = sendToStatsd(AAudioStreamFields,
+ // CONDITION(android::util::MEDIAMETRICS_AAUDIOSTREAM_REPORTED)
+ // , callerName
+ // , path
+ // , direction
+ // , framesPerBurst
+ // , bufferSizeInFrames
+ // , bufferCapacityInFrames
+ // , channelCount
+ // , totalFramesTransferred
+ // , perfModeRequested
+ // , perfModeActual
+ // , sharingMode
+ // , xrunCount
+ // , deviceType.c_str()
+ // , formatApp
+ // , formatDevice
+ // );
+ // ALOGV("%s: statsd %s", __func__, str.c_str());
+ // mAudioAnalytics.mStatsdLog.log("%s", str.c_str());
+ // }
+}
+
} // namespace android::mediametrics
diff --git a/services/mediametrics/AudioAnalytics.h b/services/mediametrics/AudioAnalytics.h
index df097b1..07872ef 100644
--- a/services/mediametrics/AudioAnalytics.h
+++ b/services/mediametrics/AudioAnalytics.h
@@ -189,6 +189,29 @@
int32_t mA2dpConnectionUnknowns GUARDED_BY(mLock) = 0;
} mDeviceConnection{*this};
+ // AAudioStreamInfo is a nested class which collect aaudio stream info from both client and
+ // server side.
+ class AAudioStreamInfo {
+ public:
+ // All the enum here must be kept the same as the ones defined in atoms.proto
+ enum CallerPath {
+ CALLER_PATH_UNKNOWN = 0,
+ CALLER_PATH_LEGACY = 1,
+ CALLER_PATH_MMAP = 2,
+ };
+
+ explicit AAudioStreamInfo(AudioAnalytics &audioAnalytics)
+ : mAudioAnalytics(audioAnalytics) {}
+
+ void endAAudioStream(
+ const std::shared_ptr<const android::mediametrics::Item> &item,
+ CallerPath path) const;
+
+ private:
+
+ AudioAnalytics &mAudioAnalytics;
+ } mAAudioStreamInfo{*this};
+
AudioPowerUsage mAudioPowerUsage{this};
};
diff --git a/services/mediametrics/AudioTypes.cpp b/services/mediametrics/AudioTypes.cpp
index 5d044bb..44e96ec 100644
--- a/services/mediametrics/AudioTypes.cpp
+++ b/services/mediametrics/AudioTypes.cpp
@@ -154,6 +154,40 @@
return map;
}
+const std::unordered_map<std::string, int32_t>& getAAudioDirection() {
+ // DO NOT MODIFY VALUES(OK to add new ones).
+ // This may be found in frameworks/av/media/libaaudio/include/aaudio/AAudio.h
+ static std::unordered_map<std::string, int32_t> map {
+ // UNKNOWN is -1
+ {"AAUDIO_DIRECTION_OUTPUT", 0},
+ {"AAUDIO_DIRECTION_INPUT", 1},
+ };
+ return map;
+}
+
+const std::unordered_map<std::string, int32_t>& getAAudioPerformanceMode() {
+ // DO NOT MODIFY VALUES(OK to add new ones).
+ // This may be found in frameworks/av/media/libaaudio/include/aaudio/AAudio.h
+ static std::unordered_map<std::string, int32_t> map {
+ // UNKNOWN is -1
+ {"AAUDIO_PERFORMANCE_MODE_NONE", 10},
+ {"AAUDIO_PERFORMANCE_MODE_POWER_SAVING", 11},
+ {"AAUDIO_PERFORMANCE_MODE_LOW_LATENCY", 12},
+ };
+ return map;
+}
+
+const std::unordered_map<std::string, int32_t>& getAAudioSharingMode() {
+ // DO NOT MODIFY VALUES(OK to add new ones).
+ // This may be found in frameworks/av/media/libaaudio/include/aaudio/AAudio.h
+ static std::unordered_map<std::string, int32_t> map {
+ // UNKNOWN is -1
+ {"AAUDIO_SHARING_MODE_EXCLUSIVE", 0},
+ {"AAUDIO_SHARING_MODE_SHARED", 1},
+ };
+ return map;
+}
+
// Helper: Create the corresponding int32 from string flags split with '|'.
template <typename Traits>
int32_t int32FromFlags(const std::string &flags)
@@ -433,4 +467,70 @@
return flagsFromMap(traits, getAudioTrackTraitsMap());
}
+template <>
+std::string lookup<AAUDIO_DIRECTION>(const std::string &direction)
+{
+ auto& map = getAAudioDirection();
+ auto it = map.find(direction);
+ if (it == map.end()) {
+ return "";
+ }
+ return direction;
+}
+
+template <>
+int32_t lookup<AAUDIO_DIRECTION>(const std::string &direction)
+{
+ auto& map = getAAudioDirection();
+ auto it = map.find(direction);
+ if (it == map.end()) {
+ return -1; // return unknown
+ }
+ return it->second;
+}
+
+template <>
+std::string lookup<AAUDIO_PERFORMANCE_MODE>(const std::string &performanceMode)
+{
+ auto& map = getAAudioPerformanceMode();
+ auto it = map.find(performanceMode);
+ if (it == map.end()) {
+ return "";
+ }
+ return performanceMode;
+}
+
+template <>
+int32_t lookup<AAUDIO_PERFORMANCE_MODE>(const std::string &performanceMode)
+{
+ auto& map = getAAudioPerformanceMode();
+ auto it = map.find(performanceMode);
+ if (it == map.end()) {
+ return -1; // return unknown
+ }
+ return it->second;
+}
+
+template <>
+std::string lookup<AAUDIO_SHARING_MODE>(const std::string &sharingMode)
+{
+ auto& map = getAAudioSharingMode();
+ auto it = map.find(sharingMode);
+ if (it == map.end()) {
+ return "";
+ }
+ return sharingMode;
+}
+
+template <>
+int32_t lookup<AAUDIO_SHARING_MODE>(const std::string &sharingMode)
+{
+ auto& map = getAAudioSharingMode();
+ auto it = map.find(sharingMode);
+ if (it == map.end()) {
+ return -1; // return unknown
+ }
+ return it->second;
+}
+
} // namespace android::mediametrics::types
diff --git a/services/mediametrics/AudioTypes.h b/services/mediametrics/AudioTypes.h
index e1deeb1..4394d79 100644
--- a/services/mediametrics/AudioTypes.h
+++ b/services/mediametrics/AudioTypes.h
@@ -40,6 +40,9 @@
// Enumeration for all the string translations to integers (generally int32_t) unless noted.
enum AudioEnumCategory {
+ AAUDIO_DIRECTION,
+ AAUDIO_PERFORMANCE_MODE,
+ AAUDIO_SHARING_MODE,
CALLER_NAME,
CONTENT_TYPE,
ENCODING,