Merge "Updating benchmark library with Large audio frame API" into main
diff --git a/camera/camera_platform.aconfig b/camera/camera_platform.aconfig
index 12311e5..bf1520b 100644
--- a/camera/camera_platform.aconfig
+++ b/camera/camera_platform.aconfig
@@ -127,24 +127,6 @@
flag {
namespace: "camera_platform"
- name: "surface_leak_fix"
- description: "Address Surface release leaks in CaptureRequest"
- bug: "324071855"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
- namespace: "camera_platform"
- name: "concert_mode_api"
- description: "Covers the eyes free videography public facing API"
- bug: "297083874"
-}
-
-
-flag {
- namespace: "camera_platform"
name: "cache_permission_services"
description: "Cache IPermissionController and IPermissionChecker in CameraService to reduce query latency."
bug: "326139956"
@@ -236,3 +218,10 @@
description: "Enable CameraServiceWatchdog to abort camera HAL to generate HAL tombstones"
bug: "349652177"
}
+
+flag {
+ namespace: "camera_platform"
+ name: "enable_stream_reconfiguration_for_unchanged_streams"
+ description: "Enable stream reconfiguration for unchanged streams"
+ bug: "341740105"
+}
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 1b5402f..1817490 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -91,7 +91,6 @@
ACAMERA_AUTOMOTIVE_LENS,
ACAMERA_EXTENSION,
ACAMERA_JPEGR,
- ACAMERA_EFV,
ACAMERA_SECTION_COUNT,
ACAMERA_VENDOR = 0x8000
@@ -139,7 +138,6 @@
ACAMERA_AUTOMOTIVE_LENS_START = ACAMERA_AUTOMOTIVE_LENS << 16,
ACAMERA_EXTENSION_START = ACAMERA_EXTENSION << 16,
ACAMERA_JPEGR_START = ACAMERA_JPEGR << 16,
- ACAMERA_EFV_START = ACAMERA_EFV << 16,
ACAMERA_VENDOR_START = ACAMERA_VENDOR << 16
} acamera_metadata_section_start_t;
@@ -11573,7 +11571,6 @@
-
__END_DECLS
#endif /* _NDK_CAMERA_METADATA_TAGS_H */
diff --git a/media/audio/aconfig/Android.bp b/media/audio/aconfig/Android.bp
index de8aca7..a5aeff2 100644
--- a/media/audio/aconfig/Android.bp
+++ b/media/audio/aconfig/Android.bp
@@ -50,6 +50,23 @@
}
cc_aconfig_library {
+ name: "com.android.media.audioserver-aconfig-cc-ro",
+ aconfig_declarations: "com.android.media.audioserver-aconfig",
+ defaults: ["audio-aconfig-cc-defaults"],
+ double_loadable: true,
+ host_supported: true,
+ product_available: true,
+ vendor_available: true,
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media",
+ "com.android.media.swcodec",
+ ],
+ min_sdk_version: "29",
+ mode: "force-read-only",
+}
+
+cc_aconfig_library {
name: "com.android.media.audio-aconfig-cc",
aconfig_declarations: "com.android.media.audio-aconfig",
defaults: ["audio-aconfig-cc-defaults"],
diff --git a/media/audio/aconfig/audio.aconfig b/media/audio/aconfig/audio.aconfig
index 9221c04..c732708 100644
--- a/media/audio/aconfig/audio.aconfig
+++ b/media/audio/aconfig/audio.aconfig
@@ -60,6 +60,15 @@
}
flag {
+ name: "equal_sco_lea_vc_index_range"
+ namespace: "media_audio"
+ description:
+ "Introduce the same index range for voice calls over SCO and "
+ "LE audio"
+ bug: "364364777"
+}
+
+flag {
name: "music_fx_edge_to_edge"
namespace: "media_audio"
description: "Enable Edge-to-edge feature for MusicFx and handle insets"
diff --git a/media/audio/aconfig/audioserver.aconfig b/media/audio/aconfig/audioserver.aconfig
index d1c6239..1ce4d00 100644
--- a/media/audio/aconfig/audioserver.aconfig
+++ b/media/audio/aconfig/audioserver.aconfig
@@ -22,6 +22,13 @@
}
flag {
+ name: "enable_audio_input_device_routing"
+ namespace: "media_audio"
+ description: "Allow audio input devices routing control."
+ bug: "364923030"
+}
+
+flag {
name: "fdtostring_timeout_fix"
namespace: "media_audio"
description: "Improve fdtostring implementation to properly handle timing out."
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index b1517bb..61204ae 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -158,6 +158,7 @@
"framework-permission-aidl-cpp",
"libbinder",
"libmediametrics",
+ "libmediautils",
"spatializer-aidl-cpp",
],
diff --git a/media/libaudioclient/TrackPlayerBase.cpp b/media/libaudioclient/TrackPlayerBase.cpp
index 4fc1c44..bc38251 100644
--- a/media/libaudioclient/TrackPlayerBase.cpp
+++ b/media/libaudioclient/TrackPlayerBase.cpp
@@ -38,12 +38,12 @@
player_type_t playerType, audio_usage_t usage,
audio_session_t sessionId) {
PlayerBase::init(playerType, usage, sessionId);
- mAudioTrack = pat;
- if (mAudioTrack != 0) {
+ mAudioTrack.store(pat);
+ if (pat != 0) {
mCallbackHandle = callback;
mSelfAudioDeviceCallback = new SelfAudioDeviceCallback(*this);
- mAudioTrack->addAudioDeviceCallback(mSelfAudioDeviceCallback);
- mAudioTrack->setPlayerIId(mPIId); // set in PlayerBase::init().
+ pat->addAudioDeviceCallback(mSelfAudioDeviceCallback);
+ pat->setPlayerIId(mPIId); // set in PlayerBase::init().
}
}
@@ -65,12 +65,15 @@
}
void TrackPlayerBase::doDestroy() {
- if (mAudioTrack != 0) {
- mAudioTrack->stop();
- mAudioTrack->removeAudioDeviceCallback(mSelfAudioDeviceCallback);
+ sp<AudioTrack> audioTrack = getAudioTrack();
+
+ // Note that there may still be another reference in post-unlock phase of SetPlayState
+ clearAudioTrack();
+
+ if (audioTrack != 0) {
+ audioTrack->stop();
+ audioTrack->removeAudioDeviceCallback(mSelfAudioDeviceCallback);
mSelfAudioDeviceCallback.clear();
- // Note that there may still be another reference in post-unlock phase of SetPlayState
- mAudioTrack.clear();
}
}
@@ -87,16 +90,16 @@
// Implementation of IPlayer
status_t TrackPlayerBase::playerStart() {
status_t status = NO_INIT;
- if (mAudioTrack != 0) {
- status = mAudioTrack->start();
+ if (sp<AudioTrack> audioTrack = getAudioTrack(); audioTrack != 0) {
+ status = audioTrack->start();
}
return status;
}
status_t TrackPlayerBase::playerPause() {
status_t status = NO_INIT;
- if (mAudioTrack != 0) {
- mAudioTrack->pause();
+ if (sp<AudioTrack> audioTrack = getAudioTrack(); audioTrack != 0) {
+ audioTrack->pause();
status = NO_ERROR;
}
return status;
@@ -105,8 +108,8 @@
status_t TrackPlayerBase::playerStop() {
status_t status = NO_INIT;
- if (mAudioTrack != 0) {
- mAudioTrack->stop();
+ if (sp<AudioTrack> audioTrack = getAudioTrack(); audioTrack != 0) {
+ audioTrack->stop();
status = NO_ERROR;
}
return status;
@@ -118,10 +121,10 @@
status_t TrackPlayerBase::doSetVolume() {
status_t status = NO_INIT;
- if (mAudioTrack != 0) {
+ if (sp<AudioTrack> audioTrack = getAudioTrack(); audioTrack != 0) {
float tl = mPlayerVolumeL * mPanMultiplierL * mVolumeMultiplierL;
float tr = mPlayerVolumeR * mPanMultiplierR * mVolumeMultiplierR;
- mAudioTrack->setVolume(tl, tr);
+ audioTrack->setVolume(tl, tr);
status = NO_ERROR;
}
return status;
@@ -140,10 +143,9 @@
if (s != OK) {
return binderStatusFromStatusT(s);
}
-
- if (mAudioTrack != 0) {
+ if (sp<AudioTrack> audioTrack = getAudioTrack(); audioTrack != 0) {
ALOGD("TrackPlayerBase::applyVolumeShaper() from IPlayer");
- VolumeShaper::Status status = mAudioTrack->applyVolumeShaper(spConfiguration, spOperation);
+ VolumeShaper::Status status = audioTrack->applyVolumeShaper(spConfiguration, spOperation);
if (status < 0) { // a non-negative value is the volume shaper id.
ALOGE("TrackPlayerBase::applyVolumeShaper() failed with status %d", status);
}
diff --git a/media/libaudioclient/include/media/TrackPlayerBase.h b/media/libaudioclient/include/media/TrackPlayerBase.h
index fe88116..8df9ff8 100644
--- a/media/libaudioclient/include/media/TrackPlayerBase.h
+++ b/media/libaudioclient/include/media/TrackPlayerBase.h
@@ -19,6 +19,7 @@
#include <media/AudioTrack.h>
#include <media/PlayerBase.h>
+#include <mediautils/Synchronization.h>
namespace android {
@@ -37,10 +38,11 @@
const media::VolumeShaperConfiguration& configuration,
const media::VolumeShaperOperation& operation);
- //FIXME move to protected field, so far made public to minimize changes to AudioTrack logic
- sp<AudioTrack> mAudioTrack;
+ sp<AudioTrack> getAudioTrack() { return mAudioTrack.load(); }
- void setPlayerVolume(float vl, float vr);
+ void clearAudioTrack() { mAudioTrack.store(nullptr); }
+
+ void setPlayerVolume(float vl, float vr);
protected:
@@ -68,6 +70,7 @@
float mPlayerVolumeL, mPlayerVolumeR;
sp<AudioTrack::IAudioTrackCallback> mCallbackHandle;
sp<SelfAudioDeviceCallback> mSelfAudioDeviceCallback;
+ mediautils::atomic_sp<AudioTrack> mAudioTrack;
};
} // namespace android
diff --git a/media/libaudioclient/tests/trackplayerbase_tests.cpp b/media/libaudioclient/tests/trackplayerbase_tests.cpp
index 7317bf0..a4dba9b 100644
--- a/media/libaudioclient/tests/trackplayerbase_tests.cpp
+++ b/media/libaudioclient/tests/trackplayerbase_tests.cpp
@@ -54,7 +54,7 @@
mPlayer = new TrackPlayer();
mPlayer->init(track.get(), mPlayer, PLAYER_TYPE_AAUDIO, AUDIO_USAGE_MEDIA,
AUDIO_SESSION_NONE);
- sp<AudioTrack> playerTrack = mPlayer->mAudioTrack;
+ sp<AudioTrack> playerTrack = mPlayer->getAudioTrack();
ASSERT_EQ(playerTrack->initCheck(), NO_ERROR);
mBufferSize = mFrameCount * playerTrack->frameSize();
@@ -74,7 +74,7 @@
void playBuffer() {
bool blocking = true;
- ssize_t nbytes = mPlayer->mAudioTrack->write(mBuffer.data(), mBufferSize, blocking);
+ ssize_t nbytes = mPlayer->getAudioTrack()->write(mBuffer.data(), mBufferSize, blocking);
EXPECT_EQ(nbytes, mBufferSize) << "Did not write all data in blocking mode";
}
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
index a13903b..f719d97 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -532,5 +532,13 @@
AudioChannelLayout::LAYOUT_HAPTIC_AB /* mask */);
}
+size_t EffectConversionHelperAidl::getInputChannelCount() const {
+ return getChannelCount(mCommon.input.base.channelMask);
+}
+
+size_t EffectConversionHelperAidl::getOutputChannelCount() const {
+ return getChannelCount(mCommon.output.base.channelMask);
+}
+
} // namespace effect
} // namespace android
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
index 50b47a9..e9e9fc2 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.h
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h
@@ -51,6 +51,8 @@
size_t getAudioChannelCount() const;
size_t getHapticChannelCount() const;
+ size_t getInputChannelCount() const;
+ size_t getOutputChannelCount() const;
uint8_t mOutputAccessMode = EFFECT_BUFFER_ACCESS_WRITE;
diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp
index ea4dbf6..f68dd8a 100644
--- a/media/libaudiohal/impl/EffectHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectHalAidl.cpp
@@ -75,7 +75,12 @@
mEffect(effect),
mSessionId(sessionId),
mIoId(ioId),
- mIsProxyEffect(isProxyEffect) {
+ mIsProxyEffect(isProxyEffect),
+ mHalVersion([factory]() {
+ int version = 0;
+ // use factory HAL version because effect can be an EffectProxy instance
+ return factory->getInterfaceVersion(&version).isOk() ? version : 0;
+ }()) {
assert(mFactory != nullptr);
assert(mEffect != nullptr);
createAidlConversion(effect, sessionId, ioId, desc);
@@ -159,6 +164,7 @@
mConversion = std::make_unique<android::effect::AidlConversionVendorExtension>(
effect, sessionId, ioId, desc, mIsProxyEffect);
}
+ mEffectName = mConversion->getDescriptor().common.name;
return OK;
}
@@ -174,100 +180,155 @@
// write to input FMQ here, wait for statusMQ STATUS_OK, and read from output FMQ
status_t EffectHalAidl::process() {
- const std::string effectName = mConversion->getDescriptor().common.name;
State state = State::INIT;
if (mConversion->isBypassing() || !mEffect->getState(&state).isOk() ||
state != State::PROCESSING) {
- ALOGI("%s skipping %s process because it's %s", __func__, effectName.c_str(),
+ ALOGI("%s skipping process because it's %s", mEffectName.c_str(),
mConversion->isBypassing()
? "bypassing"
: aidl::android::hardware::audio::effect::toString(state).c_str());
return -ENODATA;
}
- // check if the DataMq needs any update, timeout at 1ns to avoid being blocked
- auto efGroup = mConversion->getEventFlagGroup();
+ const std::shared_ptr<android::hardware::EventFlag> efGroup = mConversion->getEventFlagGroup();
if (!efGroup) {
- ALOGE("%s invalid efGroup", __func__);
+ ALOGE("%s invalid efGroup", mEffectName.c_str());
return INVALID_OPERATION;
}
- // use IFactory HAL version because IEffect can be an EffectProxy instance
- static const int halVersion = [&]() {
- int version = 0;
- return mFactory->getInterfaceVersion(&version).isOk() ? version : 0;
- }();
+ // reopen if halVersion >= kReopenSupportedVersion and receive kEventFlagDataMqUpdate
+ RETURN_STATUS_IF_ERROR(maybeReopen(efGroup));
+ const size_t samplesWritten = writeToHalInputFmqAndSignal(efGroup);
+ if (0 == samplesWritten) {
+ return INVALID_OPERATION;
+ }
- if (uint32_t efState = 0; halVersion >= kReopenSupportedVersion &&
- ::android::OK == efGroup->wait(kEventFlagDataMqUpdate, &efState,
+ RETURN_STATUS_IF_ERROR(waitHalStatusFmq(samplesWritten));
+ RETURN_STATUS_IF_ERROR(readFromHalOutputFmq(samplesWritten));
+ return OK;
+}
+
+status_t EffectHalAidl::maybeReopen(
+ const std::shared_ptr<android::hardware::EventFlag>& efGroup) const {
+ if (mHalVersion < kReopenSupportedVersion) {
+ return OK;
+ }
+
+ // check if the DataMq needs any update, timeout at 1ns to avoid being blocked
+ if (uint32_t efState = 0; ::android::OK == efGroup->wait(kEventFlagDataMqUpdate, &efState,
1 /* ns */, true /* retry */) &&
efState & kEventFlagDataMqUpdate) {
- ALOGD("%s %s V%d receive dataMQUpdate eventFlag from HAL", __func__, effectName.c_str(),
- halVersion);
-
- mConversion->reopen();
+ ALOGD("%s V%d receive dataMQUpdate eventFlag from HAL", mEffectName.c_str(), mHalVersion);
+ return mConversion->reopen();
}
- auto statusQ = mConversion->getStatusMQ();
- auto inputQ = mConversion->getInputMQ();
- auto outputQ = mConversion->getOutputMQ();
- if (!statusQ || !statusQ->isValid() || !inputQ || !inputQ->isValid() || !outputQ ||
- !outputQ->isValid()) {
- ALOGE("%s invalid FMQ [Status %d I %d O %d]", __func__, statusQ ? statusQ->isValid() : 0,
- inputQ ? inputQ->isValid() : 0, outputQ ? outputQ->isValid() : 0);
- return INVALID_OPERATION;
+ return OK;
+}
+
+size_t EffectHalAidl::writeToHalInputFmqAndSignal(
+ const std::shared_ptr<android::hardware::EventFlag>& efGroup) const {
+ const auto inputQ = mConversion->getInputMQ();
+ if (!inputQ || !inputQ->isValid()) {
+ ALOGE("%s invalid input FMQ", mEffectName.c_str());
+ return 0;
}
- size_t available = inputQ->availableToWrite();
- const size_t floatsToWrite = std::min(available, mInBuffer->getSize() / sizeof(float));
- if (floatsToWrite == 0) {
- ALOGE("%s not able to write, floats in buffer %zu, space in FMQ %zu", __func__,
- mInBuffer->getSize() / sizeof(float), available);
- return INVALID_OPERATION;
+ const size_t fmqSpaceSamples = inputQ->availableToWrite();
+ const size_t samplesInBuffer =
+ mInBuffer->audioBuffer()->frameCount * mConversion->getInputChannelCount();
+ const size_t samplesToWrite = std::min(fmqSpaceSamples, samplesInBuffer);
+ if (samplesToWrite == 0) {
+ ALOGE("%s not able to write, samplesInBuffer %zu, fmqSpaceSamples %zu", mEffectName.c_str(),
+ samplesInBuffer, fmqSpaceSamples);
+ return 0;
}
- if (!mInBuffer->audioBuffer() ||
- !inputQ->write((float*)mInBuffer->audioBuffer()->f32, floatsToWrite)) {
- ALOGE("%s failed to write %zu floats from audiobuffer %p to inputQ [avail %zu]", __func__,
- floatsToWrite, mInBuffer->audioBuffer(), inputQ->availableToWrite());
- return INVALID_OPERATION;
+
+ const float* const inputRawBuffer = static_cast<const float*>(mInBuffer->audioBuffer()->f32);
+ if (!inputQ->write(inputRawBuffer, samplesToWrite)) {
+ ALOGE("%s failed to write %zu samples to inputQ [avail %zu]", mEffectName.c_str(),
+ samplesToWrite, inputQ->availableToWrite());
+ return 0;
}
// for V2 audio effect HAL, expect different EventFlag to avoid bit conflict with FMQ_NOT_EMPTY
- efGroup->wake(halVersion >= kReopenSupportedVersion ? kEventFlagDataMqNotEmpty
- : kEventFlagNotEmpty);
+ efGroup->wake(mHalVersion >= kReopenSupportedVersion ? kEventFlagDataMqNotEmpty
+ : kEventFlagNotEmpty);
+ return samplesToWrite;
+}
+
+void EffectHalAidl::writeHapticGeneratorData(size_t totalSamples, float* const outputRawBuffer,
+ float* const fmqOutputBuffer) const {
+ const auto audioChNum = mConversion->getAudioChannelCount();
+ const auto audioSamples =
+ totalSamples * audioChNum / (audioChNum + mConversion->getHapticChannelCount());
+
+ static constexpr float kHalFloatSampleLimit = 2.0f;
+ // for HapticGenerator, the input data buffer will be updated
+ float* const inputRawBuffer = static_cast<float*>(mInBuffer->audioBuffer()->f32);
+ // accumulate or copy input to output, haptic samples remains all zero
+ if (mConversion->mOutputAccessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
+ accumulate_float(outputRawBuffer, inputRawBuffer, audioSamples);
+ } else {
+ memcpy_to_float_from_float_with_clamping(outputRawBuffer, inputRawBuffer, audioSamples,
+ kHalFloatSampleLimit);
+ }
+ // append the haptic sample at the end of input audio samples
+ memcpy_to_float_from_float_with_clamping(inputRawBuffer + audioSamples,
+ fmqOutputBuffer + audioSamples,
+ totalSamples - audioSamples, kHalFloatSampleLimit);
+}
+
+status_t EffectHalAidl::waitHalStatusFmq(size_t samplesWritten) const {
+ const auto statusQ = mConversion->getStatusMQ();
+ if (const bool statusValid = statusQ && statusQ->isValid(); !statusValid) {
+ ALOGE("%s statusFMQ %s", mEffectName.c_str(), statusValid ? "valid" : "invalid");
+ return INVALID_OPERATION;
+ }
IEffect::Status retStatus{};
if (!statusQ->readBlocking(&retStatus, 1)) {
- ALOGE("%s %s V%d read status from status FMQ failed", __func__, effectName.c_str(),
- halVersion);
+ ALOGE("%s V%d read status from status FMQ failed", mEffectName.c_str(), mHalVersion);
return INVALID_OPERATION;
}
- if (retStatus.status != OK || (size_t)retStatus.fmqConsumed != floatsToWrite ||
+ if (retStatus.status != OK || (size_t)retStatus.fmqConsumed != samplesWritten ||
retStatus.fmqProduced == 0) {
- ALOGE("%s read status failed: %s, consumed %d (of %zu) produced %d", __func__,
- retStatus.toString().c_str(), retStatus.fmqConsumed, floatsToWrite,
- retStatus.fmqProduced);
+ ALOGE("%s read status failed: %s, FMQ consumed %d (of %zu) produced %d",
+ mEffectName.c_str(), retStatus.toString().c_str(), retStatus.fmqConsumed,
+ samplesWritten, retStatus.fmqProduced);
return INVALID_OPERATION;
}
- available = outputQ->availableToRead();
- const size_t floatsToRead = std::min(available, mOutBuffer->getSize() / sizeof(float));
- if (floatsToRead == 0) {
- ALOGE("%s not able to read, buffer space %zu, floats in FMQ %zu", __func__,
- mOutBuffer->getSize() / sizeof(float), available);
+ return OK;
+}
+
+status_t EffectHalAidl::readFromHalOutputFmq(size_t samplesWritten) const {
+ const auto outputQ = mConversion->getOutputMQ();
+ if (const bool outputValid = outputQ && outputQ->isValid(); !outputValid) {
+ ALOGE("%s outputFMQ %s", mEffectName.c_str(), outputValid ? "valid" : "invalid");
return INVALID_OPERATION;
}
- float *outputRawBuffer = mOutBuffer->audioBuffer()->f32;
+ const size_t fmqProducedSamples = outputQ->availableToRead();
+ const size_t bufferSpaceSamples =
+ mOutBuffer->audioBuffer()->frameCount * mConversion->getOutputChannelCount();
+ const size_t samplesToRead = std::min(fmqProducedSamples, bufferSpaceSamples);
+ if (samplesToRead == 0) {
+ ALOGE("%s unable to read, bufferSpace %zu, fmqProduced %zu samplesWritten %zu",
+ mEffectName.c_str(), bufferSpaceSamples, fmqProducedSamples, samplesWritten);
+ return INVALID_OPERATION;
+ }
+
+ float* const outputRawBuffer = static_cast<float*>(mOutBuffer->audioBuffer()->f32);
+ float* fmqOutputBuffer = outputRawBuffer;
std::vector<float> tempBuffer;
// keep original data in the output buffer for accumulate mode or HapticGenerator effect
if (mConversion->mOutputAccessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE || mIsHapticGenerator) {
- tempBuffer.resize(floatsToRead);
- outputRawBuffer = tempBuffer.data();
+ tempBuffer.resize(samplesToRead, 0);
+ fmqOutputBuffer = tempBuffer.data();
}
// always read floating point data for AIDL
- if (!outputQ->read(outputRawBuffer, floatsToRead)) {
- ALOGE("%s failed to read %zu from outputQ to audioBuffer %p", __func__, floatsToRead,
- mOutBuffer->audioBuffer());
+ if (!outputQ->read(fmqOutputBuffer, samplesToRead)) {
+ ALOGE("%s failed to read %zu from outputQ to audioBuffer %p", mEffectName.c_str(),
+ samplesToRead, fmqOutputBuffer);
return INVALID_OPERATION;
}
@@ -276,26 +337,10 @@
// offset as input buffer, here we skip the audio samples in output FMQ and append haptic
// samples to the end of input buffer
if (mIsHapticGenerator) {
- static constexpr float kHalFloatSampleLimit = 2.0f;
- assert(floatsToRead == floatsToWrite);
- const auto audioChNum = mConversion->getAudioChannelCount();
- const auto audioSamples =
- floatsToWrite * audioChNum / (audioChNum + mConversion->getHapticChannelCount());
- // accumulate or copy input to output, haptic samples remains all zero
- if (mConversion->mOutputAccessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
- accumulate_float(mOutBuffer->audioBuffer()->f32, mInBuffer->audioBuffer()->f32,
- audioSamples);
- } else {
- memcpy_to_float_from_float_with_clamping(mOutBuffer->audioBuffer()->f32,
- mInBuffer->audioBuffer()->f32, audioSamples,
- kHalFloatSampleLimit);
- }
- // append the haptic sample at the end of input audio samples
- memcpy_to_float_from_float_with_clamping(mInBuffer->audioBuffer()->f32 + audioSamples,
- outputRawBuffer + audioSamples,
- floatsToRead - audioSamples, kHalFloatSampleLimit);
+ assert(samplesRead == samplesWritten);
+ writeHapticGeneratorData(samplesToRead, outputRawBuffer, fmqOutputBuffer);
} else if (mConversion->mOutputAccessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
- accumulate_float(mOutBuffer->audioBuffer()->f32, outputRawBuffer, floatsToRead);
+ accumulate_float(outputRawBuffer, fmqOutputBuffer, samplesToRead);
}
return OK;
diff --git a/media/libaudiohal/impl/EffectHalAidl.h b/media/libaudiohal/impl/EffectHalAidl.h
index 4f7de7c..c3982a7 100644
--- a/media/libaudiohal/impl/EffectHalAidl.h
+++ b/media/libaudiohal/impl/EffectHalAidl.h
@@ -73,7 +73,9 @@
const int32_t mSessionId;
const int32_t mIoId;
const bool mIsProxyEffect;
+ const int mHalVersion;
bool mIsHapticGenerator = false;
+ std::string mEffectName;
std::unique_ptr<EffectConversionHelperAidl> mConversion;
@@ -93,6 +95,14 @@
bool setEffectReverse(bool reverse);
bool needUpdateReturnParam(uint32_t cmdCode);
+ status_t maybeReopen(const std::shared_ptr<android::hardware::EventFlag>& efGroup) const;
+ void writeHapticGeneratorData(size_t totalSamples, float* const outputRawBuffer,
+ float* const fmqOutputBuffer) const;
+ size_t writeToHalInputFmqAndSignal(
+ const std::shared_ptr<android::hardware::EventFlag>& efGroup) const;
+ status_t waitHalStatusFmq(size_t samplesWritten) const;
+ status_t readFromHalOutputFmq(size_t samplesWritten) const;
+
// The destructor automatically releases the effect.
virtual ~EffectHalAidl();
};
diff --git a/media/libaudioprocessing/AudioMixerOps.h b/media/libaudioprocessing/AudioMixerOps.h
index ab6a8b6..8f60d29 100644
--- a/media/libaudioprocessing/AudioMixerOps.h
+++ b/media/libaudioprocessing/AudioMixerOps.h
@@ -347,6 +347,7 @@
[6] = AUDIO_CHANNEL_OUT_5POINT1,
[7] = AUDIO_CHANNEL_OUT_6POINT1,
[8] = AUDIO_CHANNEL_OUT_7POINT1,
+ [10] = AUDIO_CHANNEL_OUT_5POINT1POINT4,
[12] = AUDIO_CHANNEL_OUT_7POINT1POINT4,
[14] = AUDIO_CHANNEL_OUT_9POINT1POINT4,
[16] = AUDIO_CHANNEL_OUT_9POINT1POINT6,
diff --git a/media/libaudioprocessing/tests/mixerops_tests.cpp b/media/libaudioprocessing/tests/mixerops_tests.cpp
index 2500ba9..235129f 100644
--- a/media/libaudioprocessing/tests/mixerops_tests.cpp
+++ b/media/libaudioprocessing/tests/mixerops_tests.cpp
@@ -154,6 +154,9 @@
TEST(mixerops, stereovolume_8) {
MixerOpsBasicTest<MIXTYPE_MULTI_STEREOVOL, 8>::testStereoVolume();
}
+TEST(mixerops, stereovolume_10) {
+ MixerOpsBasicTest<MIXTYPE_MULTI_STEREOVOL, 10>::testStereoVolume();
+}
TEST(mixerops, stereovolume_12) {
if constexpr (FCC_LIMIT >= 12) { // NOTE: FCC_LIMIT is an enum, so can't #if
MixerOpsBasicTest<MIXTYPE_MULTI_STEREOVOL, 12>::testStereoVolume();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index f4143da..3987a67 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -43,6 +43,12 @@
#include <mpeg2ts/ATSParser.h>
#include <gui/Surface.h>
+#define ATRACE_TAG ATRACE_TAG_AUDIO
+#include <utils/Trace.h>
+
+#include <android-base/stringprintf.h>
+using ::android::base::StringPrintf;
+
namespace android {
static float kDisplayRefreshingRate = 60.f; // TODO: get this from the display
@@ -157,7 +163,10 @@
int32_t index;
CHECK(msg->findInt32("index", &index));
+ ATRACE_BEGIN(StringPrintf("Nuplayer::handleAnInputBuffer [%s]",
+ mIsAudio ? "audio" : "video").c_str());
handleAnInputBuffer(index);
+ ATRACE_END();
break;
}
@@ -175,7 +184,10 @@
CHECK(msg->findInt64("timeUs", &timeUs));
CHECK(msg->findInt32("flags", &flags));
+ ATRACE_BEGIN(StringPrintf("Nuplayer::handleAnOutputBuffer [%s]",
+ mIsAudio ? "audio" : "video").c_str());
handleAnOutputBuffer(index, offset, size, timeUs, flags);
+ ATRACE_END();
break;
}
@@ -184,7 +196,10 @@
sp<AMessage> format;
CHECK(msg->findMessage("format", &format));
+ ATRACE_BEGIN(StringPrintf("Nuplayer::handleOutputFormatChange [%s]",
+ mIsAudio ? "audio" : "video").c_str());
handleOutputFormatChange(format);
+ ATRACE_END();
break;
}
@@ -205,15 +220,16 @@
break;
}
}
-
break;
}
case kWhatRenderBuffer:
{
+ ATRACE_BEGIN("Nuplayer::onRenderBuffer");
if (!isStaleReply(msg)) {
onRenderBuffer(msg);
}
+ ATRACE_END();
break;
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.cpp
index 3e96d27..0cb5062 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderBase.cpp
@@ -27,6 +27,12 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
+#define ATRACE_TAG ATRACE_TAG_AUDIO
+#include <utils/Trace.h>
+
+#include <android-base/stringprintf.h>
+using ::android::base::StringPrintf;
+
namespace android {
NuPlayer::DecoderBase::DecoderBase(const sp<AMessage> ¬ify)
@@ -129,9 +135,11 @@
switch (msg->what()) {
case kWhatConfigure:
{
+ ATRACE_BEGIN("NuPlayer::DecoderBase::onConfigure");
sp<AMessage> format;
CHECK(msg->findMessage("format", &format));
onConfigure(format);
+ ATRACE_END();
break;
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index c6595ba..851d252 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -36,6 +36,11 @@
#include <media/stagefright/Utils.h>
#include <media/stagefright/FoundationUtils.h>
+#define ATRACE_TAG ATRACE_TAG_AUDIO
+#include <utils/Trace.h>
+#include <android-base/stringprintf.h>
+using ::android::base::StringPrintf;
+
static const int kDumpLockRetries = 50;
static const int kDumpLockSleepUs = 20000;
@@ -146,9 +151,11 @@
const char *url,
const KeyedVector<String8, String8> *headers) {
ALOGV("setDataSource(%p) url(%s)", this, uriDebugString(url, false).c_str());
+ ATRACE_BEGIN(StringPrintf("setDataSource(%p)", this).c_str());
Mutex::Autolock autoLock(mLock);
if (mState != STATE_IDLE) {
+ ATRACE_END();
return INVALID_OPERATION;
}
@@ -159,15 +166,18 @@
while (mState == STATE_SET_DATASOURCE_PENDING) {
mCondition.wait(mLock);
}
+ ATRACE_END();
return mAsyncResult;
}
status_t NuPlayerDriver::setDataSource(int fd, int64_t offset, int64_t length) {
ALOGV("setDataSource(%p) file(%d)", this, fd);
+ ATRACE_BEGIN(StringPrintf("setDataSource(%p) file(%d)", this, fd).c_str());
Mutex::Autolock autoLock(mLock);
if (mState != STATE_IDLE) {
+ ATRACE_END();
return INVALID_OPERATION;
}
@@ -178,15 +188,18 @@
while (mState == STATE_SET_DATASOURCE_PENDING) {
mCondition.wait(mLock);
}
+ ATRACE_END();
return mAsyncResult;
}
status_t NuPlayerDriver::setDataSource(const sp<IStreamSource> &source) {
ALOGV("setDataSource(%p) stream source", this);
+ ATRACE_BEGIN(StringPrintf("setDataSource(%p) stream source", this).c_str());
Mutex::Autolock autoLock(mLock);
if (mState != STATE_IDLE) {
+ ATRACE_END();
return INVALID_OPERATION;
}
@@ -197,15 +210,18 @@
while (mState == STATE_SET_DATASOURCE_PENDING) {
mCondition.wait(mLock);
}
+ ATRACE_END();
return mAsyncResult;
}
status_t NuPlayerDriver::setDataSource(const sp<DataSource> &source) {
ALOGV("setDataSource(%p) callback source", this);
+ ATRACE_BEGIN(StringPrintf("setDataSource(%p) callback source", this).c_str());
Mutex::Autolock autoLock(mLock);
if (mState != STATE_IDLE) {
+ ATRACE_END();
return INVALID_OPERATION;
}
@@ -216,15 +232,18 @@
while (mState == STATE_SET_DATASOURCE_PENDING) {
mCondition.wait(mLock);
}
+ ATRACE_END();
return mAsyncResult;
}
status_t NuPlayerDriver::setDataSource(const String8& rtpParams) {
ALOGV("setDataSource(%p) rtp source", this);
+ ATRACE_BEGIN(StringPrintf("setDataSource(%p) rtp source", this).c_str());
Mutex::Autolock autoLock(mLock);
if (mState != STATE_IDLE) {
+ ATRACE_END();
return INVALID_OPERATION;
}
@@ -235,6 +254,7 @@
while (mState == STATE_SET_DATASOURCE_PENDING) {
mCondition.wait(mLock);
}
+ ATRACE_END();
return mAsyncResult;
}
@@ -295,8 +315,11 @@
status_t NuPlayerDriver::prepare() {
ALOGV("prepare(%p)", this);
+ ATRACE_BEGIN(StringPrintf("prepare(%p)", this).c_str());
Mutex::Autolock autoLock(mLock);
- return prepare_l();
+ status_t ret = prepare_l();
+ ATRACE_END();
+ return ret;
}
status_t NuPlayerDriver::prepare_l() {
@@ -354,8 +377,11 @@
status_t NuPlayerDriver::start() {
ALOGV("start(%p), state is %d, eos is %d", this, mState, mAtEOS);
+ ATRACE_BEGIN(StringPrintf("start(%p), state is %d, eos is %d", this, mState, mAtEOS).c_str());
Mutex::Autolock autoLock(mLock);
- return start_l();
+ status_t ret = start_l();
+ ATRACE_END();
+ return ret;
}
status_t NuPlayerDriver::start_l() {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 3c8b809..899d50e 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -15,6 +15,7 @@
*/
//#define LOG_NDEBUG 0
+#define ATRACE_TAG ATRACE_TAG_AUDIO
#define LOG_TAG "NuPlayerRenderer"
#include <utils/Log.h>
@@ -37,6 +38,9 @@
#include <inttypes.h>
+#include <android-base/stringprintf.h>
+using ::android::base::StringPrintf;
+
namespace android {
/*
@@ -2000,6 +2004,8 @@
bool isStreaming) {
ALOGV("openAudioSink: offloadOnly(%d) offloadingAudio(%d)",
offloadOnly, offloadingAudio());
+ ATRACE_BEGIN(StringPrintf("NuPlayer::Renderer::onOpenAudioSink: offloadOnly(%d) "
+ "offloadingAudio(%d)", offloadOnly, offloadingAudio()).c_str());
bool audioSinkChanged = false;
int32_t numChannels;
@@ -2071,6 +2077,7 @@
if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) {
ALOGV("openAudioSink: no change in offload mode");
// no change from previous configuration, everything ok.
+ ATRACE_END();
return OK;
}
mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
@@ -2140,6 +2147,7 @@
if (memcmp(&mCurrentPcmInfo, &info, sizeof(info)) == 0) {
ALOGV("openAudioSink: no change in pcm mode");
// no change from previous configuration, everything ok.
+ ATRACE_END();
return OK;
}
@@ -2184,6 +2192,7 @@
ALOGW("openAudioSink: non offloaded open failed status: %d", err);
mAudioSink->close();
mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
+ ATRACE_END();
return err;
}
mCurrentPcmInfo = info;
@@ -2195,13 +2204,16 @@
onAudioSinkChanged();
}
mAudioTornDown = false;
+ ATRACE_END();
return OK;
}
void NuPlayer::Renderer::onCloseAudioSink() {
+ ATRACE_BEGIN("NuPlyer::Renderer::onCloseAudioSink");
mAudioSink->close();
mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
+ ATRACE_END();
}
void NuPlayer::Renderer::onChangeAudioFormat(
diff --git a/media/module/codecserviceregistrant/CodecServiceRegistrant.cpp b/media/module/codecserviceregistrant/CodecServiceRegistrant.cpp
index 42fd94e..433b5e9 100644
--- a/media/module/codecserviceregistrant/CodecServiceRegistrant.cpp
+++ b/media/module/codecserviceregistrant/CodecServiceRegistrant.cpp
@@ -790,47 +790,6 @@
}
using namespace ::android::hardware::media::c2;
-
- if (!ionPropertiesDefined()) {
- using IComponentStore =
- ::android::hardware::media::c2::V1_0::IComponentStore;
- std::string const preferredStoreName = "default";
- if (aidlSelected) {
- std::shared_ptr<c2_aidl::IComponentStore> preferredStore;
- if (__builtin_available(android __ANDROID_API_S__, *)) {
- std::string instanceName = ::android::base::StringPrintf(
- "%s/%s", c2_aidl::IComponentStore::descriptor, preferredStoreName.c_str());
- if (AServiceManager_isDeclared(instanceName.c_str())) {
- preferredStore = c2_aidl::IComponentStore::fromBinder(::ndk::SpAIBinder(
- AServiceManager_waitForService(instanceName.c_str())));
- }
- }
- if (preferredStore) {
- ::android::SetPreferredCodec2ComponentStore(
- std::make_shared<H2C2ComponentStore>(preferredStore));
- LOG(INFO) <<
- "Preferred Codec2 AIDL store is set to \"" <<
- preferredStoreName << "\".";
- } else {
- LOG(INFO) <<
- "Preferred Codec2 AIDL store is defaulted to \"software\".";
- }
- } else {
- sp<IComponentStore> preferredStore =
- IComponentStore::getService(preferredStoreName.c_str());
- if (preferredStore) {
- ::android::SetPreferredCodec2ComponentStore(
- std::make_shared<H2C2ComponentStore>(preferredStore));
- LOG(INFO) <<
- "Preferred Codec2 HIDL store is set to \"" <<
- preferredStoreName << "\".";
- } else {
- LOG(INFO) <<
- "Preferred Codec2 HIDL store is defaulted to \"software\".";
- }
- }
- }
-
bool registered = false;
const std::string aidlServiceName =
std::string(c2_aidl::IComponentStore::descriptor) + "/software";
@@ -876,6 +835,48 @@
" so it is not being registered with hwservicemanager.";
}
+ // Preferred store must be set after the store is registered to ensure that
+ // the correct preferred store is set.
+ if (!ionPropertiesDefined()) {
+ using IComponentStore =
+ ::android::hardware::media::c2::V1_0::IComponentStore;
+ std::string const preferredStoreName = "default";
+ if (aidlSelected) {
+ std::shared_ptr<c2_aidl::IComponentStore> preferredStore;
+ if (__builtin_available(android __ANDROID_API_S__, *)) {
+ std::string instanceName = ::android::base::StringPrintf(
+ "%s/%s", c2_aidl::IComponentStore::descriptor, preferredStoreName.c_str());
+ if (AServiceManager_isDeclared(instanceName.c_str())) {
+ preferredStore = c2_aidl::IComponentStore::fromBinder(::ndk::SpAIBinder(
+ AServiceManager_waitForService(instanceName.c_str())));
+ }
+ }
+ if (preferredStore) {
+ ::android::SetPreferredCodec2ComponentStore(
+ std::make_shared<H2C2ComponentStore>(preferredStore));
+ LOG(INFO) <<
+ "Preferred Codec2 AIDL store is set to \"" <<
+ preferredStoreName << "\".";
+ } else {
+ LOG(INFO) <<
+ "Preferred Codec2 AIDL store is defaulted to \"software\".";
+ }
+ } else {
+ sp<IComponentStore> preferredStore =
+ IComponentStore::getService(preferredStoreName.c_str());
+ if (preferredStore) {
+ ::android::SetPreferredCodec2ComponentStore(
+ std::make_shared<H2C2ComponentStore>(preferredStore));
+ LOG(INFO) <<
+ "Preferred Codec2 HIDL store is set to \"" <<
+ preferredStoreName << "\".";
+ } else {
+ LOG(INFO) <<
+ "Preferred Codec2 HIDL store is defaulted to \"software\".";
+ }
+ }
+ }
+
if (registered) {
LOG(INFO) << "Software Codec2 service created and registered.";
}
diff --git a/media/psh_utils/Android.bp b/media/psh_utils/Android.bp
index 4662db8..dafa63b 100644
--- a/media/psh_utils/Android.bp
+++ b/media/psh_utils/Android.bp
@@ -19,18 +19,23 @@
local_include_dirs: ["include"],
export_include_dirs: ["include"],
srcs: [
+ "AudioPowerManager.cpp",
+ "AudioToken.cpp",
"HealthStats.cpp",
"HealthStatsProvider.cpp",
+ "PowerClientStats.cpp",
"PowerStats.cpp",
"PowerStatsCollector.cpp",
"PowerStatsProvider.cpp",
],
shared_libs: [
+ "com.android.media.audio-aconfig-cc",
"libaudioutils",
"libbase",
"libbinder_ndk",
"libcutils",
"liblog",
+ "libmediautils",
"libutils",
],
cflags: [
diff --git a/media/psh_utils/AudioPowerManager.cpp b/media/psh_utils/AudioPowerManager.cpp
new file mode 100644
index 0000000..3ae681a
--- /dev/null
+++ b/media/psh_utils/AudioPowerManager.cpp
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2024 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 "AudioToken.h"
+#define LOG_TAG "AudioPowerManager"
+#include <com_android_media_audioserver.h>
+#include <cutils/properties.h>
+#include <utils/Log.h>
+#include <psh_utils/AudioPowerManager.h>
+
+namespace android::media::psh_utils {
+
+/* static */
+AudioPowerManager& AudioPowerManager::getAudioPowerManager() {
+ [[clang::no_destroy]] static AudioPowerManager apm;
+ return apm;
+}
+
+std::unique_ptr<Token> AudioPowerManager::startClient(pid_t pid, uid_t uid,
+ const std::string& additional) {
+ std::shared_ptr<PowerClientStats> powerClientStats;
+ std::lock_guard l(mMutex);
+ if (mPowerClientStats.count(uid) == 0) {
+ const auto it = mHistoricalClients.find(uid);
+ if (it == mHistoricalClients.end()) {
+ powerClientStats = std::make_shared<PowerClientStats>(uid, additional);
+ } else {
+ powerClientStats = it->second;
+ mHistoricalClients.erase(it);
+ }
+ mPowerClientStats[uid] = powerClientStats;
+ } else {
+ powerClientStats = mPowerClientStats[uid];
+ }
+ powerClientStats->addPid(pid);
+ mPidToUid[pid] = uid;
+ std::unique_ptr<Token> token =
+ std::make_unique<AudioClientToken>(powerClientStats, pid, uid, additional);
+ mOutstandingTokens.emplace(token.get());
+ return token;
+}
+
+std::unique_ptr<Token> AudioPowerManager::startTrack(uid_t uid, const std::string& additional) {
+ std::lock_guard l(mMutex);
+ if (mPowerClientStats.count(uid) == 0) {
+ ALOGW("%s: Cannot find uid: %d", __func__, uid);
+ return {};
+ }
+ auto powerClientStats = mPowerClientStats[uid];
+ std::unique_ptr<Token> token =
+ std::make_unique<AudioTrackToken>(powerClientStats, additional);
+ mOutstandingTokens.emplace(token.get());
+ return token;
+}
+
+std::unique_ptr<Token> AudioPowerManager::startThread(
+ pid_t pid, const std::string& wakeLockName,
+ WakeFlag wakeFlag, const std::string& additional) {
+ std::lock_guard l(mMutex);
+ std::unique_ptr<Token> token =
+ std::make_unique<AudioThreadToken>(pid, wakeLockName, wakeFlag, additional);
+ mOutstandingTokens.emplace(token.get());
+ return token;
+}
+
+std::string AudioPowerManager::toString() const {
+ const std::string prefix(" ");
+ std::string result;
+ std::lock_guard l(mMutex);
+ result.append("Power Tokens:\n");
+ std::vector<std::string> tokenInfo;
+ for (const auto& token: mOutstandingTokens) {
+ tokenInfo.emplace_back(token->toString());
+ }
+ std::sort(tokenInfo.begin(), tokenInfo.end());
+ for (const auto& info: tokenInfo) {
+ result.append(prefix).append(info).append("\n");
+ }
+ result.append("Power Clients:\n");
+ for (const auto& [uid, powerClientStats]: mPowerClientStats) {
+ result.append(powerClientStats->toString(true, prefix));
+ }
+ result.append("Power Client History:\n");
+ for (const auto& [power, powerClientStats]: mHistoricalClients) {
+ result.append(powerClientStats->toString(true, prefix));
+ }
+ return result;
+}
+
+void AudioPowerManager::stopClient(pid_t pid) {
+ std::lock_guard l(mMutex);
+ const auto pidit = mPidToUid.find(pid);
+ if (pidit == mPidToUid.end()) return;
+ const uid_t uid = pidit->second;
+ const auto it = mPowerClientStats.find(uid);
+ if (it == mPowerClientStats.end()) return;
+
+ auto powerClientStats = it->second;
+ size_t count = powerClientStats->removePid(pid);
+ if (count == 0) {
+ mHistoricalClients[uid] = powerClientStats;
+ mPowerClientStats.erase(it);
+ if (mHistoricalClients.size() > kHistory) {
+ mHistoricalClients.erase(mHistoricalClients.begin()); // remove oldest.
+ }
+ }
+ mPidToUid.erase(pid);
+}
+
+void AudioPowerManager::clear_token_ptr(Token* token) {
+ if (token != nullptr) {
+ std::lock_guard l(mMutex);
+ (void)mOutstandingTokens.erase(token);
+ }
+}
+
+/* static */
+bool AudioPowerManager::enabled() {
+ static const bool enabled = com::android::media::audioserver::power_stats()
+ && property_get_bool("persist.audio.power_stats.enabled", false);
+ return enabled;
+}
+
+} // namespace android::media::psh_utils
diff --git a/media/psh_utils/AudioToken.cpp b/media/psh_utils/AudioToken.cpp
new file mode 100644
index 0000000..f7bf382
--- /dev/null
+++ b/media/psh_utils/AudioToken.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2024 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 "AudioToken"
+#include <android-base/logging.h>
+#include <utils/Log.h>
+#include "AudioToken.h"
+#include <psh_utils/AudioPowerManager.h>
+
+namespace android::media::psh_utils {
+
+/* static */
+constinit std::atomic<size_t> AudioClientToken::sIdCounter{};
+
+AudioClientToken::AudioClientToken(
+ std::shared_ptr<PowerClientStats> powerClientStats, pid_t pid, uid_t uid,
+ const std::string& additional)
+ : mPowerClientStats(std::move(powerClientStats))
+ , mPid(pid)
+ , mAdditional(additional)
+ , mId(sIdCounter.fetch_add(1, std::memory_order_relaxed)) {
+ (void)uid;
+}
+
+AudioClientToken::~AudioClientToken() {
+ auto& apm = AudioPowerManager::getAudioPowerManager();
+
+ // APM has a back pointer to AudioToken, which is accessible on toString().
+ // We first remove ourselves to prevent use after free.
+ apm.clear_token_ptr(this);
+
+ // The client token is released when it is no longer registered with AudioFlinger.
+ // However, it is possible that AudioTrackTokens are still active when the client is released
+ // after crashing and some of its tracks are draining. Those track tokens also
+ // maintain a pointer to the PowerClientStats keeping that consistent.
+
+ // Stopping the client moves its PowerClientStats from active to historical
+ // if it is the last pid associated with the client uid.
+ apm.stopClient(mPid);
+}
+
+std::string AudioClientToken::toString() const {
+ std::string result("Client-");
+ result.append(std::to_string(mId)).append(": ")
+ .append(" pid: ").append(std::to_string(mPid));
+ if (!mAdditional.empty()) {
+ result.append(" ").append(mAdditional);
+ }
+ return result;
+}
+
+std::unique_ptr<Token> createAudioClientToken(pid_t pid, uid_t uid,
+ const std::string& additional) {
+ return AudioPowerManager::getAudioPowerManager().startClient(pid, uid, additional);
+}
+
+/* static */
+constinit std::atomic<size_t> AudioThreadToken::sIdCounter{};
+
+AudioThreadToken::AudioThreadToken(
+ pid_t tid, const std::string& wakeLockName,
+ WakeFlag wakeFlag, const std::string& additional)
+ : mTid(tid)
+ , mWakeLockName(wakeLockName)
+ , mWakeFlag(wakeFlag)
+ , mAdditional(additional)
+ , mId(sIdCounter.fetch_add(1, std::memory_order_relaxed)) {
+}
+
+AudioThreadToken::~AudioThreadToken() {
+ auto& apm = AudioPowerManager::getAudioPowerManager();
+
+ // APM has a back pointer to AudioToken, which is accessible on toString().
+ // We first remove ourselves to prevent use after free.
+ apm.clear_token_ptr(this);
+}
+
+std::string AudioThreadToken::toString() const {
+ std::string result("Thread-");
+ result.append(std::to_string(mId)).append(": ")
+ .append(" ThreadBase-tid: ").append(std::to_string(mTid))
+ .append(" wakeLockName: ").append(mWakeLockName)
+ .append(" wakeFlag: ").append(::android::media::psh_utils::toString(mWakeFlag));
+ if (!mAdditional.empty()) {
+ result.append(" ").append(mAdditional);
+ }
+ return result;
+}
+
+std::unique_ptr<Token> createAudioThreadToken(
+ pid_t pid, const std::string& wakeLockName,
+ WakeFlag wakeFlag, const std::string& additional) {
+ return AudioPowerManager::getAudioPowerManager().startThread(
+ pid, wakeLockName, wakeFlag, additional);
+}
+
+/* static */
+constinit std::atomic<size_t> AudioTrackToken::sIdCounter{};
+
+AudioTrackToken::AudioTrackToken(
+ std::shared_ptr<PowerClientStats> powerClientStats, const std::string& additional)
+ : mPowerClientStats(std::move(powerClientStats))
+ , mAdditional(additional)
+ , mId(sIdCounter.fetch_add(1, std::memory_order_relaxed)) {
+ if (mPowerClientStats){
+ mPowerClientStats->getCommandThread().add(
+ "start",
+ [pas = mPowerClientStats, actualNs = systemTime(SYSTEM_TIME_BOOTTIME)]() {
+ pas->start(actualNs);
+ });
+ }
+}
+
+AudioTrackToken::~AudioTrackToken() {
+ // APM has a back pointer to AudioToken, which is accessible on toString().
+ // We first remove ourselves to prevent use after free.
+ AudioPowerManager::getAudioPowerManager().clear_token_ptr(this);
+ if (mPowerClientStats) {
+ mPowerClientStats->getCommandThread().add(
+ "stop",
+ [pas = mPowerClientStats, actualNs = systemTime(SYSTEM_TIME_BOOTTIME)]() {
+ pas->stop(actualNs);
+ });
+ }
+}
+
+std::string AudioTrackToken::toString() const {
+ std::string result("Track-");
+ result.append(std::to_string(mId)).append(": ")
+ .append(mPowerClientStats ? mPowerClientStats->toString() : std::string("null"));
+ if (!mAdditional.empty()) {
+ result.append(" ").append(mAdditional);
+ }
+ return result;
+}
+
+std::unique_ptr<Token> createAudioTrackToken(uid_t uid, const std::string& additional) {
+ return AudioPowerManager::getAudioPowerManager().startTrack(uid, additional);
+}
+
+
+} // namespace android::media::psh_utils
diff --git a/media/psh_utils/AudioToken.h b/media/psh_utils/AudioToken.h
new file mode 100644
index 0000000..aa25b04
--- /dev/null
+++ b/media/psh_utils/AudioToken.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2024 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 <psh_utils/PowerClientStats.h>
+#include <psh_utils/Token.h>
+
+#include <atomic>
+#include <memory>
+#include <string>
+
+namespace android::media::psh_utils {
+
+class AudioClientToken : public Token {
+public:
+ AudioClientToken(std::shared_ptr<PowerClientStats> powerClientStats, pid_t pid, uid_t uid,
+ const std::string& additional);
+ ~AudioClientToken() override;
+
+ // AudioPowerManager may call toString() while AudioToken is in its dtor.
+ // It is safe so long as toString is final.
+ std::string toString() const final;
+
+private:
+ const std::shared_ptr<PowerClientStats> mPowerClientStats;
+ const pid_t mPid;
+ const std::string mAdditional;
+ const size_t mId;
+ static constinit std::atomic<size_t> sIdCounter;
+};
+
+class AudioThreadToken : public Token {
+public:
+ AudioThreadToken(
+ pid_t tid, const std::string& wakeLockName,
+ WakeFlag wakeFlag, const std::string& additional);
+ ~AudioThreadToken() override;
+
+ // AudioPowerManager may call toString() while AudioToken is in its dtor.
+ // It is safe so long as toString is final.
+ std::string toString() const final;
+
+private:
+ const pid_t mTid;
+ const std::string mWakeLockName;
+ const WakeFlag mWakeFlag;
+ const std::string mAdditional;
+ const size_t mId;
+ static constinit std::atomic<size_t> sIdCounter;
+};
+
+class AudioTrackToken : public Token {
+public:
+ AudioTrackToken(
+ std::shared_ptr<PowerClientStats> powerClientStats, const std::string& additional);
+ ~AudioTrackToken() override;
+
+ // AudioPowerManager may call toString() while AudioToken is in its dtor.
+ // It is safe so long as toString is final.
+ std::string toString() const final;
+
+private:
+ const std::shared_ptr<PowerClientStats> mPowerClientStats;
+ const std::string mAdditional;
+ const size_t mId;
+ static constinit std::atomic<size_t> sIdCounter;
+};
+
+} // namespace android::media::psh_utils
diff --git a/media/psh_utils/PowerClientStats.cpp b/media/psh_utils/PowerClientStats.cpp
new file mode 100644
index 0000000..65f65a44
--- /dev/null
+++ b/media/psh_utils/PowerClientStats.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2024 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 <psh_utils/PowerClientStats.h>
+#include <mediautils/ServiceUtilities.h>
+
+namespace android::media::psh_utils {
+
+/* static */
+audio_utils::CommandThread& PowerClientStats::getCommandThread() {
+ [[clang::no_destroy]] static audio_utils::CommandThread ct;
+ return ct;
+}
+
+PowerClientStats::PowerClientStats(uid_t uid, const std::string& additional)
+ : mUid(uid), mAdditional(additional) {}
+
+void PowerClientStats::start(int64_t actualNs) {
+ std::lock_guard l(mMutex);
+ ++mTokenCount;
+ if (mStartNs == 0) mStartNs = actualNs;
+ if (mStartStats) return;
+ mStartStats = PowerStatsCollector::getCollector().getStats(kStatTimeToleranceNs);
+}
+
+void PowerClientStats::stop(int64_t actualNs) {
+ std::lock_guard l(mMutex);
+ if (--mTokenCount > 0) return;
+ if (mStartNs != 0) mCumulativeNs += actualNs - mStartNs;
+ mStartNs = 0;
+ if (!mStartStats) return;
+ const auto stopStats = PowerStatsCollector::getCollector().getStats(kStatTimeToleranceNs);
+ if (stopStats && stopStats != mStartStats) {
+ *mCumulativeStats += *stopStats - *mStartStats;
+ }
+ mStartStats.reset();
+}
+
+void PowerClientStats::addPid(pid_t pid) {
+ std::lock_guard l(mMutex);
+ mPids.emplace(pid);
+}
+
+size_t PowerClientStats::removePid(pid_t pid) {
+ std::lock_guard l(mMutex);
+ mPids.erase(pid);
+ return mPids.size();
+}
+
+std::string PowerClientStats::toString(bool stats, const std::string& prefix) const {
+ std::lock_guard l(mMutex);
+
+ // Adjust delta time and stats if currently running.
+ auto cumulativeStats = mCumulativeStats;
+ auto cumulativeNs = mCumulativeNs;
+ if (mStartNs) cumulativeNs += systemTime(SYSTEM_TIME_BOOTTIME) - mStartNs;
+ if (mStartStats) {
+ const auto stopStats = PowerStatsCollector::getCollector().getStats(kStatTimeToleranceNs);
+ if (stopStats && stopStats != mStartStats) {
+ auto newStats = std::make_shared<PowerStats>(*cumulativeStats);
+ *newStats += *stopStats - *mStartStats;
+ cumulativeStats = newStats;
+ }
+ }
+
+ std::string result(prefix);
+ result.append("uid: ")
+ .append(std::to_string(mUid))
+ .append(" ").append(mediautils::UidInfo::getInfo(mUid)->package)
+ .append(" streams: ").append(std::to_string(mTokenCount))
+ .append(" seconds: ").append(std::to_string(cumulativeNs * 1e-9));
+ result.append(" {");
+ for (auto pid : mPids) {
+ result.append(" ").append(std::to_string(pid));
+ }
+ result.append(" }");
+ if (!mAdditional.empty()) {
+ result.append("\n").append(prefix).append(mAdditional);
+ }
+ if (stats) {
+ std::string prefix2(prefix);
+ prefix2.append(" ");
+ result.append("\n").append(cumulativeStats->normalizedEnergy(prefix2));
+ }
+ return result;
+}
+
+} // namespace android::media::psh_utils
diff --git a/media/psh_utils/benchmarks/Android.bp b/media/psh_utils/benchmarks/Android.bp
index 20efaa9..2382c69 100644
--- a/media/psh_utils/benchmarks/Android.bp
+++ b/media/psh_utils/benchmarks/Android.bp
@@ -17,14 +17,15 @@
"-Werror",
],
static_libs: [
- "libaudioutils",
"libpshutils",
],
shared_libs: [
+ "libaudioutils",
"libbase",
"libbinder_ndk",
"libcutils",
"liblog",
+ "libmediautils",
"libutils",
],
}
@@ -38,14 +39,37 @@
"-Werror",
],
static_libs: [
- "libaudioutils",
"libpshutils",
],
shared_libs: [
+ "libaudioutils",
"libbase",
"libbinder_ndk",
"libcutils",
"liblog",
+ "libmediautils",
+ "libutils",
+ ],
+}
+
+cc_benchmark {
+ name: "audio_token_benchmark",
+
+ srcs: ["audio_token_benchmark.cpp"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ static_libs: [
+ "libpshutils",
+ ],
+ shared_libs: [
+ "libaudioutils",
+ "libbase",
+ "libbinder_ndk",
+ "libcutils",
+ "liblog",
+ "libmediautils",
"libutils",
],
}
diff --git a/media/psh_utils/benchmarks/audio_powerstats_benchmark.cpp b/media/psh_utils/benchmarks/audio_powerstats_benchmark.cpp
index d3f815c..4d8b224 100644
--- a/media/psh_utils/benchmarks/audio_powerstats_benchmark.cpp
+++ b/media/psh_utils/benchmarks/audio_powerstats_benchmark.cpp
@@ -26,6 +26,140 @@
#include <thread>
#include <vector>
+/*
+Pixel 9 XL Pro
+---------------------------------------------------------------------------------------------------------------
+Benchmark Time CPU Iteration
+---------------------------------------------------------------------------------------------------------------
+audio_powerstats_benchmark:
+ #MemoryFixture/CacheAccess/64/0/0/1 5.195761589711465 ns 5.183635029038574 ns 135160912
+ #MemoryFixture/CacheAccess/128/0/0/1 10.37270431027728 ns 10.341754343667125 ns 67574354
+ #MemoryFixture/CacheAccess/256/0/0/1 20.767353363364098 ns 20.708496782017836 ns 33809541
+ #MemoryFixture/CacheAccess/512/0/0/1 41.53473855852046 ns 41.45724926375999 ns 16900399
+ #MemoryFixture/CacheAccess/1024/0/0/1 82.89673650172568 ns 82.68064919937272 ns 8462177
+ #MemoryFixture/CacheAccess/2048/0/0/1 165.77648929323732 ns 165.45127650324827 ns 4227878
+ #MemoryFixture/CacheAccess/4096/0/0/1 331.9272979248067 ns 331.0722959129879 ns 2114919
+ #MemoryFixture/CacheAccess/8192/0/0/1 663.8090302013887 ns 662.2813002594532 ns 1054528
+ #MemoryFixture/CacheAccess/16384/0/0/1 1327.4224893455748 ns 1324.0114138292752 ns 529095
+ #MemoryFixture/CacheAccess/32768/0/0/1 2657.1037276954685 ns 2651.8974883509522 ns 263970
+ #MemoryFixture/CacheAccess/65536/0/0/1 5314.170125835522 ns 5305.20127734871 ns 131679
+ #MemoryFixture/CacheAccess/131072/0/0/1 10624.517848490625 ns 10602.467739493763 ns 66056
+ #MemoryFixture/CacheAccess/262144/0/0/1 21271.09560700047 ns 21224.851075464823 ns 32916
+ #MemoryFixture/CacheAccess/524288/0/0/1 42556.76641626909 ns 42444.65628786041 ns 16508
+ #MemoryFixture/CacheAccess/1048576/0/0/1 85440.6313100312 ns 85076.15703685701 ns 8221
+ #MemoryFixture/CacheAccess/2097152/0/0/1 170908.37391089948 ns 169402.58059051324 ns 4132
+ #MemoryFixture/CacheAccess/4194304/0/0/1 373635.4350000207 ns 372955.40777777723 ns 1800
+ #MemoryFixture/CacheAccess/8388608/0/0/1 685101.2127660838 ns 681594.2330754338 ns 1034
+ #MemoryFixture/CacheAccess/16777216/0/0/1 1588009.158696047 ns 1581510.0217391246 ns 460
+ #MemoryFixture/CacheAccess/33554432/0/0/1 2721626.5387591715 ns 2708149.166666674 ns 258
+ #MemoryFixture/CacheAccess/67108864/0/0/1 5433705.728680161 ns 5413515.914728661 ns 129
+ #MemoryFixture/CacheAccess/64/1/0/1 5.201213751848433 ns 5.180967321755995 ns 135673202
+ #MemoryFixture/CacheAccess/128/1/0/1 10.386209252693448 ns 10.351378045484042 ns 67486234
+ #MemoryFixture/CacheAccess/256/1/0/1 20.742666405371747 ns 20.686210353062208 ns 33848169
+ #MemoryFixture/CacheAccess/512/1/0/1 41.52781367071582 ns 41.4438085044977 ns 16870391
+ #MemoryFixture/CacheAccess/1024/1/0/1 83.03849985460687 ns 82.6732197351271 ns 8442915
+ #MemoryFixture/CacheAccess/2048/1/0/1 166.02706801365886 ns 165.60695561393828 ns 4226169
+ #MemoryFixture/CacheAccess/4096/1/0/1 332.05696890075365 ns 331.3395040136246 ns 2112679
+ #MemoryFixture/CacheAccess/8192/1/0/1 664.3009073119205 ns 662.5811781316487 ns 1055315
+ #MemoryFixture/CacheAccess/16384/1/0/1 1329.0792867154223 ns 1325.0185471435798 ns 527251
+ #MemoryFixture/CacheAccess/32768/1/0/1 2652.9089904482526 ns 2645.5388137876826 ns 264236
+ #MemoryFixture/CacheAccess/65536/1/0/1 5312.635002724743 ns 5300.412875575496 ns 132064
+ #MemoryFixture/CacheAccess/131072/1/0/1 10625.299202810635 ns 10594.376178351697 ns 65982
+ #MemoryFixture/CacheAccess/262144/1/0/1 21270.763359464152 ns 21206.192921372138 ns 33029
+ #MemoryFixture/CacheAccess/524288/1/0/1 42496.14168177758 ns 42381.692498487435 ns 16530
+ #MemoryFixture/CacheAccess/1048576/1/0/1 85425.34302253627 ns 85063.54206182965 ns 8119
+ #MemoryFixture/CacheAccess/2097152/1/0/1 170961.8011639407 ns 169732.18840931158 ns 4124
+ #MemoryFixture/CacheAccess/4194304/1/0/1 440086.77439029363 ns 439010.07195122127 ns 1640
+ #MemoryFixture/CacheAccess/8388608/1/0/1 677684.5246376056 ns 675888.058937202 ns 1035
+ #MemoryFixture/CacheAccess/16777216/1/0/1 1571417.6297115851 ns 1566423.4922394755 ns 451
+ #MemoryFixture/CacheAccess/33554432/1/0/1 2723418.325581582 ns 2708535.8062015465 ns 258
+ #MemoryFixture/CacheAccess/67108864/1/0/1 5435209.372094963 ns 5413991.821705426 ns 129
+ #MemoryFixture/CacheAccess/64/2/0/1 5.204700890931938 ns 5.183036658664568 ns 135406460
+ #MemoryFixture/CacheAccess/128/2/0/1 10.376355078178406 ns 10.348754235460566 ns 67518337
+ #MemoryFixture/CacheAccess/256/2/0/1 20.726238269323797 ns 20.670377070062745 ns 33834057
+ #MemoryFixture/CacheAccess/512/2/0/1 41.49336362336435 ns 41.38084547087122 ns 16890919
+ #MemoryFixture/CacheAccess/1024/2/0/1 82.96761236822086 ns 82.7676652782051 ns 8440753
+ #MemoryFixture/CacheAccess/2048/2/0/1 165.90277344671065 ns 165.63781837950896 ns 4223301
+ #MemoryFixture/CacheAccess/4096/2/0/1 332.08415463794364 ns 331.07455763248197 ns 2110971
+ #MemoryFixture/CacheAccess/8192/2/0/1 662.569068830069 ns 661.1656746088121 ns 1055382
+ #MemoryFixture/CacheAccess/16384/2/0/1 1327.7767031437843 ns 1324.268331214332 ns 528552
+ #MemoryFixture/CacheAccess/32768/2/0/1 2654.714983405558 ns 2647.9097623853727 ns 264546
+ #MemoryFixture/CacheAccess/65536/2/0/1 5304.774145979664 ns 5290.380748589911 ns 131554
+ #MemoryFixture/CacheAccess/131072/2/0/1 10631.0978039924 ns 10602.125724165107 ns 65938
+ #MemoryFixture/CacheAccess/262144/2/0/1 21258.936606489668 ns 21202.585867458216 ns 33016
+ #MemoryFixture/CacheAccess/524288/2/0/1 42460.85577331506 ns 42355.304775195626 ns 16481
+ #MemoryFixture/CacheAccess/1048576/2/0/1 85428.60153206348 ns 85160.29036964968 ns 8224
+ #MemoryFixture/CacheAccess/2097152/2/0/1 170233.91140170072 ns 169409.06511740564 ns 4131
+ #MemoryFixture/CacheAccess/4194304/2/0/1 402022.9022378908 ns 401018.78327444167 ns 1698
+ #MemoryFixture/CacheAccess/8388608/2/0/1 677677.2908216701 ns 675843.1642512042 ns 1035
+ #MemoryFixture/CacheAccess/16777216/2/0/1 1554294.1339100641 ns 1549490.831533465 ns 463
+ #MemoryFixture/CacheAccess/33554432/2/0/1 2722937.453488912 ns 2709007.093023249 ns 258
+ #MemoryFixture/CacheAccess/67108864/2/0/1 5435791.6511618495 ns 5415184.511627913 ns 129
+ #MemoryFixture/CacheAccess/64/0/2/1 5.198916380394579 ns 5.178607363536682 ns 135270162
+ #MemoryFixture/CacheAccess/128/0/2/1 10.39285189976819 ns 10.361873548918089 ns 67571996
+ #MemoryFixture/CacheAccess/256/0/2/1 20.75920269645178 ns 20.69937217558235 ns 33765810
+ #MemoryFixture/CacheAccess/512/0/2/1 41.51556112567147 ns 41.372342254073665 ns 16947585
+ #MemoryFixture/CacheAccess/1024/0/2/1 82.96516513710067 ns 82.78508396196703 ns 8459485
+ #MemoryFixture/CacheAccess/2048/0/2/1 166.19624228249646 ns 165.74873814180103 ns 4221552
+ #MemoryFixture/CacheAccess/4096/0/2/1 331.7269469760912 ns 330.91601941885546 ns 2111762
+ #MemoryFixture/CacheAccess/8192/0/2/1 663.8953077112178 ns 662.4540856828183 ns 1059419
+ #MemoryFixture/CacheAccess/16384/0/2/1 1326.843343898467 ns 1323.254749209487 ns 527193
+ #MemoryFixture/CacheAccess/32768/0/2/1 2656.6743123958327 ns 2651.2139933123217 ns 264069
+ #MemoryFixture/CacheAccess/65536/0/2/1 5316.515245822549 ns 5306.343742646622 ns 131741
+ #MemoryFixture/CacheAccess/131072/0/2/1 10623.00981164003 ns 10584.927048634307 ns 66044
+ #MemoryFixture/CacheAccess/262144/0/2/1 21210.760294289023 ns 21148.895028460767 ns 33028
+ #MemoryFixture/CacheAccess/524288/0/2/1 42522.49017237178 ns 42412.58560628969 ns 16535
+ #MemoryFixture/CacheAccess/1048576/0/2/1 86800.15632693251 ns 86501.64057114806 ns 8124
+ #MemoryFixture/CacheAccess/2097152/0/2/1 177705.58147680553 ns 177010.52665832458 ns 3995
+ #MemoryFixture/CacheAccess/4194304/0/2/1 449051.5944408481 ns 448237.065698044 ns 1583
+ #MemoryFixture/CacheAccess/8388608/0/2/1 1389931.2189924652 ns 1386035.8565891527 ns 516
+ #MemoryFixture/CacheAccess/16777216/0/2/1 4438020.074999826 ns 4420751.918750021 ns 160
+ #MemoryFixture/CacheAccess/33554432/0/2/1 1.730178560976084E7 ns 1.7182623121951293E7 ns 41
+ #MemoryFixture/CacheAccess/67108864/0/2/1 5.283456416664952E7 ns 5.258297450000053E7 ns 12
+ #MemoryFixture/CacheAccess/64/1/2/1 5.204121573005314 ns 5.179569988739665 ns 135600170
+ #MemoryFixture/CacheAccess/128/1/2/1 10.387460007442089 ns 10.354541036512236 ns 67512560
+ #MemoryFixture/CacheAccess/256/1/2/1 20.77893771735786 ns 20.727591539055314 ns 33750321
+ #MemoryFixture/CacheAccess/512/1/2/1 41.4739992379063 ns 41.315239742240664 ns 16908639
+ #MemoryFixture/CacheAccess/1024/1/2/1 82.95454097741914 ns 82.7976946763163 ns 8446970
+ #MemoryFixture/CacheAccess/2048/1/2/1 165.86154320354674 ns 165.43862697234525 ns 4233855
+ #MemoryFixture/CacheAccess/4096/1/2/1 331.8942415618145 ns 331.28362462222265 ns 2109704
+ #MemoryFixture/CacheAccess/8192/1/2/1 663.6968508366361 ns 662.640989545053 ns 1057011
+ #MemoryFixture/CacheAccess/16384/1/2/1 1328.002697434852 ns 1325.3893625606 ns 527909
+ #MemoryFixture/CacheAccess/32768/1/2/1 2656.826225607798 ns 2651.831997636693 ns 264032
+ #MemoryFixture/CacheAccess/65536/1/2/1 5313.403312198365 ns 5296.6562514184625 ns 132178
+ #MemoryFixture/CacheAccess/131072/1/2/1 10603.411688232678 ns 10580.430523642488 ns 66152
+ #MemoryFixture/CacheAccess/262144/1/2/1 21213.68814698657 ns 21160.64858647625 ns 33038
+ #MemoryFixture/CacheAccess/524288/1/2/1 42446.96972817497 ns 42358.49900102921 ns 16517
+ #MemoryFixture/CacheAccess/1048576/1/2/1 85427.89922199522 ns 85099.99477267203 ns 8226
+ #MemoryFixture/CacheAccess/2097152/1/2/1 179576.28781830988 ns 178747.97179230847 ns 4006
+ #MemoryFixture/CacheAccess/4194304/1/2/1 453971.4271099782 ns 453200.38874680526 ns 1564
+ #MemoryFixture/CacheAccess/8388608/1/2/1 1413810.749999729 ns 1409767.6830708506 ns 508
+ #MemoryFixture/CacheAccess/16777216/1/2/1 4481396.176099637 ns 4463691.635220161 ns 159
+ #MemoryFixture/CacheAccess/33554432/1/2/1 1.7363190725006916E7 ns 1.7271956449999947E7 ns 40
+ #MemoryFixture/CacheAccess/67108864/1/2/1 5.310257300000861E7 ns 5.283166808333325E7 ns 12
+ #MemoryFixture/CacheAccess/64/2/2/1 5.194585073441566 ns 5.169936491706671 ns 135797225
+ #MemoryFixture/CacheAccess/128/2/2/1 10.375776978615239 ns 10.351150907177248 ns 67504271
+ #MemoryFixture/CacheAccess/256/2/2/1 20.73537619800892 ns 20.682392672592464 ns 33819437
+ #MemoryFixture/CacheAccess/512/2/2/1 41.46680809632523 ns 41.35825233901641 ns 16913944
+ #MemoryFixture/CacheAccess/1024/2/2/1 82.84606240770246 ns 82.6134204462559 ns 8446202
+ #MemoryFixture/CacheAccess/2048/2/2/1 165.87278324509214 ns 165.32429617950757 ns 4232933
+ #MemoryFixture/CacheAccess/4096/2/2/1 331.2406082982817 ns 330.5629607515063 ns 2116922
+ #MemoryFixture/CacheAccess/8192/2/2/1 663.159315900038 ns 661.6959690484747 ns 1056103
+ #MemoryFixture/CacheAccess/16384/2/2/1 1327.5666883524236 ns 1324.3426747207684 ns 528758
+ #MemoryFixture/CacheAccess/32768/2/2/1 2654.9809699966722 ns 2648.132907418347 ns 264372
+ #MemoryFixture/CacheAccess/65536/2/2/1 5314.47981229803 ns 5303.806613499892 ns 131912
+ #MemoryFixture/CacheAccess/131072/2/2/1 10606.19082560071 ns 10585.181869071148 ns 66097
+ #MemoryFixture/CacheAccess/262144/2/2/1 21187.819721722273 ns 21154.040502117125 ns 33060
+ #MemoryFixture/CacheAccess/524288/2/2/1 42442.62465239758 ns 42311.67198645875 ns 16542
+ #MemoryFixture/CacheAccess/1048576/2/2/1 85539.82432104382 ns 85200.15385547924 ns 8248
+ #MemoryFixture/CacheAccess/2097152/2/2/1 180928.070870083 ns 180122.69382093282 ns 3965
+ #MemoryFixture/CacheAccess/4194304/2/2/1 456790.68648981495 ns 455950.1693600544 ns 1547
+ #MemoryFixture/CacheAccess/8388608/2/2/1 1427351.7287124782 ns 1423232.2613861358 ns 505
+ #MemoryFixture/CacheAccess/16777216/2/2/1 4513772.829113805 ns 4495839.088607608 ns 158
+ #MemoryFixture/CacheAccess/33554432/2/2/1 1.7454686475002743E7 ns 1.7364546800000016E7 ns 40
+ #MemoryFixture/CacheAccess/67108864/2/2/1 5.2963768833327174E7 ns 5.266439433333403E7 ns 12
+
+ */
float result = 0;
using android::media::psh_utils::CoreClass;
diff --git a/media/psh_utils/benchmarks/audio_powerstatscollector_benchmark.cpp b/media/psh_utils/benchmarks/audio_powerstatscollector_benchmark.cpp
index 9e581bc..021eb5a 100644
--- a/media/psh_utils/benchmarks/audio_powerstatscollector_benchmark.cpp
+++ b/media/psh_utils/benchmarks/audio_powerstatscollector_benchmark.cpp
@@ -22,16 +22,17 @@
#include <benchmark/benchmark.h>
/*
- Pixel 8 Pro
+ Pixel 9 Pro XL
+ (tolerance is the amount of time a cached value is valid).
------------------------------------------------------------------------------------------
Benchmark Time CPU Iteration
------------------------------------------------------------------------------------------
audio_powerstatscollector_benchmark:
- #BM_StatsToleranceMs/0 1.2005660120994434E8 ns 2532739.72 ns 100
- #BM_StatsToleranceMs/50 1281.095987079007 ns 346.0322183913503 ns 2022168
- #BM_StatsToleranceMs/100 459.9668862534226 ns 189.47902626735942 ns 2891307
- #BM_StatsToleranceMs/200 233.8438662484292 ns 149.84041813854736 ns 4407343
- #BM_StatsToleranceMs/500 184.42197142314103 ns 144.86896036787098 ns 7295167
+ #BM_StatsToleranceMs/0 6.346578290999787E7 ns 2069264.56 ns 100
+ #BM_StatsToleranceMs/50 454.12461256065177 ns 203.1644161064639 ns 2615571
+ #BM_StatsToleranceMs/100 167.74983887731364 ns 101.99598388920647 ns 5436852
+ #BM_StatsToleranceMs/200 102.57950838168422 ns 79.40969988086803 ns 7600815
+ #BM_StatsToleranceMs/500 86.87348495571898 ns 75.24841434306252 ns 9789318
*/
// We check how expensive it is to query stats depending
diff --git a/media/psh_utils/benchmarks/audio_token_benchmark.cpp b/media/psh_utils/benchmarks/audio_token_benchmark.cpp
new file mode 100644
index 0000000..47003c0
--- /dev/null
+++ b/media/psh_utils/benchmarks/audio_token_benchmark.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2024 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 "audio_token_benchmark"
+#include <utils/Log.h>
+
+#include <psh_utils/Token.h>
+
+#include <benchmark/benchmark.h>
+
+/*
+ Pixel 9 Pro XL
+------------------------------------------------------------------------------------------
+ Benchmark Time CPU Iteration
+------------------------------------------------------------------------------------------
+audio_token_benchmark:
+ #BM_ClientToken 494.6548907301575 ns 492.4932166101717 ns 1376819
+ #BM_ThreadToken 140.34316175293938 ns 139.91778452790845 ns 5000397
+ #BM_TrackToken 944.0571625384163 ns 893.7912613357879 ns 643096
+*/
+
+static void BM_ClientToken(benchmark::State& state) {
+ constexpr pid_t kPid = 10;
+ constexpr uid_t kUid = 100;
+ while (state.KeepRunning()) {
+ auto token = android::media::psh_utils::createAudioClientToken(
+ kPid, kUid);
+ benchmark::ClobberMemory();
+ }
+}
+
+BENCHMARK(BM_ClientToken);
+
+static void BM_ThreadToken(benchmark::State& state) {
+ constexpr pid_t kTid = 20;
+ constexpr const char* kWakeLockTag = "thread";
+ while (state.KeepRunning()) {
+ auto token = android::media::psh_utils::createAudioThreadToken(
+ kTid, kWakeLockTag);
+ benchmark::ClobberMemory();
+ }
+}
+
+BENCHMARK(BM_ThreadToken);
+
+static void BM_TrackToken(benchmark::State& state) {
+ constexpr pid_t kPid = 10;
+ constexpr uid_t kUid = 100;
+ auto clientToken = android::media::psh_utils::createAudioClientToken(
+ kPid, kUid);
+ while (state.KeepRunning()) {
+ auto token = android::media::psh_utils::createAudioTrackToken(kUid);
+ benchmark::ClobberMemory();
+ }
+}
+
+BENCHMARK(BM_TrackToken);
+
+BENCHMARK_MAIN();
diff --git a/media/psh_utils/include/psh_utils/AudioPowerManager.h b/media/psh_utils/include/psh_utils/AudioPowerManager.h
new file mode 100644
index 0000000..47dfdb2
--- /dev/null
+++ b/media/psh_utils/include/psh_utils/AudioPowerManager.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2024 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 "PowerClientStats.h"
+#include "PowerStatsCollector.h"
+#include "Token.h"
+
+#include <android-base/thread_annotations.h>
+#include <audio_utils/linked_hash_map.h>
+#include <list>
+#include <map>
+#include <unordered_map>
+#include <unordered_set>
+
+namespace android::media::psh_utils {
+
+/**
+ * AudioPowerManager is a singleton class that
+ * serializes the power, wakelock, and performance
+ * messages
+ */
+class AudioPowerManager {
+ friend class AudioClientToken;
+ friend class AudioThreadToken;
+ friend class AudioTrackToken;
+
+public:
+ static AudioPowerManager& getAudioPowerManager();
+
+ /**
+ * Returns a token indicating that a client is started.
+ * This is associated with an application.
+ */
+ std::unique_ptr<Token> startClient(pid_t pid, uid_t uid,
+ const std::string& additional);
+
+ /**
+ * Returns a token that represents a start instance for uid.
+ * This is typically associated with an AudioTrack / AudioRecord start.
+ */
+ std::unique_ptr<Token> startTrack(uid_t uid, const std::string& additional);
+
+ /**
+ * Returns a token that represents a wakelock for a Thread start.
+ */
+ std::unique_ptr<Token> startThread(
+ pid_t pid, const std::string& wakeLockName,
+ WakeFlag wakeFlag, const std::string& additional);
+
+ std::string toString() const;
+
+ static bool enabled();
+
+private:
+ // For AudioToken dtor only.
+ void clear_token_ptr(Token* token);
+ void stopClient(pid_t pid);
+
+ static constexpr size_t kHistory = 6;
+
+ mutable std::mutex mMutex;
+ std::unordered_set<Token *> mOutstandingTokens GUARDED_BY(mMutex);
+ std::unordered_map<pid_t, uid_t> mPidToUid GUARDED_BY(mMutex);
+ std::map<uid_t, std::shared_ptr<PowerClientStats>> mPowerClientStats GUARDED_BY(mMutex);
+ audio_utils::linked_hash_map<uid_t, std::shared_ptr<PowerClientStats>>
+ mHistoricalClients GUARDED_BY(mMutex);
+};
+
+} // namespace android::media::psh_utils
diff --git a/media/psh_utils/include/psh_utils/PowerClientStats.h b/media/psh_utils/include/psh_utils/PowerClientStats.h
new file mode 100644
index 0000000..6e27e41
--- /dev/null
+++ b/media/psh_utils/include/psh_utils/PowerClientStats.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2024 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 "PowerStats.h"
+#include "PowerStatsCollector.h"
+
+#include <android-base/thread_annotations.h>
+#include <audio_utils/CommandThread.h>
+#include <memory>
+#include <set>
+
+namespace android::media::psh_utils {
+
+/**
+ * PowerClientStats accumulates power measurements based on start and stop events.
+ *
+ * The start and stop events must eventually be matched, but several start events
+ * in a row only results in the power counted once.
+ */
+class PowerClientStats {
+public:
+ // A command thread is used for tokens to dispatch start and stop sequentially
+ // with less overhead to the caller.
+ static audio_utils::CommandThread& getCommandThread();
+
+ /**
+ * Creates an UID based power stat tracker.
+ *
+ * @param uid uid of app
+ * @param additional string to be printed out.
+ */
+ PowerClientStats(uid_t uid, const std::string& additional);
+
+ /**
+ * Starts power tracking.
+ */
+ void start(int64_t actualNs) EXCLUDES(mMutex);
+
+ /**
+ * Stops power tracking (saves the difference) - must be paired with start().
+ */
+ void stop(int64_t actualNs) EXCLUDES(mMutex);
+
+ /**
+ * Adds a pid to the App for string printing.
+ */
+ void addPid(pid_t pid) EXCLUDES(mMutex);
+
+ /**
+ * Removes the pid from the App for string printing.
+ */
+ size_t removePid(pid_t pid) EXCLUDES(mMutex);
+
+ /**
+ * Returns the string info.
+ * @param stats if true returns the stats.
+ * @return stat string.
+ */
+ std::string toString(bool stats = false, const std::string& prefix = {})
+ const EXCLUDES(mMutex);
+
+private:
+ // Snapshots are taken no more often than 500ms.
+ static constexpr int64_t kStatTimeToleranceNs = 500'000'000;
+
+ mutable std::mutex mMutex;
+ const uid_t mUid;
+ const std::string mName;
+ const std::string mAdditional;
+ std::set<pid_t> mPids GUARDED_BY(mMutex); // pids sharing same uid
+ int64_t mTokenCount GUARDED_BY(mMutex) = 0;
+ int64_t mStartNs GUARDED_BY(mMutex) = 0;
+ std::shared_ptr<const PowerStats> mStartStats GUARDED_BY(mMutex);
+
+ // Cumulative time while active: sum of deltas of (stop - start).
+ int64_t mCumulativeNs GUARDED_BY(mMutex) = 0;
+ // Cumulative stats while active: sum of deltas of (stop - start),
+ // where snapshots are quantized to ~500ms accuracy.
+ std::shared_ptr<PowerStats> mCumulativeStats GUARDED_BY(mMutex) =
+ std::make_shared<PowerStats>();
+};
+
+} // namespace android::media::psh_utils
diff --git a/media/psh_utils/include/psh_utils/Token.h b/media/psh_utils/include/psh_utils/Token.h
new file mode 100644
index 0000000..2b52d11
--- /dev/null
+++ b/media/psh_utils/include/psh_utils/Token.h
@@ -0,0 +1,62 @@
+
+/*
+ * Copyright (C) 2024 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 <string>
+
+namespace android::media::psh_utils {
+
+class Token {
+public:
+ virtual ~Token() = default;
+ virtual std::string toString() const = 0;
+};
+
+// Client tokens (one per Audio Client PID)
+std::unique_ptr<Token> createAudioClientToken(pid_t pid, uid_t uid,
+ const std::string& additional = {});
+
+enum class WakeFlag {
+ kNone = 0,
+ kLowLatency = 1,
+ kLowPower = 2,
+};
+
+inline std::string toString(WakeFlag wakeFlag) {
+ std::string result;
+ for (const auto& [flag, name] : std::initializer_list<std::pair<WakeFlag, std::string>> {
+ {WakeFlag::kLowLatency, "kLowLatency"},
+ {WakeFlag::kLowPower, "kLowPower"},
+ }) {
+ if (static_cast<int>(flag) & static_cast<int>(wakeFlag)) {
+ if (!result.empty()) result.append("|");
+ result.append(name);
+ }
+ }
+ return result;
+}
+
+// Thread tokens (one per ThreadBase PID started).
+std::unique_ptr<Token> createAudioThreadToken(
+ pid_t pid, const std::string& wakeLockName,
+ WakeFlag wakeFlag = WakeFlag::kNone, const std::string& additional = {});
+
+// AudioTrack/AudioRecord tokens.
+std::unique_ptr<Token> createAudioTrackToken(uid_t uid, const std::string& additional = {});
+
+} // namespace android::media::psh_utils
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 0315ac9..e13f8f7 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -41,6 +41,10 @@
namespace android {
+namespace {
+constexpr auto PERMISSION_HARD_DENIED = permission::PermissionChecker::PERMISSION_HARD_DENIED;
+}
+
using content::AttributionSourceState;
static const String16 sAndroidPermissionRecordAudio("android.permission.RECORD_AUDIO");
@@ -115,7 +119,7 @@
return std::optional<AttributionSourceState>{myAttributionSource};
}
- static bool checkRecordingInternal(const AttributionSourceState &attributionSource,
+ static int checkRecordingInternal(const AttributionSourceState &attributionSource,
const uint32_t virtualDeviceId,
const String16 &msg, bool start, audio_source_t source) {
// Okay to not track in app ops as audio server or media server is us and if
@@ -138,15 +142,15 @@
const int32_t attributedOpCode = getOpForSource(source);
permission::PermissionChecker permissionChecker;
- bool permitted = false;
+ int permitted;
if (start) {
- permitted = (permissionChecker.checkPermissionForStartDataDeliveryFromDatasource(
+ permitted = permissionChecker.checkPermissionForStartDataDeliveryFromDatasource(
sAndroidPermissionRecordAudio, resolvedAttributionSource.value(), msg,
- attributedOpCode) != permission::PermissionChecker::PERMISSION_HARD_DENIED);
+ attributedOpCode);
} else {
- permitted = (permissionChecker.checkPermissionForPreflightFromDatasource(
+ permitted = permissionChecker.checkPermissionForPreflightFromDatasource(
sAndroidPermissionRecordAudio, resolvedAttributionSource.value(), msg,
- attributedOpCode) != permission::PermissionChecker::PERMISSION_HARD_DENIED);
+ attributedOpCode);
}
return permitted;
@@ -156,17 +160,17 @@
bool recordingAllowed(const AttributionSourceState &attributionSource, audio_source_t source) {
return checkRecordingInternal(attributionSource, DEVICE_ID_DEFAULT, String16(), /*start*/ false,
- source);
+ source) != PERMISSION_HARD_DENIED;
}
bool recordingAllowed(const AttributionSourceState &attributionSource,
const uint32_t virtualDeviceId,
audio_source_t source) {
return checkRecordingInternal(attributionSource, virtualDeviceId,
- String16(), /*start*/ false, source);
+ String16(), /*start*/ false, source) != PERMISSION_HARD_DENIED;
}
-bool startRecording(const AttributionSourceState& attributionSource,
+int startRecording(const AttributionSourceState& attributionSource,
const uint32_t virtualDeviceId,
const String16& msg,
audio_source_t source) {
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index b365648..2631469 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -92,7 +92,7 @@
bool recordingAllowed(const AttributionSourceState &attributionSource,
uint32_t virtualDeviceId,
audio_source_t source);
-bool startRecording(const AttributionSourceState& attributionSource, uint32_t virtualDeviceId,
+int startRecording(const AttributionSourceState& attributionSource, uint32_t virtualDeviceId,
const String16& msg, audio_source_t source);
void finishRecording(const AttributionSourceState& attributionSource, uint32_t virtualDeviceId,
audio_source_t source);
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index 264fc4f..01bde42 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -234,6 +234,22 @@
"libpermission",
],
+ export_static_lib_headers: [
+ "libpshutils",
+ ],
+
+ shared: {
+ static_libs: [
+ "libpshutils",
+ ],
+ },
+
+ static: {
+ whole_static_libs: [
+ "libpshutils",
+ ],
+ },
+
cflags: [
"-Wall",
"-Werror",
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index d94862a..0034027 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -17,6 +17,8 @@
#define LOG_TAG "AudioFlinger"
//#define LOG_NDEBUG 0
+#define ATRACE_TAG ATRACE_TAG_AUDIO
+#include <utils/Trace.h>
// Define AUDIO_ARRAYS_STATIC_CHECK to check all audio arrays are correct
#define AUDIO_ARRAYS_STATIC_CHECK 1
@@ -899,6 +901,17 @@
BUFLOG_RESET;
+ if (media::psh_utils::AudioPowerManager::enabled()) {
+ char value[PROPERTY_VALUE_MAX];
+ property_get("ro.build.display.id", value, "Unknown build");
+ std::string build(value);
+ build.append("\n");
+ write(fd, build.c_str(), build.size());
+ const std::string powerLog =
+ media::psh_utils::AudioPowerManager::getAudioPowerManager().toString();
+ write(fd, powerLog.c_str(), powerLog.size());
+ }
+
if (locked) {
mutex().unlock();
}
@@ -1054,6 +1067,7 @@
status_t AudioFlinger::createTrack(const media::CreateTrackRequest& _input,
media::CreateTrackResponse& _output)
{
+ ATRACE_CALL();
// Local version of VALUE_OR_RETURN, specific to this method's calling conventions.
CreateTrackInput input = VALUE_OR_RETURN_STATUS(CreateTrackInput::fromAidl(_input));
CreateTrackOutput output;
@@ -2327,6 +2341,9 @@
pid_t pid,
uid_t uid)
: mAudioFlinger(audioFlinger), mPid(pid), mUid(uid), mAudioFlingerClient(client)
+ , mClientToken(media::psh_utils::AudioPowerManager::enabled()
+ ? media::psh_utils::createAudioClientToken(pid, uid)
+ : nullptr)
{
}
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 7c58c96..ba2b920 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -38,6 +38,7 @@
#include <media/audiohal/DevicesFactoryHalInterface.h>
#include <mediautils/ServiceUtilities.h>
#include <mediautils/Synchronization.h>
+#include <psh_utils/AudioPowerManager.h>
// not needed with the includes above, added to prevent transitive include dependency.
#include <utils/KeyedVector.h>
@@ -499,6 +500,7 @@
const pid_t mPid;
const uid_t mUid;
const sp<media::IAudioFlingerClient> mAudioFlingerClient;
+ const std::unique_ptr<media::psh_utils::Token> mClientToken;
};
// --- MediaLogNotifier ---
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 406b832..3f0bd70 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -81,6 +81,7 @@
#include <powermanager/PowerManager.h>
#include <private/android_filesystem_config.h>
#include <private/media/AudioTrackShared.h>
+#include <psh_utils/AudioPowerManager.h>
#include <system/audio_effects/effect_aec.h>
#include <system/audio_effects/effect_downmix.h>
#include <system/audio_effects/effect_ns.h>
@@ -1218,6 +1219,10 @@
{} /* historyTag */);
if (status.isOk()) {
mWakeLockToken = binder;
+ if (media::psh_utils::AudioPowerManager::enabled()) {
+ mThreadToken = media::psh_utils::createAudioThreadToken(
+ getTid(), String8(getWakeLockTag()).c_str());
+ }
}
ALOGV("acquireWakeLock_l() %s status %d", mThreadName, status.exceptionCode());
}
@@ -1243,6 +1248,7 @@
}
mWakeLockToken.clear();
}
+ mThreadToken.reset();
}
void ThreadBase::getPowerManager_l() {
@@ -4059,7 +4065,13 @@
// FIXME could this be made local to while loop?
writeFrames = 0;
- cacheParameters_l();
+ {
+ audio_utils::lock_guard l(mutex());
+
+ cacheParameters_l();
+ checkSilentMode_l();
+ }
+
mSleepTimeUs = mIdleSleepTimeUs;
if (mType == MIXER || mType == SPATIALIZER) {
@@ -4084,8 +4096,6 @@
// suspended mode (for now) to help schedule the wait time until next iteration.
nsecs_t timeLoopNextNs = 0;
- checkSilentMode_l();
-
audio_patch_handle_t lastDownstreamPatchHandle = AUDIO_PATCH_HANDLE_NONE;
sendCheckOutputStageEffectsEvent();
@@ -11603,6 +11613,7 @@
void BitPerfectThread::setTracksInternalMute(
std::map<audio_port_handle_t, bool>* tracksInternalMute) {
+ audio_utils::lock_guard _l(mutex());
for (auto& track : mTracks) {
if (auto it = tracksInternalMute->find(track->portId()); it != tracksInternalMute->end()) {
track->setInternalMute(it->second);
@@ -11619,6 +11630,11 @@
// Return the bit perfect track if all other tracks are muted
for (const auto& track : mActiveTracks) {
if (track->isBitPerfect()) {
+ if (track->getInternalMute()) {
+ // There can only be one bit-perfect client active. If it is mute internally,
+ // there is no need to stream bit-perfectly.
+ break;
+ }
bitPerfectTrack = track;
} else if (track->getFinalVolume() != 0.f) {
allOtherTracksMuted = false;
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index a7a2630..4c4939b 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -33,6 +33,7 @@
#include <fastpath/FastMixer.h>
#include <mediautils/Synchronization.h>
#include <mediautils/ThreadSnapshot.h>
+#include <psh_utils/Token.h>
#include <timing/MonotonicFrameCounter.h>
#include <utils/Log.h>
@@ -725,6 +726,7 @@
char mThreadName[kThreadNameLength]; // guaranteed NUL-terminated
sp<os::IPowerManager> mPowerManager GUARDED_BY(mutex());
sp<IBinder> mWakeLockToken GUARDED_BY(mutex());
+ std::unique_ptr<media::psh_utils::Token> mThreadToken GUARDED_BY(mutex());
const sp<PMDeathRecipient> mDeathRecipient;
// list of suspended effects per session and per type. The first (outer) vector is
// keyed by session ID, the second (inner) by type UUID timeLow field
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index 1342b7b..cde7fc2 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -24,6 +24,7 @@
#include <android-base/macros.h> // DISALLOW_COPY_AND_ASSIGN
#include <datapath/TrackMetrics.h>
#include <mediautils/BatteryNotifier.h>
+#include <psh_utils/AudioPowerManager.h>
#include <atomic> // avoid transitive dependency
#include <list> // avoid transitive dependency
@@ -240,17 +241,13 @@
* Called when a track moves to active state to record its contribution to battery usage.
* Track state transitions should eventually be handled within the track class.
*/
- void beginBatteryAttribution() final {
- mBatteryStatsHolder.emplace(uid());
- }
+ void beginBatteryAttribution() final;
/**
* Called when a track moves out of the active state to record its contribution
* to battery usage.
*/
- void endBatteryAttribution() final {
- mBatteryStatsHolder.reset();
- }
+ void endBatteryAttribution() final;
protected:
DISALLOW_COPY_AND_ASSIGN(TrackBase);
@@ -400,6 +397,7 @@
std::atomic_flag mChangeNotified = ATOMIC_FLAG_INIT;
// RAII object for battery stats book-keeping
std::optional<mediautils::BatteryStatsAudioHandle> mBatteryStatsHolder;
+ std::unique_ptr<media::psh_utils::Token> mTrackToken;
};
class PatchTrackBase : public PatchProxyBufferProvider, public virtual IAfPatchTrackBase
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 5aa58a2..a692773 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -318,13 +318,25 @@
{
const auto thread = mThread.promote();
if (thread == nullptr) return;
- thread->getThreadloopExecutor().defer(
- [track = wp<TrackBase>::fromExisting(this)] {
- const auto actual = track.promote();
+ auto weakTrack = wp<TrackBase>::fromExisting(this);
+ thread->getThreadloopExecutor().defer([weakTrack] {
+ const auto actual = weakTrack.promote();
if (actual) actual->restartIfDisabled();
});
}
+void TrackBase::beginBatteryAttribution() {
+ mBatteryStatsHolder.emplace(uid());
+ if (media::psh_utils::AudioPowerManager::enabled()) {
+ mTrackToken = media::psh_utils::createAudioTrackToken(uid());
+ }
+}
+
+void TrackBase::endBatteryAttribution() {
+ mBatteryStatsHolder.reset();
+ mTrackToken.reset();
+}
+
PatchTrackBase::PatchTrackBase(const sp<ClientProxy>& proxy,
IAfThreadBase* thread, const Timeout& timeout)
: mProxy(proxy)
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 796e3c7..574307a 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -2379,8 +2379,8 @@
// the bit-perfect sink so that it is guaranteed only bit-perfect stream is active.
PortHandleVector clientsToInvalidate;
for (size_t i = 0; i < mOutputs.size(); i++) {
- if (mOutputs[i] == outputDesc ||
- mOutputs[i]->devices().filter(outputDesc->devices()).isEmpty()) {
+ if (mOutputs[i] == outputDesc || (!mOutputs[i]->devices().isEmpty() &&
+ mOutputs[i]->devices().filter(outputDesc->devices()).isEmpty())) {
continue;
}
for (const auto& c : mOutputs[i]->getClientIterable()) {
@@ -9068,6 +9068,13 @@
status_t AudioPolicyManager::getDevicesForAttributes(
const audio_attributes_t &attr, DeviceVector &devices, bool forVolume) {
+ // attr containing source set by AudioAttributes.Builder.setCapturePreset() has precedence
+ // over any usage or content type also present in attr.
+ if (com::android::media::audioserver::enable_audio_input_device_routing() &&
+ attr.source != AUDIO_SOURCE_INVALID) {
+ return getInputDevicesForAttributes(attr, devices);
+ }
+
// Devices are determined in the following precedence:
//
// 1) Devices associated with a dynamic policy matching the attributes. This is often
@@ -9131,6 +9138,15 @@
return NO_ERROR;
}
+status_t AudioPolicyManager::getInputDevicesForAttributes(
+ const audio_attributes_t &attr, DeviceVector &devices) {
+ devices = DeviceVector(
+ mEngine->getInputDeviceForAttributes(attr, 0 /*uid unknown here*/,
+ AUDIO_SESSION_NONE,
+ nullptr /* mix */));
+ return NO_ERROR;
+}
+
status_t AudioPolicyManager::getProfilesForDevices(const DeviceVector& devices,
AudioProfileVector& audioProfiles,
uint32_t flags,
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 4736980..84edf34 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -1366,6 +1366,11 @@
DeviceVector &devices,
bool forVolume);
+ // A helper method used by getDevicesForAttributes to retrieve input devices when
+ // capture preset is available in the given audio attributes parameter.
+ status_t getInputDevicesForAttributes(const audio_attributes_t &attr,
+ DeviceVector &devices);
+
status_t getProfilesForDevices(const DeviceVector& devices,
AudioProfileVector& audioProfiles,
uint32_t flags,
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 2f7d722..24ab6a1 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -88,6 +88,10 @@
using media::audio::common::Int;
constexpr int kDefaultVirtualDeviceId = 0;
+namespace {
+constexpr auto PERMISSION_HARD_DENIED = permission::PermissionChecker::PERMISSION_HARD_DENIED;
+constexpr auto PERMISSION_GRANTED = permission::PermissionChecker::PERMISSION_GRANTED;
+}
const std::vector<audio_usage_t>& SYSTEM_USAGES = {
AUDIO_USAGE_CALL_ASSISTANT,
@@ -902,13 +906,13 @@
std::stringstream msg;
msg << "Audio recording on session " << client->session;
+ const auto permitted = startRecording(client->attributionSource, client->virtualDeviceId,
+ String16(msg.str().c_str()), client->attributes.source);
// check calling permissions
- if (!(startRecording(client->attributionSource, client->virtualDeviceId,
- String16(msg.str().c_str()), client->attributes.source)
- || client->attributes.source == AUDIO_SOURCE_FM_TUNER
- || client->attributes.source == AUDIO_SOURCE_REMOTE_SUBMIX
- || client->attributes.source == AUDIO_SOURCE_ECHO_REFERENCE)) {
+ if (permitted == PERMISSION_HARD_DENIED && client->attributes.source != AUDIO_SOURCE_FM_TUNER
+ && client->attributes.source != AUDIO_SOURCE_REMOTE_SUBMIX
+ && client->attributes.source != AUDIO_SOURCE_ECHO_REFERENCE) {
ALOGE("%s permission denied: recording not allowed for attribution source %s",
__func__, client->attributionSource.toString().c_str());
return binderStatusFromStatusT(PERMISSION_DENIED);
@@ -928,13 +932,17 @@
return binderStatusFromStatusT(INVALID_OPERATION);
}
- // Force the possibly silenced client to be unsilenced since we just called
- // startRecording (i.e. we have assumed it is unsilenced).
- // At this point in time, the client is inactive, so no calls to appops are sent in
- // setAppState_l.
- // This ensures existing clients have the same behavior as new clients (starting unsilenced).
+ // Force the possibly silenced client to match the state on the appops side
+ // following the call to startRecording (i.e. unsilenced iff call succeeded)
+ // At this point in time, the client is inactive, so no calls to appops are
+ // sent in setAppState_l. This ensures existing clients have the same
+ // behavior as new clients.
// TODO(b/282076713)
- setAppState_l(client, APP_STATE_TOP);
+ if (permitted == PERMISSION_GRANTED) {
+ setAppState_l(client, APP_STATE_TOP);
+ } else {
+ setAppState_l(client, APP_STATE_IDLE);
+ }
client->active = true;
client->startTimeNs = systemTime();
@@ -1020,8 +1028,10 @@
client->active = false;
client->startTimeNs = 0;
updateUidStates_l();
- finishRecording(client->attributionSource, client->virtualDeviceId,
- client->attributes.source);
+ if (!client->silenced) {
+ finishRecording(client->attributionSource, client->virtualDeviceId,
+ client->attributes.source);
+ }
}
return binderStatusFromStatusT(status);
@@ -1050,7 +1060,11 @@
updateUidStates_l();
// finish the recording app op
- finishRecording(client->attributionSource, client->virtualDeviceId, client->attributes.source);
+ if (!client->silenced) {
+ finishRecording(client->attributionSource, client->virtualDeviceId,
+ client->attributes.source);
+ }
+
AutoCallerClear acc;
return binderStatusFromStatusT(mAudioPolicyManager->stopInput(portId));
}
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 74cfdbe..4a839f8 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -61,6 +61,10 @@
static const String16 sManageAudioPolicyPermission("android.permission.MANAGE_AUDIO_POLICY");
+namespace {
+constexpr auto PERMISSION_GRANTED = permission::PermissionChecker::PERMISSION_GRANTED;
+}
+
// Creates an association between Binder code to name for IAudioPolicyService.
#define IAUDIOPOLICYSERVICE_BINDER_METHOD_MACRO_LIST \
BINDER_METHOD_ENTRY(onNewAudioModulesAvailable) \
@@ -1216,9 +1220,10 @@
} else {
std::stringstream msg;
msg << "Audio recording un-silenced on session " << client->session;
- if (!startRecording(client->attributionSource, client->virtualDeviceId,
- String16(msg.str().c_str()), client->attributes.source)) {
- silenced = true;
+ if (startRecording(client->attributionSource, client->virtualDeviceId,
+ String16(msg.str().c_str()), client->attributes.source)
+ != PERMISSION_GRANTED) {
+ return;
}
}
}
diff --git a/services/camera/libcameraservice/aidl/ExtensionMetadataTags.h b/services/camera/libcameraservice/aidl/ExtensionMetadataTags.h
index 86af36c..61b150d 100644
--- a/services/camera/libcameraservice/aidl/ExtensionMetadataTags.h
+++ b/services/camera/libcameraservice/aidl/ExtensionMetadataTags.h
@@ -30,13 +30,4 @@
std::vector<camera_metadata_tag> extension_metadata_keys{
ANDROID_EXTENSION_STRENGTH,
ANDROID_EXTENSION_CURRENT_TYPE,
- ANDROID_EFV_PADDING_ZOOM_FACTOR,
- ANDROID_EFV_AUTO_ZOOM,
- ANDROID_EFV_MAX_PADDING_ZOOM_FACTOR,
- ANDROID_EFV_STABILIZATION_MODE,
- ANDROID_EFV_TRANSLATE_VIEWPORT,
- ANDROID_EFV_ROTATE_VIEWPORT,
- ANDROID_EFV_PADDING_REGION,
- ANDROID_EFV_AUTO_ZOOM_PADDING_REGION,
- ANDROID_EFV_TARGET_COORDINATES,
};
diff --git a/services/camera/libcameraservice/aidl/VndkVersionMetadataTags.h b/services/camera/libcameraservice/aidl/VndkVersionMetadataTags.h
index 0e1db5c..b07d8d5 100644
--- a/services/camera/libcameraservice/aidl/VndkVersionMetadataTags.h
+++ b/services/camera/libcameraservice/aidl/VndkVersionMetadataTags.h
@@ -87,7 +87,6 @@
} },
{35, {
ANDROID_CONTROL_LOW_LIGHT_BOOST_INFO_LUMINANCE_RANGE,
- ANDROID_EFV_PADDING_ZOOM_FACTOR_RANGE,
ANDROID_FLASH_SINGLE_STRENGTH_DEFAULT_LEVEL,
ANDROID_FLASH_SINGLE_STRENGTH_MAX_LEVEL,
ANDROID_FLASH_TORCH_STRENGTH_DEFAULT_LEVEL,
@@ -121,15 +120,6 @@
} },
{35, {
ANDROID_CONTROL_LOW_LIGHT_BOOST_STATE,
- ANDROID_EFV_AUTO_ZOOM,
- ANDROID_EFV_AUTO_ZOOM_PADDING_REGION,
- ANDROID_EFV_MAX_PADDING_ZOOM_FACTOR,
- ANDROID_EFV_PADDING_REGION,
- ANDROID_EFV_PADDING_ZOOM_FACTOR,
- ANDROID_EFV_ROTATE_VIEWPORT,
- ANDROID_EFV_STABILIZATION_MODE,
- ANDROID_EFV_TARGET_COORDINATES,
- ANDROID_EFV_TRANSLATE_VIEWPORT,
ANDROID_FLASH_STRENGTH_LEVEL,
ANDROID_LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_SENSOR_CROP_REGION,
ANDROID_STATISTICS_LENS_INTRINSIC_SAMPLES,
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index db39b39..51f06cb 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -467,10 +467,6 @@
status_t CameraProviderManager::getSessionCharacteristics(
const std::string& id, const SessionConfiguration& configuration, bool overrideForPerfClass,
int rotationOverride, CameraMetadata* sessionCharacteristics /*out*/) const {
- if (!flags::feature_combination_query()) {
- return INVALID_OPERATION;
- }
-
std::lock_guard<std::mutex> lock(mInterfaceMutex);
auto deviceInfo = findDeviceInfoLocked(id);
if (deviceInfo == nullptr) {
diff --git a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
index 45a31ee..4bfe11d 100644
--- a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
@@ -526,13 +526,11 @@
__FUNCTION__, strerror(-res), res);
return;
}
- if (flags::camera_manual_flash_strength_control()) {
- res = fixupManualFlashStrengthControlTags(mCameraCharacteristics);
- if (OK != res) {
- ALOGE("%s: Unable to fix up manual flash strength control tags: %s (%d)",
- __FUNCTION__, strerror(-res), res);
- return;
- }
+ res = fixupManualFlashStrengthControlTags(mCameraCharacteristics);
+ if (OK != res) {
+ ALOGE("%s: Unable to fix up manual flash strength control tags: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ return;
}
auto stat = addDynamicDepthTags();
@@ -679,13 +677,11 @@
__FUNCTION__, strerror(-res), res);
}
- if (flags::camera_manual_flash_strength_control()) {
- res = fixupManualFlashStrengthControlTags(mPhysicalCameraCharacteristics[id]);
- if (OK != res) {
- ALOGE("%s: Unable to fix up manual flash strength control tags: %s (%d)",
- __FUNCTION__, strerror(-res), res);
- return;
- }
+ res = fixupManualFlashStrengthControlTags(mPhysicalCameraCharacteristics[id]);
+ if (OK != res) {
+ ALOGE("%s: Unable to fix up manual flash strength control tags: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ return;
}
}
}
diff --git a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
index c394d43..6cedb04 100644
--- a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
@@ -616,13 +616,12 @@
__FUNCTION__, strerror(-res), res);
return;
}
- if (flags::camera_manual_flash_strength_control()) {
- res = fixupManualFlashStrengthControlTags(mCameraCharacteristics);
- if (OK != res) {
- ALOGE("%s: Unable to fix up manual flash strength control tags: %s (%d)",
- __FUNCTION__, strerror(-res), res);
- return;
- }
+
+ res = fixupManualFlashStrengthControlTags(mCameraCharacteristics);
+ if (OK != res) {
+ ALOGE("%s: Unable to fix up manual flash strength control tags: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ return;
}
auto stat = addDynamicDepthTags();
@@ -780,13 +779,11 @@
__FUNCTION__, strerror(-res), res);
}
- if (flags::camera_manual_flash_strength_control()) {
- res = fixupManualFlashStrengthControlTags(mPhysicalCameraCharacteristics[id]);
- if (OK != res) {
- ALOGE("%s: Unable to fix up manual flash strength control tags: %s (%d)",
- __FUNCTION__, strerror(-res), res);
- return;
- }
+ res = fixupManualFlashStrengthControlTags(mPhysicalCameraCharacteristics[id]);
+ if (OK != res) {
+ ALOGE("%s: Unable to fix up manual flash strength control tags: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ return;
}
}
}
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 4934203..ceb3d30 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -29,6 +29,9 @@
#include "ui/GraphicBufferMapper.h"
#include <cutils/properties.h>
+#include <com_android_internal_camera_flags.h>
+
+namespace flags = com::android::internal::camera::flags;
namespace android {
@@ -388,6 +391,10 @@
mOldDataSpace == camera_stream::data_space &&
mOldFormat == camera_stream::format) {
mState = STATE_CONFIGURED;
+ if (flags::enable_stream_reconfiguration_for_unchanged_streams()
+ && streamReconfigured != nullptr) {
+ *streamReconfigured = true;
+ }
return OK;
}
diff --git a/services/mediametrics/AudioAnalytics.cpp b/services/mediametrics/AudioAnalytics.cpp
index bd4ac38..c01d46e 100644
--- a/services/mediametrics/AudioAnalytics.cpp
+++ b/services/mediametrics/AudioAnalytics.cpp
@@ -555,22 +555,24 @@
}
std::pair<std::string, int32_t> AudioAnalytics::dump(
- int32_t lines, int64_t sinceNs, const char *prefix) const
+ bool details, int32_t lines, int64_t sinceNs, const char *prefix) const
{
std::stringstream ss;
int32_t ll = lines;
if (ll > 0) {
- auto [s, l] = mAnalyticsState->dump(ll, sinceNs, prefix);
+ auto [s, l] = mAnalyticsState->dump(details, ll, sinceNs, prefix);
ss << s;
ll -= l;
}
- if (ll > 0) {
+
+ // use details to dump prior state.
+ if (details && ll > 0) {
ss << "Prior audioserver state:\n";
--ll;
}
- if (ll > 0) {
- auto [s, l] = mPreviousAnalyticsState->dump(ll, sinceNs, prefix);
+ if (details && ll > 0) {
+ auto [s, l] = mPreviousAnalyticsState->dump(details, ll, sinceNs, prefix);
ss << s;
ll -= l;
}
diff --git a/services/mediametrics/MediaMetricsService.cpp b/services/mediametrics/MediaMetricsService.cpp
index 1309626..2ec4ac8 100644
--- a/services/mediametrics/MediaMetricsService.cpp
+++ b/services/mediametrics/MediaMetricsService.cpp
@@ -49,12 +49,9 @@
// (0 for either of these disables that threshold)
//
static constexpr nsecs_t kMaxRecordAgeNs = 28 * 3600 * NANOS_PER_SECOND;
-// 2019/6: average daily per device is currently 375-ish;
-// setting this to 2000 is large enough to catch most devices
-// we'll lose some data on very very media-active devices, but only for
-// the gms collection; statsd will have already covered those for us.
-// This also retains enough information to help with bugreports
-static constexpr size_t kMaxRecords = 2000;
+
+// Max records to keep in queue which dump out for bugreports.
+static constexpr size_t kMaxRecords = 2500;
// max we expire in a single call, to constrain how long we hold the
// mutex, which also constrains how long a client might wait.
@@ -311,7 +308,8 @@
// TODO: maybe consider a better way of dumping audio analytics info.
const int32_t linesToDump = all ? INT32_MAX : 1000;
- auto [ dumpString, lines ] = mAudioAnalytics.dump(linesToDump, sinceNs, prefixptr);
+ auto [ dumpString, lines ] = mAudioAnalytics.dump(
+ all, linesToDump, sinceNs, prefixptr);
result << dumpString;
if (lines == linesToDump) {
result << "-- some lines may be truncated --\n";
diff --git a/services/mediametrics/include/mediametricsservice/AnalyticsState.h b/services/mediametrics/include/mediametricsservice/AnalyticsState.h
index 09c0b4c..1dabe5d 100644
--- a/services/mediametrics/include/mediametricsservice/AnalyticsState.h
+++ b/services/mediametrics/include/mediametricsservice/AnalyticsState.h
@@ -83,11 +83,12 @@
* different locks, so may not be 100% consistent with the last data
* delivered.
*
+ * \param details dumps the detailed internal state.
* \param lines the maximum number of lines in the string returned.
* \param sinceNs the nanoseconds since Unix epoch to start dump (0 shows all)
* \param prefix the desired key prefix to match (nullptr shows all)
*/
- std::pair<std::string, int32_t> dump(
+ std::pair<std::string, int32_t> dump(bool details,
int32_t lines = INT32_MAX, int64_t sinceNs = 0, const char *prefix = nullptr) const {
std::stringstream ss;
int32_t ll = lines;
@@ -96,7 +97,7 @@
ss << "TransactionLog: gc(" << mTransactionLog.getGarbageCollectionCount() << ")\n";
--ll;
}
- if (ll > 0) {
+ if (details && ll > 0) {
auto [s, l] = mTransactionLog.dump(ll, sinceNs, prefix);
ss << s;
ll -= l;
@@ -105,7 +106,7 @@
ss << "TimeMachine: gc(" << mTimeMachine.getGarbageCollectionCount() << ")\n";
--ll;
}
- if (ll > 0) {
+ if (details && ll > 0) {
auto [s, l] = mTimeMachine.dump(ll, sinceNs, prefix);
ss << s;
ll -= l;
diff --git a/services/mediametrics/include/mediametricsservice/AudioAnalytics.h b/services/mediametrics/include/mediametricsservice/AudioAnalytics.h
index f0a4ac8..57f55c1 100644
--- a/services/mediametrics/include/mediametricsservice/AudioAnalytics.h
+++ b/services/mediametrics/include/mediametricsservice/AudioAnalytics.h
@@ -67,11 +67,12 @@
* different locks, so may not be 100% consistent with the last data
* delivered.
*
+ * \param details dumps the detailed internal state.
* \param lines the maximum number of lines in the string returned.
* \param sinceNs the nanoseconds since Unix epoch to start dump (0 shows all)
* \param prefix the desired key prefix to match (nullptr shows all)
*/
- std::pair<std::string, int32_t> dump(
+ std::pair<std::string, int32_t> dump(bool details,
int32_t lines = INT32_MAX, int64_t sinceNs = 0, const char *prefix = nullptr) const;
/**
diff --git a/services/mediametrics/tests/mediametrics_tests.cpp b/services/mediametrics/tests/mediametrics_tests.cpp
index 4a6aee4..a7684f4 100644
--- a/services/mediametrics/tests/mediametrics_tests.cpp
+++ b/services/mediametrics/tests/mediametrics_tests.cpp
@@ -850,14 +850,14 @@
// TODO: Verify contents of AudioAnalytics.
// Currently there is no getter API in AudioAnalytics besides dump.
- ASSERT_EQ(10, audioAnalytics.dump(1000).second /* lines */);
+ ASSERT_EQ(10, audioAnalytics.dump(true /* details */, 1000).second /* lines */);
ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item, true /* isTrusted */));
// untrusted entities can add to an existing key
ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item2, false /* isTrusted */));
// Check that we have some info in the dump.
- ASSERT_LT(9, audioAnalytics.dump(1000).second /* lines */);
+ ASSERT_LT(9, audioAnalytics.dump(true /* details */, 1000).second /* lines */);
}
TEST(mediametrics_tests, audio_analytics_permission2) {
@@ -888,14 +888,14 @@
// TODO: Verify contents of AudioAnalytics.
// Currently there is no getter API in AudioAnalytics besides dump.
- ASSERT_EQ(10, audioAnalytics.dump(1000).second /* lines */);
+ ASSERT_EQ(10, audioAnalytics.dump(true /* details */, 1000).second /* lines */);
ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item, true /* isTrusted */));
// untrusted entities can add to an existing key
ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item2, false /* isTrusted */));
// Check that we have some info in the dump.
- ASSERT_LT(9, audioAnalytics.dump(1000).second /* lines */);
+ ASSERT_LT(9, audioAnalytics.dump(true /* details */, 1000).second /* lines */);
}
TEST(mediametrics_tests, audio_analytics_dump) {
@@ -922,13 +922,13 @@
ASSERT_EQ(NO_ERROR, audioAnalytics.submit(item3, true /* isTrusted */));
// find out how many lines we have.
- auto [string, lines] = audioAnalytics.dump(1000);
+ auto [string, lines] = audioAnalytics.dump(true /* details */, 1000);
ASSERT_EQ(lines, (int32_t) countNewlines(string.c_str()));
printf("AudioAnalytics: %s", string.c_str());
// ensure that dump operates over those lines.
for (int32_t ll = 0; ll < lines; ++ll) {
- auto [s, l] = audioAnalytics.dump(ll);
+ auto [s, l] = audioAnalytics.dump(true /* details */, ll);
ASSERT_EQ(ll, l);
ASSERT_EQ(ll, (int32_t) countNewlines(s.c_str()));
}