Merge "Camera: Remove flag "concert_mode"" into main
diff --git a/camera/camera_platform.aconfig b/camera/camera_platform.aconfig
index b5d4ae5..bf1520b 100644
--- a/camera/camera_platform.aconfig
+++ b/camera/camera_platform.aconfig
@@ -218,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/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/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/psh_utils/AudioToken.cpp b/media/psh_utils/AudioToken.cpp
index 626f959..f7bf382 100644
--- a/media/psh_utils/AudioToken.cpp
+++ b/media/psh_utils/AudioToken.cpp
@@ -41,6 +41,14 @@
// 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);
}
diff --git a/media/psh_utils/PowerClientStats.cpp b/media/psh_utils/PowerClientStats.cpp
index 77d79e4..65f65a44 100644
--- a/media/psh_utils/PowerClientStats.cpp
+++ b/media/psh_utils/PowerClientStats.cpp
@@ -39,12 +39,12 @@
void PowerClientStats::stop(int64_t actualNs) {
std::lock_guard l(mMutex);
if (--mTokenCount > 0) return;
- if (mStartNs != 0) mDeltaNs += actualNs - mStartNs;
+ if (mStartNs != 0) mCumulativeNs += actualNs - mStartNs;
mStartNs = 0;
if (!mStartStats) return;
const auto stopStats = PowerStatsCollector::getCollector().getStats(kStatTimeToleranceNs);
if (stopStats && stopStats != mStartStats) {
- *mDeltaStats += *stopStats - *mStartStats;
+ *mCumulativeStats += *stopStats - *mStartStats;
}
mStartStats.reset();
}
@@ -64,15 +64,15 @@
std::lock_guard l(mMutex);
// Adjust delta time and stats if currently running.
- auto deltaStats = mDeltaStats;
- auto deltaNs = mDeltaNs;
- if (mStartNs) deltaNs += systemTime(SYSTEM_TIME_BOOTTIME) - mStartNs;
+ 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>(*deltaStats);
+ auto newStats = std::make_shared<PowerStats>(*cumulativeStats);
*newStats += *stopStats - *mStartStats;
- deltaStats = newStats;
+ cumulativeStats = newStats;
}
}
@@ -81,7 +81,7 @@
.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(deltaNs * 1e-9));
+ .append(" seconds: ").append(std::to_string(cumulativeNs * 1e-9));
result.append(" {");
for (auto pid : mPids) {
result.append(" ").append(std::to_string(pid));
@@ -93,7 +93,7 @@
if (stats) {
std::string prefix2(prefix);
prefix2.append(" ");
- result.append("\n").append(deltaStats->normalizedEnergy(prefix2));
+ result.append("\n").append(cumulativeStats->normalizedEnergy(prefix2));
}
return result;
}
diff --git a/media/psh_utils/include/psh_utils/PowerClientStats.h b/media/psh_utils/include/psh_utils/PowerClientStats.h
index 93d1fa9..6e27e41 100644
--- a/media/psh_utils/include/psh_utils/PowerClientStats.h
+++ b/media/psh_utils/include/psh_utils/PowerClientStats.h
@@ -87,10 +87,12 @@
int64_t mStartNs GUARDED_BY(mMutex) = 0;
std::shared_ptr<const PowerStats> mStartStats GUARDED_BY(mMutex);
- // Total actual time app is active (stop - start)
- int64_t mDeltaNs GUARDED_BY(mMutex) = 0;
- // The stats taken for the active time (snapshots are quantized to 500ms accuracy).
- std::shared_ptr<PowerStats> mDeltaStats GUARDED_BY(mMutex) = std::make_shared<PowerStats>();
+ // 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/tests/benchmark/MediaBenchmarkTest/Android.bp b/media/tests/benchmark/MediaBenchmarkTest/Android.bp
index 1049d5e..8f9ee86 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/Android.bp
+++ b/media/tests/benchmark/MediaBenchmarkTest/Android.bp
@@ -69,6 +69,6 @@
java_defaults {
name: "MediaBenchmark-defaults",
- min_sdk_version: "29",
- target_sdk_version: "30",
+ min_sdk_version: "35",
+ target_sdk_version: "35",
}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/AndroidManifest.xml b/media/tests/benchmark/MediaBenchmarkTest/AndroidManifest.xml
index 28c2654..bc0c16f 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/AndroidManifest.xml
+++ b/media/tests/benchmark/MediaBenchmarkTest/AndroidManifest.xml
@@ -26,7 +26,7 @@
tools:ignore="AllowBackup,GoogleAppIndexingWarning,MissingApplicationIcon"
tools:remove="android:appComponentFactory">
</application>
- <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="31"/>
+ <uses-sdk android:minSdkVersion="35" android:targetSdkVersion="35"/>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.media.benchmark"
android:label="Benchmark Media Test"/>
diff --git a/media/tests/benchmark/MediaBenchmarkTest/build.gradle b/media/tests/benchmark/MediaBenchmarkTest/build.gradle
index a2af701..87fc24c 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/build.gradle
+++ b/media/tests/benchmark/MediaBenchmarkTest/build.gradle
@@ -27,11 +27,11 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 30
+ compileSdkVersion 35
defaultConfig {
applicationId "com.android.media.benchmark"
minSdkVersion 29
- targetSdkVersion 30
+ targetSdkVersion 35
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/DecoderTest.java b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/DecoderTest.java
index afd70a3..c68a990 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/DecoderTest.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/DecoderTest.java
@@ -46,6 +46,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.List;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
@@ -118,7 +119,7 @@
}
@Test(timeout = PER_TEST_TIMEOUT_MS)
- public void testDecoder() throws IOException {
+ public void testDecoder() throws IOException, InterruptedException {
File inputFile = new File(mInputFilePath + mInputFile);
assertTrue("Cannot find " + mInputFile + " in directory " + mInputFilePath,
inputFile.exists());
@@ -133,7 +134,7 @@
extractor.selectExtractorTrack(currentTrack);
MediaFormat format = extractor.getFormat(currentTrack);
String mime = format.getString(MediaFormat.KEY_MIME);
- ArrayList<String> mediaCodecs = CodecUtils.selectCodecs(mime, false);
+ List<String> mediaCodecs = CodecUtils.selectCodecs(mime, false);
assertTrue("No suitable codecs found for file: " + mInputFile + " track : " +
currentTrack + " mime: " + mime, (mediaCodecs.size() > 0));
@@ -205,7 +206,7 @@
extractor.selectExtractorTrack(currentTrack);
MediaFormat format = extractor.getFormat(currentTrack);
String mime = format.getString(MediaFormat.KEY_MIME);
- ArrayList<String> mediaCodecs = CodecUtils.selectCodecs(mime, false);
+ List<String> mediaCodecs = CodecUtils.selectCodecs(mime, false);
for (String codecName : mediaCodecs) {
Log.i("Test: %s\n", mInputFile);
Native nativeDecoder = new Native();
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java
index 4202732..4ce5214 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java
@@ -50,6 +50,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.List;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
@@ -150,7 +151,7 @@
}
@BeforeClass
- public static void prepareInput() throws IOException {
+ public static void prepareInput() throws IOException, InterruptedException {
mDecodedFileFullHd = new File(mFileDirPath + DECODE_FULLHD_UNPACKED);
int status = decodeFile(mInputFilePath + DECODE_FULLHD_INPUT, mDecodedFileFullHd);
@@ -165,7 +166,8 @@
assertEquals("Decoder returned error " + status, 0, status);
}
- private static int decodeFile(String inputFileName, File outputDecodeFile) throws IOException {
+ private static int decodeFile(String inputFileName, File outputDecodeFile)
+ throws IOException, InterruptedException {
int status = -1;
File inputFile = new File(inputFileName);
assertTrue("Cannot open input file " + inputFileName, inputFile.exists());
@@ -220,7 +222,7 @@
int status;
int frameSize;
- ArrayList<String> mediaCodecs = CodecUtils.selectCodecs(mMime, true);
+ List<String> mediaCodecs = CodecUtils.selectCodecs(mMime, true);
assertTrue("No suitable codecs found for mimetype: " + mMime, (mediaCodecs.size() > 0));
Boolean[] encodeMode = {true, false};
// Encoding the decoded input file
@@ -297,7 +299,7 @@
@Test(timeout = PER_TEST_TIMEOUT_MS)
public void testNativeEncoder() {
- ArrayList<String> mediaCodecs = CodecUtils.selectCodecs(mMime, true);
+ List<String> mediaCodecs = CodecUtils.selectCodecs(mMime, true);
assertTrue("No suitable codecs found for mimetype: " + mMime, (mediaCodecs.size() > 0));
for (String codecName : mediaCodecs) {
Native nativeEncoder = new Native();
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/CodecUtils.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/CodecUtils.java
index 1e10b37..f223242 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/CodecUtils.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/CodecUtils.java
@@ -5,6 +5,7 @@
import android.media.MediaFormat;
import android.os.Build;
import java.util.ArrayList;
+import java.util.List;
public class CodecUtils {
private CodecUtils() {}
@@ -15,7 +16,7 @@
* @param isEncoder Specifies encoder or decoder
* @return ArrayList of codec names
*/
- public static ArrayList<String> selectCodecs(String mimeType, boolean isEncoder) {
+ public static List<String> selectCodecs(String mimeType, boolean isEncoder) {
MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
MediaCodecInfo[] codecInfos = codecList.getCodecInfos();
ArrayList<String> supportedCodecs = new ArrayList<>();
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java
index e947ef6..e9b337d 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Decoder.java
@@ -28,7 +28,10 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
+import java.util.ArrayDeque;
import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
import com.android.media.benchmark.library.IBufferXfer;
@@ -37,28 +40,28 @@
private static final boolean DEBUG = false;
private static final int kQueueDequeueTimeoutUs = 1000;
- private final Object mLock = new Object();
- private MediaCodec mCodec;
- private Surface mSurface = null;
- private boolean mRender = false;
- private ArrayList<BufferInfo> mInputBufferInfo;
- private Stats mStats;
- private String mMime;
+ protected final Object mLock = new Object();
+ protected MediaCodec mCodec;
+ protected Surface mSurface = null;
+ protected boolean mRender = false;
+ protected ArrayList<BufferInfo> mInputBufferInfo;
+ protected Stats mStats;
+ protected String mMime;
- private boolean mSawInputEOS;
- private boolean mSawOutputEOS;
- private boolean mSignalledError;
+ protected boolean mSawInputEOS;
+ protected boolean mSawOutputEOS;
+ protected boolean mSignalledError;
- private int mNumInFramesProvided;
- private int mNumInFramesRequired;
+ protected int mNumInFramesProvided;
+ protected int mNumInFramesRequired;
- private int mNumOutputFrame;
- private int mIndex;
+ protected int mNumOutputFrame;
+ protected int mIndex;
- private ArrayList<ByteBuffer> mInputBuffer;
- private FileOutputStream mOutputStream;
- private FrameReleaseQueue mFrameReleaseQueue = null;
- private IBufferXfer.ISendBuffer mIBufferSend = null;
+ protected ArrayList<ByteBuffer> mInputBuffer;
+ protected FileOutputStream mOutputStream;
+ protected FrameReleaseQueue mFrameReleaseQueue = null;
+ protected IBufferXfer.ISendBuffer mIBufferSend = null;
/* success for decoder */
public static final int DECODE_SUCCESS = 0;
@@ -71,7 +74,9 @@
@Override
public boolean receiveBuffer(IBufferXfer.BufferXferInfo info) {
MediaCodec codec = (MediaCodec)info.obj;
- codec.releaseOutputBuffer(info.idx, mRender);
+ if (info.isComplete) {
+ codec.releaseOutputBuffer(info.idx, mRender);
+ }
return true;
}
@Override
@@ -133,6 +138,49 @@
}
}
+ protected void setCallback(MediaCodec codec) {
+ codec.setCallback(new MediaCodec.Callback() {
+ @Override
+ public void onInputBufferAvailable(
+ @NonNull MediaCodec mediaCodec, int inputBufferId) {
+ try {
+ mStats.addInputTime();
+ onInputAvailable(inputBufferId, mediaCodec);
+ } catch (Exception e) {
+ e.printStackTrace();
+ Log.e(TAG, e.toString());
+ }
+ }
+
+ @Override
+ public void onOutputBufferAvailable(@NonNull MediaCodec mediaCodec,
+ int outputBufferId, @NonNull MediaCodec.BufferInfo bufferInfo) {
+ mStats.addOutputTime();
+ onOutputAvailable(mediaCodec, outputBufferId, bufferInfo);
+ if (mSawOutputEOS) {
+ synchronized (mLock) { mLock.notify(); }
+ }
+ }
+
+ @Override
+ public void onOutputFormatChanged(
+ @NonNull MediaCodec mediaCodec, @NonNull MediaFormat format) {
+ Log.i(TAG, "Output format changed. Format: " + format.toString());
+ }
+
+ @Override
+ public void onError(
+ @NonNull MediaCodec mediaCodec, @NonNull MediaCodec.CodecException e) {
+ mSignalledError = true;
+ Log.e(TAG, "Codec Error: " + e.toString());
+ e.printStackTrace();
+ synchronized (mLock) { mLock.notify(); }
+ }
+ });
+
+
+ }
+
/**
* Decodes the given input buffer,
* provided valid list of buffer info and format are passed as inputs.
@@ -146,9 +194,10 @@
* DECODE_CREATE_ERROR for decoder not created
* @throws IOException if the codec cannot be created.
*/
- public int decode(@NonNull ArrayList<ByteBuffer> inputBuffer,
- @NonNull ArrayList<BufferInfo> inputBufferInfo, final boolean asyncMode,
- @NonNull MediaFormat format, String codecName) throws IOException {
+ public int decode(@NonNull List<ByteBuffer> inputBuffer,
+ @NonNull List<BufferInfo> inputBufferInfo, final boolean asyncMode,
+ @NonNull MediaFormat format, String codecName)
+ throws IOException, InterruptedException {
mInputBuffer = new ArrayList<>(inputBuffer.size());
mInputBuffer.addAll(inputBuffer);
mInputBufferInfo = new ArrayList<>(inputBufferInfo.size());
@@ -170,64 +219,34 @@
mFrameReleaseQueue.setMediaCodec(mCodec);
mFrameReleaseQueue.setMime(mMime);
}
+
if (asyncMode) {
- mCodec.setCallback(new MediaCodec.Callback() {
- @Override
- public void onInputBufferAvailable(
- @NonNull MediaCodec mediaCodec, int inputBufferId) {
- try {
- mStats.addInputTime();
- onInputAvailable(inputBufferId, mediaCodec);
- } catch (Exception e) {
- e.printStackTrace();
- Log.e(TAG, e.toString());
- }
- }
-
- @Override
- public void onOutputBufferAvailable(@NonNull MediaCodec mediaCodec,
- int outputBufferId, @NonNull MediaCodec.BufferInfo bufferInfo) {
- mStats.addOutputTime();
- onOutputAvailable(mediaCodec, outputBufferId, bufferInfo);
- if (mSawOutputEOS) {
- synchronized (mLock) { mLock.notify(); }
- }
- }
-
- @Override
- public void onOutputFormatChanged(
- @NonNull MediaCodec mediaCodec, @NonNull MediaFormat format) {
- Log.i(TAG, "Output format changed. Format: " + format.toString());
- }
-
- @Override
- public void onError(
- @NonNull MediaCodec mediaCodec, @NonNull MediaCodec.CodecException e) {
- mSignalledError = true;
- Log.e(TAG, "Codec Error: " + e.toString());
- e.printStackTrace();
- synchronized (mLock) { mLock.notify(); }
- }
- });
+ setCallback(mCodec);
}
int isEncoder = 0;
if (DEBUG) {
Log.d(TAG, "Media Format : " + format.toString());
}
mCodec.configure(format, mSurface, null, isEncoder);
+
mCodec.start();
- Log.i(TAG, "Codec started ");
+ Log.i(TAG, "Codec started async mode ? " + asyncMode);
long eTime = mStats.getCurTime();
mStats.setInitTime(mStats.getTimeDiff(sTime, eTime));
mStats.setStartTime();
if (asyncMode) {
try {
- synchronized (mLock) { mLock.wait(); }
- if (mSignalledError) {
- return DECODE_DECODER_ERROR;
+ synchronized (mLock) {
+ while (!mSawOutputEOS && !mSignalledError) {
+ mLock.wait();
+ }
+ if (mSignalledError) {
+ return DECODE_DECODER_ERROR;
+ }
}
} catch (InterruptedException e) {
- e.printStackTrace();
+ Log.e(TAG, "Error in waiting");
+ throw e;
}
} else {
while (!mSawOutputEOS && !mSignalledError) {
@@ -319,7 +338,7 @@
return mCodec.getOutputFormat();
}
- private void onInputAvailable(int inputBufferId, MediaCodec mediaCodec) {
+ protected void onInputAvailable(int inputBufferId, MediaCodec mediaCodec) {
if (inputBufferId >= 0) {
ByteBuffer inputCodecBuffer = mediaCodec.getInputBuffer(inputBufferId);
BufferInfo bufInfo;
@@ -351,7 +370,7 @@
}
}
- private void onOutputAvailable(
+ protected void onOutputAvailable(
MediaCodec mediaCodec, int outputBufferId, BufferInfo outputBufferInfo) {
if (mSawOutputEOS || outputBufferId < 0) {
return;
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java
index 63d17ee..3aa38d1 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java
@@ -200,7 +200,8 @@
* @throws IOException If the codec cannot be created.
*/
public int encode(String codecName, MediaFormat encodeFormat, String mime, int frameRate,
- int sampleRate, int frameSize, boolean asyncMode) throws IOException {
+ int sampleRate, int frameSize, boolean asyncMode)
+ throws IOException, InterruptedException {
mInputBufferSize = (mInputStream != null) ? mInputStream.getChannel().size() : 0;
mOffset = 0;
mFrameRate = frameRate;
@@ -275,12 +276,16 @@
mStats.setStartTime();
if (asyncMode) {
try {
- synchronized (mLock) { mLock.wait(); }
- if (mSignalledError) {
- return ENCODE_ENCODER_ERROR;
+ synchronized (mLock) {
+ while (!mSawOutputEOS && !mSignalledError) {
+ mLock.wait();
+ }
+ if (mSignalledError) {
+ return ENCODE_ENCODER_ERROR;
+ }
}
} catch (InterruptedException e) {
- e.printStackTrace();
+ throw e;
}
} else {
while (!mSawOutputEOS && !mSignalledError) {
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Extractor.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Extractor.java
index f3024e7..1c0f810 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Extractor.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Extractor.java
@@ -76,6 +76,21 @@
public MediaCodec.BufferInfo getBufferInfo() { return this.mBufferInfo; }
/**
+ * Returns the maximum sample size for the selected track
+ * @return max sample size in the given track
+ */
+ public int getMaxSampleSize() {
+ int size = 0;
+ int maxSampleSize = 0;
+ while ((size = (int) mExtractor.getSampleSize()) != -1) {
+ maxSampleSize = Math.max(maxSampleSize, size);
+ mExtractor.advance();
+ }
+ mExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
+ return maxSampleSize;
+ }
+
+ /**
* Returns the duration of the sample
*/
public long getClipDuration() { return this.mDurationUs; }
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/FrameReleaseQueue.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/FrameReleaseQueue.java
index 90731ed..20a2573 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/FrameReleaseQueue.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/FrameReleaseQueue.java
@@ -185,7 +185,7 @@
try {
mCodec.releaseOutputBuffer(curFrameInfo.bufferId, actualRender);
} catch (IllegalStateException e) {
- e.printStackTrace();
+ throw(e);
}
});
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/IBufferXfer.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/IBufferXfer.java
index a75962c..c97a35c 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/IBufferXfer.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/IBufferXfer.java
@@ -28,6 +28,7 @@
public Object obj;
int flag;
int bytesRead;
+ boolean isComplete = true;
long presentationTimeUs;
}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/IBufferXferImpl.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/IBufferXferImpl.java
index ab55df5..3e6cee1 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/IBufferXferImpl.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/IBufferXferImpl.java
@@ -16,9 +16,9 @@
package com.android.media.benchmark.library;
-/**
+/*
* Class that manages the buffer senders
-*/
+ */
import com.android.media.benchmark.library.IBufferXfer;
import java.util.ArrayDeque;
import android.util.Log;
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/MultiAccessUnitDecoder.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/MultiAccessUnitDecoder.java
new file mode 100644
index 0000000..cb92f06
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/MultiAccessUnitDecoder.java
@@ -0,0 +1,223 @@
+/*
+ * 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.
+ */
+
+package com.android.media.benchmark.library;
+
+import android.view.Surface;
+
+import android.media.MediaCodec;
+import android.media.MediaCodec.BufferInfo;
+import android.media.MediaFormat;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import com.android.media.benchmark.library.IBufferXfer;
+import com.android.media.benchmark.library.Decoder;
+
+public class MultiAccessUnitDecoder extends Decoder {
+ private static final String TAG = "MultiAccessUnitDecoder";
+ private static final boolean DEBUG = false;
+ private final ArrayDeque<BufferInfo> mInputInfos = new ArrayDeque<>();
+
+ @Override
+ public void setCallback(MediaCodec codec) {
+ mCodec.setCallback(new MediaCodec.Callback() {
+ boolean isUsingLargeFrameMode = false;
+
+ @Override
+ public void onInputBufferAvailable(
+ @NonNull MediaCodec mediaCodec, int inputBufferId) {
+ try {
+ mStats.addInputTime();
+ if (isUsingLargeFrameMode) {
+ onInputsAvailable(inputBufferId, mediaCodec);
+ } else {
+ onInputAvailable(inputBufferId, mediaCodec);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ Log.e(TAG, e.toString());
+ }
+ }
+
+ @Override
+ public void onOutputBufferAvailable(@NonNull MediaCodec mediaCodec,
+ int outputBufferId, @NonNull MediaCodec.BufferInfo bufferInfo) {
+ mStats.addOutputTime();
+ onOutputAvailable(mediaCodec, outputBufferId, bufferInfo);
+ if (mSawOutputEOS) {
+ synchronized (mLock) { mLock.notify(); }
+ }
+ }
+
+ @Override
+ public void onOutputBuffersAvailable(
+ @NonNull MediaCodec mediaCodec,
+ int outputBufferId, @NonNull ArrayDeque<BufferInfo> infos) {
+ int i = 0;
+ while(i++ < infos.size()) {
+ mStats.addOutputTime();
+ }
+ onOutputsAvailable(mediaCodec, outputBufferId, infos);
+ if (mSawOutputEOS) {
+ synchronized (mLock) { mLock.notify(); }
+ }
+ }
+
+ @Override
+ public void onOutputFormatChanged(
+ @NonNull MediaCodec mediaCodec, @NonNull MediaFormat format) {
+ Log.i(TAG, "Output format changed. Format: " + format.toString());
+ final int maxOutputSize = format.getNumber(
+ MediaFormat.KEY_BUFFER_BATCH_MAX_OUTPUT_SIZE, 0).intValue();
+ isUsingLargeFrameMode = (maxOutputSize > 0);
+ }
+
+ @Override
+ public void onError(
+ @NonNull MediaCodec mediaCodec, @NonNull MediaCodec.CodecException e) {
+ mSignalledError = true;
+ Log.e(TAG, "Codec Error: " + e.toString());
+ e.printStackTrace();
+ synchronized (mLock) { mLock.notify(); }
+ }
+ });
+
+ }
+ /**
+ * Decodes the given input buffer,
+ * provided valid list of buffer info and format are passed as inputs.
+ *
+ * @param inputBuffer Decode the provided list of ByteBuffers
+ * @param inputBufferInfo List of buffer info corresponding to provided input buffers
+ * @param asyncMode Will run on async implementation if true
+ * @param format For creating the decoder if codec name is empty and configuring it
+ * @param codecName Will create the decoder with codecName
+ * @return DECODE_SUCCESS if decode was successful, DECODE_DECODER_ERROR for fail,
+ * DECODE_CREATE_ERROR for decoder not created
+ * @throws IOException if the codec cannot be created.
+ */
+ @Override
+ public int decode(@NonNull List<ByteBuffer> inputBuffer,
+ @NonNull List<BufferInfo> inputBufferInfo, final boolean asyncMode,
+ @NonNull MediaFormat format, String codecName)
+ throws IOException, InterruptedException {
+ return super.decode(inputBuffer, inputBufferInfo, asyncMode, format, codecName);
+ }
+
+ private void onInputsAvailable(int inputBufferId, MediaCodec mediaCodec) {
+ if (inputBufferId >= 0) {
+ ByteBuffer inputCodecBuffer = mediaCodec.getInputBuffer(inputBufferId);
+ BufferInfo bufInfo;
+ mInputInfos.clear();
+ int offset = 0;
+ while (mNumInFramesProvided < mNumInFramesRequired) {
+ bufInfo = mInputBufferInfo.get(mIndex);
+ mSawInputEOS = (bufInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
+ if (inputCodecBuffer.remaining() < bufInfo.size) {
+ if (mInputInfos.size() == 0) {
+ Log.d(TAG, "SampleSize " + inputCodecBuffer.remaining()
+ + "greater than MediaCodec Buffer size " + bufInfo.size);
+ }
+ break;
+ }
+ inputCodecBuffer.put(mInputBuffer.get(mIndex).array());
+ bufInfo.offset = offset; offset += bufInfo.size;
+ mInputInfos.add(bufInfo);
+ mNumInFramesProvided++;
+ mIndex = mNumInFramesProvided % (mInputBufferInfo.size() - 1);
+ }
+ if (mNumInFramesProvided >= mNumInFramesRequired) {
+ mIndex = mInputBufferInfo.size() - 1;
+ bufInfo = mInputBufferInfo.get(mIndex);
+ if (inputCodecBuffer.remaining() > bufInfo.size) {
+ if ((bufInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) == 0) {
+ Log.e(TAG, "Error in EOS flag for Decoder");
+ }
+ mSawInputEOS = (bufInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
+ inputCodecBuffer.put(mInputBuffer.get(mIndex).array());
+ bufInfo.offset = offset; offset += bufInfo.size;
+ mInputInfos.add(bufInfo);
+ mNumInFramesProvided++;
+ }
+ }
+ if (mInputInfos.size() == 0) {
+ Log.d(TAG, " No inputs to queue");
+ } else {
+ mStats.addFrameSize(offset);
+ mediaCodec.queueInputBuffers(inputBufferId, mInputInfos);
+ }
+ }
+ }
+
+ private void onOutputsAvailable(MediaCodec mc, int outputBufferId,
+ ArrayDeque<BufferInfo> infos) {
+ if (mSawOutputEOS || outputBufferId < 0) {
+ return;
+ }
+ Iterator<BufferInfo> iter = infos.iterator();
+ while (iter.hasNext()) {
+ BufferInfo bufferInfo = iter.next();
+ mNumOutputFrame++;
+ if (DEBUG) {
+ Log.d(TAG,
+ "In OutputBufferAvailable ,"
+ + " output frame number = " + mNumOutputFrame
+ + " timestamp = " + bufferInfo.presentationTimeUs
+ + " size = " + bufferInfo.size);
+ }
+ if (mIBufferSend != null) {
+ IBufferXfer.BufferXferInfo info = new IBufferXfer.BufferXferInfo();
+ info.buf = mc.getOutputBuffer(outputBufferId);
+ info.idx = outputBufferId;
+ info.obj = mc;
+ info.bytesRead = bufferInfo.size;
+ info.presentationTimeUs = bufferInfo.presentationTimeUs;
+ info.flag = bufferInfo.flags;
+ info.isComplete = iter.hasNext() ? false : true;
+ mIBufferSend.sendBuffer(this, info);
+ }
+ mSawOutputEOS |= (bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
+ }
+ if (mOutputStream != null) {
+ try {
+ ByteBuffer outputBuffer = mc.getOutputBuffer(outputBufferId);
+ byte[] bytesOutput = new byte[outputBuffer.remaining()];
+ outputBuffer.get(bytesOutput);
+ mOutputStream.write(bytesOutput);
+ } catch (IOException e) {
+ e.printStackTrace();
+ Log.d(TAG, "Error Dumping File: Exception " + e.toString());
+ }
+ }
+ if (mIBufferSend == null) {
+ mc.releaseOutputBuffer(outputBufferId, mRender);
+ }
+ if (mSawOutputEOS) {
+ Log.i(TAG, "Large frame - saw output EOS");
+ }
+ // we don't support frame release queue for large audio frame
+ }
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Muxer.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Muxer.java
index 340b539..786290d 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Muxer.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Muxer.java
@@ -23,6 +23,7 @@
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
+import java.util.List;
public class Muxer {
private Stats mStats;
@@ -61,8 +62,8 @@
* @param inputBufferInfo Buffer information related to these samples
* @return Returns Status as 0 if write operation is successful, -1 otherwise
*/
- public int mux(int trackIndex, ArrayList<ByteBuffer> inputExtractedBuffer,
- ArrayList<MediaCodec.BufferInfo> inputBufferInfo) {
+ public int mux(int trackIndex, List<ByteBuffer> inputExtractedBuffer,
+ List<MediaCodec.BufferInfo> inputBufferInfo) {
mStats.setStartTime();
for (int sampleCount = 0; sampleCount < inputExtractedBuffer.size(); sampleCount++) {
try {
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Stats.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Stats.java
index 0ebf798..17de1e7 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Stats.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Stats.java
@@ -23,6 +23,7 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.List;
/**
* Measures Performance.
@@ -88,9 +89,9 @@
public long getStartTime() { return mStartTimeNs; }
- public ArrayList<Long> getOutputTimers() { return mOutputTimer; }
+ public List<Long> getOutputTimers() { return mOutputTimer; }
- public ArrayList<Long> getInputTimers() { return mInputTimer; }
+ public List<Long> getInputTimers() { return mInputTimer; }
public long getTimeDiff(long sTime, long eTime) { return (eTime - sTime); }
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index e1b244b..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
@@ -1065,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;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 0d961bb..3f0bd70 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -4065,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) {
@@ -4090,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();
@@ -11609,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);
@@ -11625,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/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/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 4a839f8..7b7275e 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -1807,6 +1807,7 @@
++numTimesBecameEmpty;
}
mLastCommand = command;
+ status_t createAudioPatchStatus;
switch (command->mCommand) {
case SET_VOLUME: {
@@ -1874,10 +1875,11 @@
ALOGV("AudioCommandThread() processing create audio patch");
sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
if (af == 0) {
- command->mStatus = PERMISSION_DENIED;
+ createAudioPatchStatus = PERMISSION_DENIED;
} else {
ul.unlock();
- command->mStatus = af->createAudioPatch(&data->mPatch, &data->mHandle);
+ createAudioPatchStatus = af->createAudioPatch(&data->mPatch,
+ &data->mHandle);
ul.lock();
}
} break;
@@ -2046,8 +2048,28 @@
{
audio_utils::lock_guard _l(command->mMutex);
if (command->mWaitStatus) {
+ if (command->mCommand == CREATE_AUDIO_PATCH) {
+ command->mStatus = createAudioPatchStatus;
+ }
command->mWaitStatus = false;
command->mCond.notify_one();
+ } else if (command->mCommand == CREATE_AUDIO_PATCH &&
+ command->mStatus == TIMED_OUT &&
+ createAudioPatchStatus == NO_ERROR) {
+ // Because of special handling in insertCommand_l() the CREATE_AUDIO_PATCH
+ // command wait status can be only false in case timeout (see TIMED_OUT)
+ // happened.
+ CreateAudioPatchData *createData =
+ (CreateAudioPatchData *)command->mParam.get();
+ ALOGW("AudioCommandThread() no caller awaiting for handle(%d) after \
+ processing create audio patch, going to release it",
+ createData->mHandle);
+ sp<AudioCommand> releaseCommand = new AudioCommand();
+ releaseCommand->mCommand = RELEASE_AUDIO_PATCH;
+ ReleaseAudioPatchData *releaseData = new ReleaseAudioPatchData();
+ releaseData->mHandle = createData->mHandle;
+ releaseCommand->mParam = releaseData;
+ insertCommand_l(releaseCommand, 0);
}
}
waitTime = -1;
@@ -2607,7 +2629,8 @@
// Disable wait for status if delay is not 0.
// Except for create audio patch command because the returned patch handle
- // is needed by audio policy manager
+ // is needed by audio policy manager. Audio patch created after timeout
+ // (see TIMED_OUT) will be released from threadLoop().
if (delayMs != 0 && command->mCommand != CREATE_AUDIO_PATCH) {
command->mWaitStatus = false;
}
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()));
}