Merge "Resolve uid / pid early during connection" into main
diff --git a/camera/camera_platform.aconfig b/camera/camera_platform.aconfig
index e916985..471bfdf 100644
--- a/camera/camera_platform.aconfig
+++ b/camera/camera_platform.aconfig
@@ -165,6 +165,16 @@
flag {
namespace: "camera_platform"
+ name: "single_thread_executor_naming"
+ description: "Set the device executor thread name."
+ bug: "359709863"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
+ namespace: "camera_platform"
name: "surface_leak_fix"
description: "Address Surface release leaks in CaptureRequest"
bug: "324071855"
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 7d234bb..1b5402f 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -646,9 +646,14 @@
* be made, and for firing pre-capture flash pulses to estimate
* scene brightness and required final capture flash power, when
* the flash is enabled.</p>
- * <p>Normally, this entry should be set to START for only a
- * single request, and the application should wait until the
- * sequence completes before starting a new one.</p>
+ * <p>Flash is enabled during precapture sequence when:</p>
+ * <ul>
+ * <li>AE mode is ON_ALWAYS_FLASH</li>
+ * <li>AE mode is ON_AUTO_FLASH and the scene is deemed too dark without flash, or</li>
+ * <li>AE mode is ON and flash mode is TORCH or SINGLE</li>
+ * </ul>
+ * <p>Normally, this entry should be set to START for only single request, and the
+ * application should wait until the sequence completes before starting a new one.</p>
* <p>When a precapture metering sequence is finished, the camera device
* may lock the auto-exposure routine internally to be able to accurately expose the
* subsequent still capture image (<code>ACAMERA_CONTROL_CAPTURE_INTENT == STILL_CAPTURE</code>).
@@ -2289,8 +2294,6 @@
* boost when the light level threshold is exceeded.</p>
* <p>This state indicates when low light boost is 'ACTIVE' and applied. Similarly, it can
* indicate when it is not being applied by returning 'INACTIVE'.</p>
- * <p>This key will be absent from the CaptureResult if AE mode is not set to
- * 'ON_LOW_LIGHT_BOOST_BRIGHTNESS_PRIORITY.</p>
* <p>The default value will always be 'INACTIVE'.</p>
*/
ACAMERA_CONTROL_LOW_LIGHT_BOOST_STATE = // byte (acamera_metadata_enum_android_control_low_light_boost_state_t)
@@ -2448,6 +2451,13 @@
* in ACAMERA_FLASH_SINGLE_STRENGTH_DEFAULT_LEVEL.
* If ACAMERA_CONTROL_AE_MODE is set to any of <code>ON_AUTO_FLASH</code>, <code>ON_ALWAYS_FLASH</code>,
* <code>ON_AUTO_FLASH_REDEYE</code>, <code>ON_EXTERNAL_FLASH</code> values, then the strengthLevel will be ignored.</p>
+ * <p>When AE mode is ON and flash mode is TORCH or SINGLE, the application should make sure
+ * the AE mode, flash mode, and flash strength level remain the same between precapture
+ * trigger request and final capture request. The flash strength level being set during
+ * precapture sequence is used by the camera device as a reference. The actual strength
+ * may be less, and the auto-exposure routine makes sure proper conversions of sensor
+ * exposure time and sensitivities between precapture and final capture for the specified
+ * strength level.</p>
*
* @see ACAMERA_CONTROL_AE_MODE
* @see ACAMERA_FLASH_MODE
diff --git a/cmds/screenrecord/screenrecord.cpp b/cmds/screenrecord/screenrecord.cpp
index 03c765a..de925b8 100644
--- a/cmds/screenrecord/screenrecord.cpp
+++ b/cmds/screenrecord/screenrecord.cpp
@@ -362,13 +362,26 @@
const ui::DisplayState& displayState,
const sp<IGraphicBufferProducer>& bufferProducer,
sp<IBinder>* pDisplayHandle, sp<SurfaceControl>* mirrorRoot) {
- static const std::string kDisplayName("ScreenRecorder");
+ std::string displayName = gPhysicalDisplayId
+ ? "ScreenRecorder " + to_string(*gPhysicalDisplayId)
+ : "ScreenRecorder";
+ static const std::string kDisplayName(displayName);
+
sp<IBinder> dpy = SurfaceComposerClient::createVirtualDisplay(kDisplayName, gSecureDisplay);
SurfaceComposerClient::Transaction t;
t.setDisplaySurface(dpy, bufferProducer);
setDisplayProjection(t, dpy, displayState);
+
+ // ensures that random layer stack assigned to virtual display changes
+ // between calls - if a list of displays with their layer stacks becomes
+ // available, we should use it to ensure a new layer stack is used here
+ std::srand(
+ std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::system_clock::now().time_since_epoch()
+ ).count());
ui::LayerStack layerStack = ui::LayerStack::fromValue(std::rand());
t.setDisplayLayerStack(dpy, layerStack);
+
PhysicalDisplayId displayId;
status_t err = getPhysicalDisplayId(displayId);
if (err != NO_ERROR) {
@@ -1224,6 +1237,8 @@
" see \"dumpsys SurfaceFlinger --display-id\" for valid display IDs.\n"
"--verbose\n"
" Display interesting information on stdout.\n"
+ "--version\n"
+ " Show Android screenrecord version.\n"
"--help\n"
" Show this message.\n"
"\n"
@@ -1255,6 +1270,7 @@
{ "bframes", required_argument, NULL, 'B' },
{ "display-id", required_argument, NULL, 'd' },
{ "capture-secure", no_argument, NULL, 'S' },
+ { "version", no_argument, NULL, 'x' },
{ NULL, 0, NULL, 0 }
};
@@ -1377,6 +1393,9 @@
case 'S':
gSecureDisplay = true;
break;
+ case 'x':
+ fprintf(stderr, "%d.%d\n", kVersionMajor, kVersionMinor);
+ return 0;
default:
if (ic != '?') {
fprintf(stderr, "getopt_long returned unexpected value 0x%x\n", ic);
diff --git a/cmds/screenrecord/screenrecord.h b/cmds/screenrecord/screenrecord.h
index cec7c13..57826b0 100644
--- a/cmds/screenrecord/screenrecord.h
+++ b/cmds/screenrecord/screenrecord.h
@@ -18,6 +18,6 @@
#define SCREENRECORD_SCREENRECORD_H
#define kVersionMajor 1
-#define kVersionMinor 3
+#define kVersionMinor 4
#endif /*SCREENRECORD_SCREENRECORD_H*/
diff --git a/media/aconfig/codec_fwk.aconfig b/media/aconfig/codec_fwk.aconfig
index d662585..362e98e 100644
--- a/media/aconfig/codec_fwk.aconfig
+++ b/media/aconfig/codec_fwk.aconfig
@@ -133,3 +133,10 @@
description: "Feature flag to track teamfood population"
bug: "328770262"
}
+
+flag {
+ name: "thumbnail_block_model"
+ namespace: "codec_fwk"
+ description: "Feature flag for using block model decoder in thumbnail generation"
+ bug: "329521645"
+}
diff --git a/media/audio/aconfig/audio_framework.aconfig b/media/audio/aconfig/audio_framework.aconfig
index 0209e28..b940e78 100644
--- a/media/audio/aconfig/audio_framework.aconfig
+++ b/media/audio/aconfig/audio_framework.aconfig
@@ -22,6 +22,13 @@
bug: "302323921"
}
+flag{
+ name: "enable_ringtone_haptics_customization"
+ namespace: "media_audio"
+ description: "Enables haptic customization for playing ringtone."
+ bug: "351974934"
+}
+
flag {
name: "feature_spatial_audio_headtracking_low_latency"
is_exported: true
diff --git a/media/codec2/hal/client/GraphicsTracker.cpp b/media/codec2/hal/client/GraphicsTracker.cpp
index efac892..bdfc409 100644
--- a/media/codec2/hal/client/GraphicsTracker.cpp
+++ b/media/codec2/hal/client/GraphicsTracker.cpp
@@ -34,7 +34,7 @@
c2_status_t retrieveAHardwareBufferId(const C2ConstGraphicBlock &blk, uint64_t *bid) {
std::shared_ptr<const _C2BlockPoolData> bpData = _C2BlockFactory::GetGraphicBlockPoolData(blk);
- if (bpData->getType() != _C2BlockPoolData::TYPE_AHWBUFFER) {
+ if (!bpData || bpData->getType() != _C2BlockPoolData::TYPE_AHWBUFFER) {
return C2_BAD_VALUE;
}
if (__builtin_available(android __ANDROID_API_T__, *)) {
diff --git a/media/codec2/hal/client/include/codec2/hidl/output.h b/media/codec2/hal/client/include/codec2/hidl/output.h
index ddb9855..108f0a6 100644
--- a/media/codec2/hal/client/include/codec2/hidl/output.h
+++ b/media/codec2/hal/client/include/codec2/hidl/output.h
@@ -96,6 +96,7 @@
uint64_t mBqId;
int32_t mMaxDequeueBufferCount;
std::shared_ptr<int> mOwner;
+ std::shared_ptr<int> mConsumerAttachCount;
// To migrate existing buffers
sp<GraphicBuffer> mBuffers[BufferQueueDefs::NUM_BUFFER_SLOTS]; // find a better way
std::weak_ptr<_C2BlockPoolData> mPoolDatas[BufferQueueDefs::NUM_BUFFER_SLOTS];
diff --git a/media/codec2/hal/client/output.cpp b/media/codec2/hal/client/output.cpp
index 54d78a0..2eb381b 100644
--- a/media/codec2/hal/client/output.cpp
+++ b/media/codec2/hal/client/output.cpp
@@ -261,6 +261,7 @@
mGeneration = generation;
mBqId = bqId;
mOwner = std::make_shared<int>(0);
+ mConsumerAttachCount = std::make_shared<int>(0);
mMaxDequeueBufferCount = maxDequeueBufferCount;
if (igbp == nullptr) {
return false;
@@ -522,6 +523,7 @@
std::shared_ptr<C2SurfaceSyncMemory> syncMem;
sp<IGraphicBufferProducer> outputIgbp;
uint32_t outputGeneration = 0;
+ std::shared_ptr<int> consumerAttachCount;
{
std::unique_lock<std::mutex> l(mMutex);
if (mStopped) {
@@ -529,6 +531,7 @@
}
outputIgbp = mIgbp;
outputGeneration = mGeneration;
+ consumerAttachCount = mConsumerAttachCount;
syncMem = mSyncMem;
}
@@ -536,15 +539,42 @@
auto syncVar = syncMem ? syncMem->mem() : nullptr;
if (syncVar) {
syncVar->lock();
- syncVar->notifyQueuedLocked();
+ if (consumerAttachCount && *consumerAttachCount > 0) {
+ (*consumerAttachCount)--;
+ } else {
+ syncVar->notifyQueuedLocked();
+ }
syncVar->unlock();
}
}
}
void OutputBufferQueue::onBufferAttached(uint32_t generation) {
- // TODO
- (void) generation;
+ std::shared_ptr<C2SurfaceSyncMemory> syncMem;
+ sp<IGraphicBufferProducer> outputIgbp;
+ uint32_t outputGeneration = 0;
+ std::shared_ptr<int> consumerAttachCount;
+ {
+ std::unique_lock<std::mutex> l(mMutex);
+ if (mStopped) {
+ return;
+ }
+ outputIgbp = mIgbp;
+ outputGeneration = mGeneration;
+ consumerAttachCount = mConsumerAttachCount;
+ syncMem = mSyncMem;
+ }
+
+ if (outputIgbp && generation == outputGeneration) {
+ auto syncVar = syncMem ? syncMem->mem() : nullptr;
+ if (syncVar) {
+ syncVar->lock();
+ if (consumerAttachCount) {
+ (*consumerAttachCount)++;
+ }
+ syncVar->unlock();
+ }
+ }
}
void OutputBufferQueue::pollForRenderedFrames(FrameEventHistoryDelta* delta) {
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index 36725ec..a943626 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -1896,7 +1896,8 @@
std::vector<C2QpOffsetRectStruct> c2QpOffsetRects;
char mutableStrQpOffsetRects[strlen(qpOffsetRects.c_str()) + 1];
strcpy(mutableStrQpOffsetRects, qpOffsetRects.c_str());
- char* box = strtok(mutableStrQpOffsetRects, ";");
+ char* savePtr;
+ char* box = strtok_r(mutableStrQpOffsetRects, ";", &savePtr);
while (box != nullptr) {
int top, left, bottom, right, offset;
if (sscanf(box, "%d,%d-%d,%d=%d", &top, &left, &bottom, &right, &offset) == 5) {
@@ -1914,7 +1915,7 @@
} else {
ALOGE("Rects configuration %s doesn't follow the string pattern.", box);
}
- box = strtok(nullptr, ";");
+ box = strtok_r(nullptr, ";", &savePtr);
}
if (c2QpOffsetRects.size() != 0) {
const std::unique_ptr<C2StreamQpOffsetRects::output> regions =
diff --git a/media/codec2/vndk/C2Buffer.cpp b/media/codec2/vndk/C2Buffer.cpp
index 7b9b80d..bff953d 100644
--- a/media/codec2/vndk/C2Buffer.cpp
+++ b/media/codec2/vndk/C2Buffer.cpp
@@ -1311,8 +1311,7 @@
for (size_t planeIx = 0; planeIx < mLayout.numPlanes; ++planeIx) {
const uint32_t colSampling = mLayout.planes[planeIx].colSampling;
const uint32_t rowSampling = mLayout.planes[planeIx].rowSampling;
- if (crop.left % colSampling || crop.right() % colSampling
- || crop.top % rowSampling || crop.bottom() % rowSampling) {
+ if (crop.left % colSampling || crop.top % rowSampling) {
// cannot calculate data pointer
mImpl->getAllocation()->unmap(mData, crop, nullptr);
memset(&mLayout, 0, sizeof(mLayout));
diff --git a/media/libaaudio/Android.bp b/media/libaaudio/Android.bp
index 4b417a7..add28e0 100644
--- a/media/libaaudio/Android.bp
+++ b/media/libaaudio/Android.bp
@@ -36,9 +36,6 @@
symbol_file: "src/libaaudio.map.txt",
first_version: "26",
unversioned_until: "current",
- export_header_libs: [
- "libAAudio_headers",
- ],
}
cc_library_headers {
diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp
index 1e27a81..1e8ac8d 100644
--- a/media/libaaudio/src/core/AAudioAudio.cpp
+++ b/media/libaaudio/src/core/AAudioAudio.cpp
@@ -602,6 +602,7 @@
}
AAUDIO_API aaudio_result_t AAudio_setMMapPolicy(aaudio_policy_t policy) {
+ ALOGD("%s(%d)", __func__, policy);
return AudioGlobal_setMMapPolicy(policy);
}
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.cpp b/media/libaaudio/src/core/AudioStreamBuilder.cpp
index c9d8b35..01f0038 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.cpp
+++ b/media/libaaudio/src/core/AudioStreamBuilder.cpp
@@ -109,10 +109,12 @@
std::vector<AudioMMapPolicyInfo> policyInfos;
aaudio_policy_t mmapPolicy = AudioGlobal_getMMapPolicy();
- if (android::AudioSystem::getMmapPolicyInfo(
- AudioMMapPolicyType::DEFAULT, &policyInfos) == NO_ERROR) {
+ ALOGD("%s, global mmap policy is %d", __func__, mmapPolicy);
+ if (status_t status = android::AudioSystem::getMmapPolicyInfo(
+ AudioMMapPolicyType::DEFAULT, &policyInfos); status == NO_ERROR) {
aaudio_policy_t systemMmapPolicy = AAudio_getAAudioPolicy(
policyInfos, AAUDIO_MMAP_POLICY_DEFAULT_AIDL);
+ ALOGD("%s, system mmap policy is %d", __func__, systemMmapPolicy);
if (mmapPolicy == AAUDIO_POLICY_ALWAYS && systemMmapPolicy == AAUDIO_POLICY_NEVER) {
// No need to try as AAudioService is not created and the client only wants MMAP path.
return AAUDIO_ERROR_NO_SERVICE;
@@ -125,6 +127,7 @@
mmapPolicy = systemMmapPolicy;
}
} else {
+ ALOGD("%s, failed to query system mmap policy, error=%d", __func__, status);
// If it fails querying mmap policy info, it is highly possible that the AAudioService is
// not created. In this case, we don't try mmap path.
if (mmapPolicy == AAUDIO_POLICY_ALWAYS) {
@@ -136,17 +139,22 @@
if (mmapPolicy == AAUDIO_UNSPECIFIED) {
mmapPolicy = AAUDIO_MMAP_POLICY_DEFAULT;
}
+ ALOGD("%s, final mmap policy is %d", __func__, mmapPolicy);
policyInfos.clear();
aaudio_policy_t mmapExclusivePolicy = AAUDIO_UNSPECIFIED;
- if (android::AudioSystem::getMmapPolicyInfo(
- AudioMMapPolicyType::EXCLUSIVE, &policyInfos) == NO_ERROR) {
+ if (status_t status = android::AudioSystem::getMmapPolicyInfo(
+ AudioMMapPolicyType::EXCLUSIVE, &policyInfos); status == NO_ERROR) {
mmapExclusivePolicy = AAudio_getAAudioPolicy(
policyInfos, AAUDIO_MMAP_EXCLUSIVE_POLICY_DEFAULT_AIDL);
+ ALOGD("%s, system mmap exclusive policy is %d", __func__, mmapExclusivePolicy);
+ } else {
+ ALOGD("%s, failed to query mmap exclusive policy, error=%d", __func__, status);
}
if (mmapExclusivePolicy == AAUDIO_UNSPECIFIED) {
mmapExclusivePolicy = AAUDIO_MMAP_EXCLUSIVE_POLICY_DEFAULT;
}
+ ALOGD("%s, final mmap exclusive policy is %d", __func__, mmapExclusivePolicy);
aaudio_sharing_mode_t sharingMode = getSharingMode();
if ((sharingMode == AAUDIO_SHARING_MODE_EXCLUSIVE)
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 7f5a165..5b954f7 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -79,6 +79,17 @@
return NO_ERROR;
}
+status_t AudioRecord::logIfErrorAndReturnStatus(status_t status, const std::string& errorMessage,
+ const std::string& func) {
+ if (status != NO_ERROR) {
+ if (!func.empty()) mMediaMetrics.markError(status, func.c_str());
+ ALOGE_IF(!errorMessage.empty(), "%s", errorMessage.c_str());
+ reportError(status, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE, errorMessage.c_str());
+ }
+ mStatus = status;
+ return mStatus;
+}
+
// ---------------------------------------------------------------------------
void AudioRecord::MediaMetrics::gather(const AudioRecord *record)
@@ -246,13 +257,28 @@
if (pid == -1 || (callingPid != myPid)) {
adjPid = callingPid;
}
- mClientAttributionSource.pid = VALUE_OR_FATAL(legacy2aidl_pid_t_int32_t(adjPid));
-
+ auto clientAttributionSourcePid = legacy2aidl_pid_t_int32_t(adjPid);
+ if (!clientAttributionSourcePid.ok()) {
+ return logIfErrorAndReturnStatus(BAD_VALUE,
+ StringPrintf("%s: received invalid client attribution "
+ "source pid, pid: %d, sessionId: %d",
+ __func__, pid, sessionId),
+ __func__);
+ }
+ mClientAttributionSource.pid = clientAttributionSourcePid.value();
uid_t adjUid = uid;
if (uid == -1 || (callingPid != myPid)) {
adjUid = IPCThreadState::self()->getCallingUid();
}
- mClientAttributionSource.uid = VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(adjUid));
+ auto clientAttributionSourceUid = legacy2aidl_uid_t_int32_t(adjUid);
+ if (!clientAttributionSourceUid.ok()) {
+ return logIfErrorAndReturnStatus(BAD_VALUE,
+ StringPrintf("%s: received invalid client attribution "
+ "source uid, pid: %d, session id: %d",
+ __func__, pid, sessionId),
+ __func__);
+ }
+ mClientAttributionSource.uid = clientAttributionSourceUid.value();
mTracker.reset(new RecordingActivityTracker());
@@ -268,7 +294,6 @@
mSelectedMicFieldDimension = microphoneFieldDimension;
mMaxSharedAudioHistoryMs = maxSharedAudioHistoryMs;
- std::string errorMessage;
// Copy the state variables early so they are available for error reporting.
if (pAttributes == nullptr) {
mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
@@ -311,38 +336,48 @@
break;
case TRANSFER_CALLBACK:
if (callback == nullptr) {
- errorMessage = StringPrintf(
- "%s: Transfer type TRANSFER_CALLBACK but callback == nullptr", __func__);
- status = BAD_VALUE;
- goto error;
+ return logIfErrorAndReturnStatus(
+ BAD_VALUE,
+ StringPrintf("%s: Transfer type TRANSFER_CALLBACK but callback == nullptr, "
+ "pid: %d, session id: %d",
+ __func__, pid, sessionId),
+ __func__);
}
break;
case TRANSFER_OBTAIN:
case TRANSFER_SYNC:
break;
default:
- errorMessage = StringPrintf("%s: Invalid transfer type %d", __func__, mTransfer);
- status = BAD_VALUE;
- goto error;
+ return logIfErrorAndReturnStatus(
+ BAD_VALUE,
+ StringPrintf("%s: Invalid transfer type %d, pid: %d, session id: %d", __func__,
+ mTransfer, pid, sessionId),
+ __func__);
}
// invariant that mAudioRecord != 0 is true only after set() returns successfully
if (mAudioRecord != 0) {
- errorMessage = StringPrintf("%s: Track already in use", __func__);
- status = INVALID_OPERATION;
- goto error;
+ return logIfErrorAndReturnStatus(
+ INVALID_OPERATION,
+ StringPrintf("%s: Track already in use, pid: %d, session id: %d", __func__, pid,
+ sessionId),
+ __func__);
}
if (!audio_is_valid_format(mFormat)) {
- errorMessage = StringPrintf("%s: Format %#x is not valid", __func__, mFormat);
- status = BAD_VALUE;
- goto error;
+ return logIfErrorAndReturnStatus(
+ BAD_VALUE,
+ StringPrintf("%s: Format %#x is not valid, pid: %d, session id: %d", __func__,
+ mFormat, pid, sessionId),
+ __func__);
}
if (!audio_is_input_channel(mChannelMask)) {
- errorMessage = StringPrintf("%s: Invalid channel mask %#x", __func__, mChannelMask);
- status = BAD_VALUE;
- goto error;
+ return logIfErrorAndReturnStatus(
+ BAD_VALUE,
+ StringPrintf("%s: Invalid channel mask %#x, pid: %d, session id: %d", __func__,
+ mChannelMask, pid, sessionId),
+ __func__);
}
mChannelCount = audio_channel_count_from_in_mask(mChannelMask);
@@ -376,7 +411,8 @@
mAudioRecordThread.clear();
}
// bypass error message to avoid logging twice (createRecord_l logs the error).
- goto exit;
+ mStatus = status;
+ return mStatus;
}
// TODO: add audio hardware input latency here
@@ -392,15 +428,7 @@
mFramesRead = 0;
mFramesReadServerOffset = 0;
-error:
- if (status != NO_ERROR) {
- mMediaMetrics.markError(status, __FUNCTION__);
- ALOGE_IF(!errorMessage.empty(), "%s", errorMessage.c_str());
- reportError(status, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE, errorMessage.c_str());
- }
-exit:
- mStatus = status;
- return status;
+ return logIfErrorAndReturnStatus(status, "", __func__);
}
// -------------------------------------------------------------------------
@@ -801,12 +829,10 @@
status_t status;
static const int32_t kMaxCreateAttempts = 3;
int32_t remainingAttempts = kMaxCreateAttempts;
- std::string errorMessage;
if (audioFlinger == 0) {
- errorMessage = StringPrintf("%s(%d): Could not get audioflinger", __func__, mPortId);
- status = NO_INIT;
- goto exit;
+ return logIfErrorAndReturnStatus(
+ NO_INIT, StringPrintf("%s(%d): Could not get audioflinger", __func__, mPortId), "");
}
// mFlags (not mOrigFlags) is modified depending on whether fast request is accepted.
@@ -864,16 +890,34 @@
do {
media::CreateRecordResponse response;
- status = audioFlinger->createRecord(VALUE_OR_FATAL(input.toAidl()), response);
- output = VALUE_OR_FATAL(IAudioFlinger::CreateRecordOutput::fromAidl(response));
+ auto aidlInput = input.toAidl();
+ if (!aidlInput.ok()) {
+ return logIfErrorAndReturnStatus(
+ BAD_VALUE,
+ StringPrintf("%s(%d): Could not create record due to invalid input", __func__,
+ mPortId),
+ "");
+ }
+ status = audioFlinger->createRecord(aidlInput.value(), response);
+
+ auto recordOutput = IAudioFlinger::CreateRecordOutput::fromAidl(response);
+ if (!recordOutput.ok()) {
+ return logIfErrorAndReturnStatus(
+ BAD_VALUE,
+ StringPrintf("%s(%d): Could not create record output due to invalid response",
+ __func__, mPortId),
+ "");
+ }
+ output = recordOutput.value();
if (status == NO_ERROR) {
break;
}
if (status != FAILED_TRANSACTION || --remainingAttempts <= 0) {
- errorMessage = StringPrintf(
- "%s(%d): AudioFlinger could not create record track, status: %d",
- __func__, mPortId, status);
- goto exit;
+ return logIfErrorAndReturnStatus(
+ status,
+ StringPrintf("%s(%d): AudioFlinger could not create record track, status: %d",
+ __func__, mPortId, status),
+ "");
}
// FAILED_TRANSACTION happens under very specific conditions causing a state mismatch
// between audio policy manager and audio flinger during the input stream open sequence
@@ -908,9 +952,9 @@
mHalFormat = output.halConfig.format;
if (output.cblk == 0) {
- errorMessage = StringPrintf("%s(%d): Could not get control block", __func__, mPortId);
- status = NO_INIT;
- goto exit;
+ return logIfErrorAndReturnStatus(
+ NO_INIT, StringPrintf("%s(%d): Could not get control block", __func__, mPortId),
+ "");
}
// TODO: Using unsecurePointer() has some associated security pitfalls
// (see declaration for details).
@@ -918,10 +962,9 @@
// issue (e.g. by copying).
iMemPointer = output.cblk ->unsecurePointer();
if (iMemPointer == NULL) {
- errorMessage = StringPrintf(
- "%s(%d): Could not get control block pointer", __func__, mPortId);
- status = NO_INIT;
- goto exit;
+ return logIfErrorAndReturnStatus(
+ NO_INIT,
+ StringPrintf("%s(%d): Could not get control block pointer", __func__, mPortId), "");
}
cblk = static_cast<audio_track_cblk_t*>(iMemPointer);
@@ -938,10 +981,9 @@
// issue (e.g. by copying).
buffers = output.buffers->unsecurePointer();
if (buffers == NULL) {
- errorMessage = StringPrintf(
- "%s(%d): Could not get buffer pointer", __func__, mPortId);
- status = NO_INIT;
- goto exit;
+ return logIfErrorAndReturnStatus(
+ NO_INIT,
+ StringPrintf("%s(%d): Could not get buffer pointer", __func__, mPortId), "");
}
}
@@ -1033,15 +1075,8 @@
.set(AMEDIAMETRICS_PROP_SELECTEDMICFIELDDIRECTION, (double)mSelectedMicFieldDimension)
.record();
-exit:
- if (status != NO_ERROR) {
- ALOGE_IF(!errorMessage.empty(), "%s", errorMessage.c_str());
- reportError(status, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE, errorMessage.c_str());
- }
-
- mStatus = status;
// sp<IAudioTrack> track destructor will cause releaseOutput() to be called by AudioFlinger
- return status;
+ return logIfErrorAndReturnStatus(status, "", "");
}
// Report error associated with the event and some configuration details.
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 3602e94..55f74e1 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -322,6 +322,18 @@
return NO_ERROR;
}
+status_t AudioSystem::setPortsVolume(
+ const std::vector<audio_port_handle_t>& portIds, float volume, audio_io_handle_t output) {
+ const sp<IAudioFlinger> af = get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ std::vector<int32_t> portIdsAidl = VALUE_OR_RETURN_STATUS(
+ convertContainer<std::vector<int32_t>>(
+ portIds, legacy2aidl_audio_port_handle_t_int32_t));
+ int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
+ af->setPortsVolume(portIdsAidl, volume, outputAidl);
+ return NO_ERROR;
+}
+
status_t AudioSystem::setMode(audio_mode_t mode) {
if (uint32_t(mode) >= AUDIO_MODE_CNT) return BAD_VALUE;
const sp<IAudioFlinger> af = get_audio_flinger();
@@ -1081,7 +1093,8 @@
audio_port_handle_t* portId,
std::vector<audio_io_handle_t>* secondaryOutputs,
bool *isSpatialized,
- bool *isBitPerfect) {
+ bool *isBitPerfect,
+ float *volume) {
if (attr == nullptr) {
ALOGE("%s NULL audio attributes", __func__);
return BAD_VALUE;
@@ -1147,6 +1160,7 @@
*isBitPerfect = responseAidl.isBitPerfect;
*attr = VALUE_OR_RETURN_STATUS(
aidl2legacy_AudioAttributes_audio_attributes_t(responseAidl.attr));
+ *volume = responseAidl.volume;
return OK;
}
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 336af36..d7c0b5b 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -188,6 +188,14 @@
return result.value_or(false);
}
+status_t AudioTrack::logIfErrorAndReturnStatus(status_t status, const std::string& errorMessage) {
+ if (status != NO_ERROR) {
+ ALOGE_IF(!errorMessage.empty(), "%s", errorMessage.c_str());
+ reportError(status, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE, errorMessage.c_str());
+ }
+ mStatus = status;
+ return mStatus;
+}
// ---------------------------------------------------------------------------
void AudioTrack::MediaMetrics::gather(const AudioTrack *track)
@@ -365,6 +373,10 @@
mSessionId, IPCThreadState::self()->getCallingPid(), clientPid);
AudioSystem::releaseAudioSessionId(mSessionId, clientPid);
}
+
+ if (mOutput != AUDIO_IO_HANDLE_NONE) {
+ AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId);
+ }
}
void AudioTrack::stopAndJoinCallbacks() {
@@ -413,9 +425,16 @@
uint32_t channelCount;
pid_t callingPid;
pid_t myPid;
- uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
- pid_t pid = VALUE_OR_FATAL(aidl2legacy_int32_t_pid_t(attributionSource.pid));
- std::string errorMessage;
+ auto uid = aidl2legacy_int32_t_uid_t(attributionSource.uid);
+ auto pid = aidl2legacy_int32_t_pid_t(attributionSource.pid);
+ if (!uid.ok()) {
+ return logIfErrorAndReturnStatus(
+ BAD_VALUE, StringPrintf("%s: received invalid attribution source uid", __func__));
+ }
+ if (!pid.ok()) {
+ return logIfErrorAndReturnStatus(
+ BAD_VALUE, StringPrintf("%s: received invalid attribution source pid", __func__));
+ }
// Note mPortId is not valid until the track is created, so omit mPortId in ALOG for set.
ALOGV("%s(): streamType %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
"flags %#x, notificationFrames %d, sessionId %d, transferType %d, uid %d, pid %d",
@@ -486,34 +505,33 @@
case TRANSFER_CALLBACK:
case TRANSFER_SYNC_NOTIF_CALLBACK:
if (callback == nullptr || sharedBuffer != 0) {
- errorMessage = StringPrintf(
- "%s: Transfer type %s but callback == nullptr || sharedBuffer != 0",
- convertTransferToText(transferType), __func__);
- status = BAD_VALUE;
- goto error;
+ return logIfErrorAndReturnStatus(
+ BAD_VALUE,
+ StringPrintf(
+ "%s: Transfer type %s but callback == nullptr || sharedBuffer != 0",
+ convertTransferToText(transferType), __func__));
}
break;
case TRANSFER_OBTAIN:
case TRANSFER_SYNC:
if (sharedBuffer != 0) {
- errorMessage = StringPrintf(
- "%s: Transfer type TRANSFER_OBTAIN but sharedBuffer != 0", __func__);
- status = BAD_VALUE;
- goto error;
+ return logIfErrorAndReturnStatus(
+ BAD_VALUE,
+ StringPrintf("%s: Transfer type TRANSFER_OBTAIN but sharedBuffer != 0",
+ __func__));
}
break;
case TRANSFER_SHARED:
if (sharedBuffer == 0) {
- errorMessage = StringPrintf(
- "%s: Transfer type TRANSFER_SHARED but sharedBuffer == 0", __func__);
- status = BAD_VALUE;
- goto error;
+ return logIfErrorAndReturnStatus(
+ BAD_VALUE,
+ StringPrintf("%s: Transfer type TRANSFER_SHARED but sharedBuffer == 0",
+ __func__));
}
break;
default:
- errorMessage = StringPrintf("%s: Invalid transfer type %d", __func__, transferType);
- status = BAD_VALUE;
- goto error;
+ return logIfErrorAndReturnStatus(
+ BAD_VALUE, StringPrintf("%s: Invalid transfer type %d", __func__, transferType));
}
mSharedBuffer = sharedBuffer;
mTransfer = transferType;
@@ -524,9 +542,8 @@
// invariant that mAudioTrack != 0 is true only after set() returns successfully
if (mAudioTrack != 0) {
- errorMessage = StringPrintf("%s: Track already in use", __func__);
- status = INVALID_OPERATION;
- goto error;
+ return logIfErrorAndReturnStatus(INVALID_OPERATION,
+ StringPrintf("%s: Track already in use", __func__));
}
// handle default values first.
@@ -535,9 +552,8 @@
}
if (pAttributes == NULL) {
if (uint32_t(streamType) >= AUDIO_STREAM_PUBLIC_CNT) {
- errorMessage = StringPrintf("%s: Invalid stream type %d", __func__, streamType);
- status = BAD_VALUE;
- goto error;
+ return logIfErrorAndReturnStatus(
+ BAD_VALUE, StringPrintf("%s: Invalid stream type %d", __func__, streamType));
}
mOriginalStreamType = streamType;
} else {
@@ -546,15 +562,13 @@
// validate parameters
if (!audio_is_valid_format(format)) {
- errorMessage = StringPrintf("%s: Invalid format %#x", __func__, format);
- status = BAD_VALUE;
- goto error;
+ return logIfErrorAndReturnStatus(BAD_VALUE,
+ StringPrintf("%s: Invalid format %#x", __func__, format));
}
if (!audio_is_output_channel(channelMask)) {
- errorMessage = StringPrintf("%s: Invalid channel mask %#x", __func__, channelMask);
- status = BAD_VALUE;
- goto error;
+ return logIfErrorAndReturnStatus(
+ BAD_VALUE, StringPrintf("%s: Invalid channel mask %#x", __func__, channelMask));
}
channelCount = audio_channel_count_from_out_mask(channelMask);
mChannelCount = channelCount;
@@ -569,10 +583,9 @@
// sampling rate must be specified for direct outputs
if (sampleRate == 0 && (mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
- errorMessage = StringPrintf(
- "%s: sample rate must be specified for direct outputs", __func__);
- status = BAD_VALUE;
- goto error;
+ return logIfErrorAndReturnStatus(
+ BAD_VALUE,
+ StringPrintf("%s: sample rate must be specified for direct outputs", __func__));
}
// 1.0 <= mMaxRequiredSpeed <= AUDIO_TIMESTRETCH_SPEED_MAX
mMaxRequiredSpeed = min(max(maxRequiredSpeed, 1.0f), AUDIO_TIMESTRETCH_SPEED_MAX);
@@ -600,17 +613,16 @@
mNotificationsPerBufferReq = 0;
} else {
if (!(mFlags & AUDIO_OUTPUT_FLAG_FAST)) {
- errorMessage = StringPrintf(
- "%s: notificationFrames=%d not permitted for non-fast track",
- __func__, notificationFrames);
- status = BAD_VALUE;
- goto error;
+ return logIfErrorAndReturnStatus(
+ BAD_VALUE,
+ StringPrintf("%s: notificationFrames=%d not permitted for non-fast track",
+ __func__, notificationFrames));
}
if (frameCount > 0) {
- ALOGE("%s(): notificationFrames=%d not permitted with non-zero frameCount=%zu",
- __func__, notificationFrames, frameCount);
- status = BAD_VALUE;
- goto error;
+ return logIfErrorAndReturnStatus(
+ BAD_VALUE, StringPrintf("%s(): notificationFrames=%d not permitted "
+ "with non-zero frameCount=%zu",
+ __func__, notificationFrames, frameCount));
}
mNotificationFramesReq = 0;
const uint32_t minNotificationsPerBuffer = 1;
@@ -627,12 +639,24 @@
mClientAttributionSource = AttributionSourceState(attributionSource);
callingPid = IPCThreadState::self()->getCallingPid();
myPid = getpid();
- if (uid == -1 || (callingPid != myPid)) {
- mClientAttributionSource.uid = VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(
- IPCThreadState::self()->getCallingUid()));
+ if (uid.value() == -1 || (callingPid != myPid)) {
+ auto clientAttributionSourceUid =
+ legacy2aidl_uid_t_int32_t(IPCThreadState::self()->getCallingUid());
+ if (!clientAttributionSourceUid.ok()) {
+ return logIfErrorAndReturnStatus(
+ BAD_VALUE,
+ StringPrintf("%s: received invalid client attribution source uid", __func__));
+ }
+ mClientAttributionSource.uid = clientAttributionSourceUid.value();
}
- if (pid == (pid_t)-1 || (callingPid != myPid)) {
- mClientAttributionSource.pid = VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(callingPid));
+ if (pid.value() == (pid_t)-1 || (callingPid != myPid)) {
+ auto clientAttributionSourcePid = legacy2aidl_uid_t_int32_t(callingPid);
+ if (!clientAttributionSourcePid.ok()) {
+ return logIfErrorAndReturnStatus(
+ BAD_VALUE,
+ StringPrintf("%s: received invalid client attribution source pid", __func__));
+ }
+ mClientAttributionSource.pid = clientAttributionSourcePid.value();
}
mAuxEffectId = 0;
mCallback = callback;
@@ -655,7 +679,8 @@
mAudioTrackThread.clear();
}
// We do not goto error to prevent double-logging errors.
- goto exit;
+ mStatus = status;
+ return mStatus;
}
mLoopCount = 0;
@@ -670,7 +695,7 @@
mReleased = 0;
mStartNs = 0;
mStartFromZeroUs = 0;
- AudioSystem::acquireAudioSessionId(mSessionId, pid, uid);
+ AudioSystem::acquireAudioSessionId(mSessionId, pid.value(), uid.value());
mSequence = 1;
mObservedSequence = mSequence;
mInUnderrun = false;
@@ -688,15 +713,7 @@
mFramesWrittenAtRestore = -1; // -1 is a unique initializer.
mVolumeHandler = new media::VolumeHandler();
-error:
- if (status != NO_ERROR) {
- ALOGE_IF(!errorMessage.empty(), "%s", errorMessage.c_str());
- reportError(status, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE, errorMessage.c_str());
- }
- // fall through
-exit:
- mStatus = status;
- return status;
+ return logIfErrorAndReturnStatus(status, "");
}
@@ -723,8 +740,22 @@
audio_port_handle_t selectedDeviceId)
{
AttributionSourceState attributionSource;
- attributionSource.uid = VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(uid));
- attributionSource.pid = VALUE_OR_FATAL(legacy2aidl_pid_t_int32_t(pid));
+ auto attributionSourceUid = legacy2aidl_uid_t_int32_t(uid);
+ if (!attributionSourceUid.ok()) {
+ return logIfErrorAndReturnStatus(
+ BAD_VALUE,
+ StringPrintf("%s: received invalid attribution source uid, uid: %d, session id: %d",
+ __func__, uid, sessionId));
+ }
+ attributionSource.uid = attributionSourceUid.value();
+ auto attributionSourcePid = legacy2aidl_pid_t_int32_t(pid);
+ if (!attributionSourcePid.ok()) {
+ return logIfErrorAndReturnStatus(
+ BAD_VALUE,
+ StringPrintf("%s: received invalid attribution source pid, pid: %d, sessionId: %d",
+ __func__, pid, sessionId));
+ }
+ attributionSource.pid = attributionSourcePid.value();
attributionSource.token = sp<BBinder>::make();
if (callback) {
mLegacyCallbackWrapper = sp<LegacyCallbackWrapper>::make(callback, user);
@@ -1804,15 +1835,11 @@
status_t AudioTrack::createTrack_l()
{
status_t status;
- bool callbackAdded = false;
- std::string errorMessage;
const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
if (audioFlinger == 0) {
- errorMessage = StringPrintf("%s(%d): Could not get audioflinger",
- __func__, mPortId);
- status = DEAD_OBJECT;
- goto exit;
+ return logIfErrorAndReturnStatus(
+ DEAD_OBJECT, StringPrintf("%s(%d): Could not get audioflinger", __func__, mPortId));
}
{
@@ -1880,21 +1907,31 @@
input.audioTrackCallback = mAudioTrackCallback;
media::CreateTrackResponse response;
- status = audioFlinger->createTrack(VALUE_OR_FATAL(input.toAidl()), response);
+ auto aidlInput = input.toAidl();
+ if (!aidlInput.ok()) {
+ return logIfErrorAndReturnStatus(
+ BAD_VALUE, StringPrintf("%s(%d): Could not create track due to invalid input",
+ __func__, mPortId));
+ }
+ status = audioFlinger->createTrack(aidlInput.value(), response);
IAudioFlinger::CreateTrackOutput output{};
if (status == NO_ERROR) {
- output = VALUE_OR_FATAL(IAudioFlinger::CreateTrackOutput::fromAidl(response));
+ auto trackOutput = IAudioFlinger::CreateTrackOutput::fromAidl(response);
+ if (!trackOutput.ok()) {
+ return logIfErrorAndReturnStatus(
+ BAD_VALUE,
+ StringPrintf("%s(%d): Could not create track output due to invalid response",
+ __func__, mPortId));
+ }
+ output = trackOutput.value();
}
if (status != NO_ERROR || output.outputId == AUDIO_IO_HANDLE_NONE) {
- errorMessage = StringPrintf(
- "%s(%d): AudioFlinger could not create track, status: %d output %d",
- __func__, mPortId, status, output.outputId);
- if (status == NO_ERROR) {
- status = INVALID_OPERATION; // device not ready
- }
- goto exit;
+ return logIfErrorAndReturnStatus(
+ status == NO_ERROR ? INVALID_OPERATION : status, // device not ready
+ StringPrintf("%s(%d): AudioFlinger could not create track, status: %d output %d",
+ __func__, mPortId, status, output.outputId));
}
ALOG_ASSERT(output.audioTrack != 0);
@@ -1924,22 +1961,22 @@
// FIXME compare to AudioRecord
std::optional<media::SharedFileRegion> sfr;
output.audioTrack->getCblk(&sfr);
- sp<IMemory> iMem = VALUE_OR_FATAL(aidl2legacy_NullableSharedFileRegion_IMemory(sfr));
- if (iMem == 0) {
- errorMessage = StringPrintf("%s(%d): Could not get control block", __func__, mPortId);
- status = FAILED_TRANSACTION;
- goto exit;
+ auto iMemory = aidl2legacy_NullableSharedFileRegion_IMemory(sfr);
+ if (!iMemory.ok() || iMemory.value() == 0) {
+ return logIfErrorAndReturnStatus(
+ FAILED_TRANSACTION,
+ StringPrintf("%s(%d): Could not get control block", __func__, mPortId));
}
+ sp<IMemory> iMem = iMemory.value();
// TODO: Using unsecurePointer() has some associated security pitfalls
// (see declaration for details).
// Either document why it is safe in this case or address the
// issue (e.g. by copying).
void *iMemPointer = iMem->unsecurePointer();
if (iMemPointer == NULL) {
- errorMessage = StringPrintf(
- "%s(%d): Could not get control block pointer", __func__, mPortId);
- status = FAILED_TRANSACTION;
- goto exit;
+ return logIfErrorAndReturnStatus(
+ FAILED_TRANSACTION,
+ StringPrintf("%s(%d): Could not get control block pointer", __func__, mPortId));
}
// invariant that mAudioTrack != 0 is true only after set() returns successfully
if (mAudioTrack != 0) {
@@ -1974,7 +2011,6 @@
AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId);
}
AudioSystem::addAudioDeviceCallback(this, output.outputId, output.portId);
- callbackAdded = true;
}
mPortId = output.portId;
@@ -1999,11 +2035,9 @@
// issue (e.g. by copying).
buffers = mSharedBuffer->unsecurePointer();
if (buffers == NULL) {
- errorMessage = StringPrintf(
- "%s(%d): Could not get buffer pointer", __func__, mPortId);
- ALOGE("%s", errorMessage.c_str());
- status = FAILED_TRANSACTION;
- goto exit;
+ return logIfErrorAndReturnStatus(
+ FAILED_TRANSACTION,
+ StringPrintf("%s(%d): Could not get buffer pointer", __func__, mPortId));
}
}
@@ -2100,19 +2134,8 @@
}
-exit:
- if (status != NO_ERROR) {
- if (callbackAdded) {
- // note: mOutput is always valid is callbackAdded is true
- AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId);
- }
- ALOGE_IF(!errorMessage.empty(), "%s", errorMessage.c_str());
- reportError(status, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE, errorMessage.c_str());
- }
- mStatus = status;
-
// sp<IAudioTrack> track destructor will cause releaseOutput() to be called by AudioFlinger
- return status;
+ return logIfErrorAndReturnStatus(status, "");
}
void AudioTrack::reportError(status_t status, const char *event, const char *message) const
@@ -3203,7 +3226,12 @@
media::AudioTimestampInternal ts;
mAudioTrack->getTimestamp(&ts, &status);
if (status == OK) {
- timestamp = VALUE_OR_FATAL(aidl2legacy_AudioTimestampInternal_AudioTimestamp(ts));
+ auto legacyTs = aidl2legacy_AudioTimestampInternal_AudioTimestamp(ts);
+ if (!legacyTs.ok()) {
+ return logIfErrorAndReturnStatus(
+ BAD_VALUE, StringPrintf("%s: received invalid audio timestamp", __func__));
+ }
+ timestamp = legacyTs.value();
}
} else {
// read timestamp from shared memory
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index e0dca2d..9241973 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -350,6 +350,15 @@
return statusTFromBinderStatus(mDelegate->setStreamMute(streamAidl, muted));
}
+status_t AudioFlingerClientAdapter::setPortsVolume(
+ const std::vector<audio_port_handle_t>& portIds, float volume, audio_io_handle_t output) {
+ std::vector<int32_t> portIdsAidl = VALUE_OR_RETURN_STATUS(
+ convertContainer<std::vector<int32_t>>(
+ portIds, legacy2aidl_audio_port_handle_t_int32_t));
+ int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
+ return statusTFromBinderStatus(mDelegate->setPortsVolume(portIdsAidl, volume, outputAidl));
+}
+
status_t AudioFlingerClientAdapter::setMode(audio_mode_t mode) {
AudioMode modeAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_mode_t_AudioMode(mode));
return statusTFromBinderStatus(mDelegate->setMode(modeAidl));
@@ -1012,6 +1021,16 @@
return Status::fromStatusT(mDelegate->setStreamMute(streamLegacy, muted));
}
+Status AudioFlingerServerAdapter::setPortsVolume(
+ const std::vector<int32_t>& portIds, float volume, int32_t output) {
+ std::vector<audio_port_handle_t> portIdsLegacy = VALUE_OR_RETURN_BINDER(
+ convertContainer<std::vector<audio_port_handle_t>>(
+ portIds, aidl2legacy_int32_t_audio_port_handle_t));
+ audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
+ aidl2legacy_int32_t_audio_io_handle_t(output));
+ return Status::fromStatusT(mDelegate->setPortsVolume(portIdsLegacy, volume, outputLegacy));
+}
+
Status AudioFlingerServerAdapter::setMode(AudioMode mode) {
audio_mode_t modeLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_AudioMode_audio_mode_t(mode));
return Status::fromStatusT(mDelegate->setMode(modeLegacy));
diff --git a/media/libaudioclient/aidl/android/media/GetOutputForAttrResponse.aidl b/media/libaudioclient/aidl/android/media/GetOutputForAttrResponse.aidl
index b814b85..4b26d5b 100644
--- a/media/libaudioclient/aidl/android/media/GetOutputForAttrResponse.aidl
+++ b/media/libaudioclient/aidl/android/media/GetOutputForAttrResponse.aidl
@@ -39,4 +39,6 @@
boolean isBitPerfect;
/** The corrected audio attributes. **/
AudioAttributes attr;
+ /** initial port volume for the new audio track */
+ float volume;
}
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
index 29de9c2..1c825bc 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -100,6 +100,13 @@
void setStreamVolume(AudioStreamType stream, float value, int /* audio_io_handle_t */ output);
void setStreamMute(AudioStreamType stream, boolean muted);
+ /*
+ * Set AudioTrack port ids volume attribute. This is the new way of controlling volume from
+ * AudioPolicyManager to AudioFlinger.
+ */
+ void setPortsVolume(in int[] /* audio_port_handle_t[] */ portIds, float volume,
+ int /* audio_io_handle_t */ output);
+
// set audio mode.
void setMode(AudioMode mode);
diff --git a/media/libaudioclient/aidl/fuzzer/corpus/seed-2024-08-29-0 b/media/libaudioclient/aidl/fuzzer/corpus/seed-2024-08-29-0
new file mode 100644
index 0000000..c1e1de5
--- /dev/null
+++ b/media/libaudioclient/aidl/fuzzer/corpus/seed-2024-08-29-0
Binary files differ
diff --git a/media/libaudioclient/aidl/fuzzer/corpus/seed-2024-08-29-1 b/media/libaudioclient/aidl/fuzzer/corpus/seed-2024-08-29-1
new file mode 100644
index 0000000..8e49acd
--- /dev/null
+++ b/media/libaudioclient/aidl/fuzzer/corpus/seed-2024-08-29-1
Binary files differ
diff --git a/media/libaudioclient/aidl/fuzzer/corpus/seed-2024-08-29-2 b/media/libaudioclient/aidl/fuzzer/corpus/seed-2024-08-29-2
new file mode 100644
index 0000000..a8ffcae
--- /dev/null
+++ b/media/libaudioclient/aidl/fuzzer/corpus/seed-2024-08-29-2
Binary files differ
diff --git a/media/libaudioclient/aidl/fuzzer/corpus/seed-2024-08-29-3 b/media/libaudioclient/aidl/fuzzer/corpus/seed-2024-08-29-3
new file mode 100644
index 0000000..7c25f6e
--- /dev/null
+++ b/media/libaudioclient/aidl/fuzzer/corpus/seed-2024-08-29-3
Binary files differ
diff --git a/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp b/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp
index 4c94974..710a656 100644
--- a/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp
+++ b/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp
@@ -26,6 +26,7 @@
#include <android/content/AttributionSourceState.h>
#include <binder/IServiceManager.h>
#include <binder/MemoryDealer.h>
+#include <com_android_media_audioserver.h>
#include <media/AidlConversion.h>
#include <media/AudioEffect.h>
#include <media/AudioRecord.h>
@@ -41,6 +42,8 @@
constexpr int32_t kMaxSampleRateHz = 192000;
constexpr int32_t kSampleRateUnspecified = 0;
+namespace audioserver_flags = com::android::media::audioserver;
+
using namespace std;
using namespace android;
@@ -501,13 +504,19 @@
AudioSystem::getMasterMute(&state);
AudioSystem::isMicrophoneMuted(&state);
- audio_stream_type_t stream = getValue(&mFdp, kStreamtypes);
- AudioSystem::setStreamMute(getValue(&mFdp, kStreamtypes), mFdp.ConsumeBool());
+ audio_stream_type_t stream ;
+ if (!audioserver_flags::portid_volume_management()) {
+ stream = getValue(&mFdp, kStreamtypes);
+ AudioSystem::setStreamMute(getValue(&mFdp, kStreamtypes), mFdp.ConsumeBool());
- stream = getValue(&mFdp, kStreamtypes);
- AudioSystem::setStreamVolume(stream, mFdp.ConsumeFloatingPoint<float>(),
- mFdp.ConsumeIntegral<int32_t>());
-
+ stream = getValue(&mFdp, kStreamtypes);
+ AudioSystem::setStreamVolume(stream, mFdp.ConsumeFloatingPoint<float>(),
+ mFdp.ConsumeIntegral<int32_t>());
+ } else {
+ std::vector <audio_port_handle_t> portsForVolumeChange{};
+ AudioSystem::setPortsVolume(portsForVolumeChange, mFdp.ConsumeFloatingPoint<float>(),
+ mFdp.ConsumeIntegral<int32_t>());
+ }
audio_mode_t mode = getValue(&mFdp, kModes);
AudioSystem::setMode(mode);
diff --git a/media/libaudioclient/include/media/AudioRecord.h b/media/libaudioclient/include/media/AudioRecord.h
index d4479ef..25d91d3 100644
--- a/media/libaudioclient/include/media/AudioRecord.h
+++ b/media/libaudioclient/include/media/AudioRecord.h
@@ -138,6 +138,12 @@
audio_format_t format,
audio_channel_mask_t channelMask);
+ /* Checks for erroneous status, marks error in MediaMetrics, logs the error message.
+ * Updates and returns mStatus.
+ */
+ status_t logIfErrorAndReturnStatus(status_t status, const std::string& errorMessage,
+ const std::string& func);
+
/* How data is transferred from AudioRecord
*/
enum transfer_type {
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 67b3dcd..40e5673 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -131,6 +131,16 @@
// mute/unmute stream
static status_t setStreamMute(audio_stream_type_t stream, bool mute);
+ /**
+ * Set volume for given AudioTrack port ids on specified output
+ * @param portIds to consider
+ * @param volume to set
+ * @param output to consider
+ * @return NO_ERROR if successful
+ */
+ static status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds,
+ float volume, audio_io_handle_t output);
+
// set audio mode in audio hardware
static status_t setMode(audio_mode_t mode);
@@ -334,7 +344,8 @@
audio_port_handle_t *portId,
std::vector<audio_io_handle_t> *secondaryOutputs,
bool *isSpatialized,
- bool *isBitPerfect);
+ bool *isBitPerfect,
+ float *volume);
static status_t startOutput(audio_port_handle_t portId);
static status_t stopOutput(audio_port_handle_t portId);
static void releaseOutput(audio_port_handle_t portId);
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index 3a001a4..de97863 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -233,8 +233,7 @@
* FIXME This API assumes a route, and so should be deprecated.
*/
- static status_t getMinFrameCount(size_t* frameCount,
- audio_stream_type_t streamType,
+ static status_t getMinFrameCount(size_t* frameCount, audio_stream_type_t streamType,
uint32_t sampleRate);
/* Check if direct playback is possible for the given audio configuration and attributes.
@@ -243,6 +242,11 @@
static bool isDirectOutputSupported(const audio_config_base_t& config,
const audio_attributes_t& attributes);
+ /* Checks for erroneous status, logs the error message.
+ * Updates and returns mStatus.
+ */
+ status_t logIfErrorAndReturnStatus(status_t status, const std::string& errorMessage);
+
/* How data is transferred to AudioTrack
*/
enum transfer_type {
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 667e9ae..a5f3217 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -229,6 +229,16 @@
audio_io_handle_t output) = 0;
virtual status_t setStreamMute(audio_stream_type_t stream, bool muted) = 0;
+ /**
+ * Set volume for given AudioTrack port ids on specified output
+ * @param portIds to consider
+ * @param volume to set
+ * @param output to consider
+ * @return NO_ERROR if successful
+ */
+ virtual status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume,
+ audio_io_handle_t output) = 0;
+
// set audio mode
virtual status_t setMode(audio_mode_t mode) = 0;
@@ -420,6 +430,8 @@
status_t setStreamVolume(audio_stream_type_t stream, float value,
audio_io_handle_t output) override;
status_t setStreamMute(audio_stream_type_t stream, bool muted) override;
+ status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume,
+ audio_io_handle_t output) override;
status_t setMode(audio_mode_t mode) override;
status_t setMicMute(bool state) override;
bool getMicMute() const override;
@@ -542,6 +554,7 @@
MASTER_MUTE = media::BnAudioFlingerService::TRANSACTION_masterMute,
SET_STREAM_VOLUME = media::BnAudioFlingerService::TRANSACTION_setStreamVolume,
SET_STREAM_MUTE = media::BnAudioFlingerService::TRANSACTION_setStreamMute,
+ SET_PORTS_VOLUME = media::BnAudioFlingerService::TRANSACTION_setPortsVolume,
SET_MODE = media::BnAudioFlingerService::TRANSACTION_setMode,
SET_MIC_MUTE = media::BnAudioFlingerService::TRANSACTION_setMicMute,
GET_MIC_MUTE = media::BnAudioFlingerService::TRANSACTION_getMicMute,
@@ -664,6 +677,8 @@
Status setStreamVolume(media::audio::common::AudioStreamType stream,
float value, int32_t output) override;
Status setStreamMute(media::audio::common::AudioStreamType stream, bool muted) override;
+ Status setPortsVolume(const std::vector<int32_t>& portIds, float volume, int32_t output)
+ override;
Status setMode(media::audio::common::AudioMode mode) override;
Status setMicMute(bool state) override;
Status getMicMute(bool* _aidl_return) override;
diff --git a/media/libmediaplayerservice/fuzzer/corpus/seed-2024-08-29-0 b/media/libmediaplayerservice/fuzzer/corpus/seed-2024-08-29-0
new file mode 100644
index 0000000..aae78ae
--- /dev/null
+++ b/media/libmediaplayerservice/fuzzer/corpus/seed-2024-08-29-0
Binary files differ
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index 46703bb..893b442 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -18,19 +18,14 @@
#define LOG_TAG "FrameDecoder"
#define ATRACE_TAG ATRACE_TAG_VIDEO
#include "include/FrameDecoder.h"
-#include "include/FrameCaptureLayer.h"
-#include "include/HevcUtils.h"
+#include <android_media_codec.h>
#include <binder/MemoryBase.h>
#include <binder/MemoryHeapBase.h>
#include <gui/Surface.h>
#include <inttypes.h>
-#include <mediadrm/ICrypto.h>
#include <media/IMediaSource.h>
#include <media/MediaCodecBuffer.h>
-#include <media/stagefright/foundation/avc_utils.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/foundation/ColorUtils.h>
+#include <media/stagefright/CodecBase.h>
#include <media/stagefright/ColorConverter.h>
#include <media/stagefright/FrameCaptureProcessor.h>
#include <media/stagefright/MediaBuffer.h>
@@ -39,13 +34,24 @@
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/Utils.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/ColorUtils.h>
+#include <media/stagefright/foundation/avc_utils.h>
+#include <mediadrm/ICrypto.h>
#include <private/media/VideoFrame.h>
#include <utils/Log.h>
#include <utils/Trace.h>
+#include "include/FrameCaptureLayer.h"
+#include "include/HevcUtils.h"
+
+#include <C2Buffer.h>
+#include <Codec2BufferUtils.h>
namespace android {
static const int64_t kBufferTimeOutUs = 10000LL; // 10 msec
+static const int64_t kAsyncBufferTimeOutUs = 2000000LL; // 2000 msec
static const size_t kRetryCount = 100; // must be >0
static const int64_t kDefaultSampleDurationUs = 33333LL; // 33ms
// For codec, 0 is the highest importance; higher the number lesser important.
@@ -232,6 +238,104 @@
return false;
}
+AsyncCodecHandler::AsyncCodecHandler(const wp<FrameDecoder>& frameDecoder) {
+ mFrameDecoder = frameDecoder;
+}
+
+void AsyncCodecHandler::onMessageReceived(const sp<AMessage>& msg) {
+ switch (msg->what()) {
+ case FrameDecoder::kWhatCallbackNotify:
+ int32_t callbackId;
+ if (!msg->findInt32("callbackID", &callbackId)) {
+ ALOGE("kWhatCallbackNotify: callbackID is expected.");
+ break;
+ }
+ switch (callbackId) {
+ case MediaCodec::CB_INPUT_AVAILABLE: {
+ int32_t index;
+ if (!msg->findInt32("index", &index)) {
+ ALOGE("CB_INPUT_AVAILABLE: index is expected.");
+ break;
+ }
+ ALOGD("CB_INPUT_AVAILABLE received, index is %d", index);
+ sp<FrameDecoder> frameDecoder = mFrameDecoder.promote();
+ if (frameDecoder != nullptr) {
+ frameDecoder->handleInputBufferAsync(index);
+ }
+ break;
+ }
+ case MediaCodec::CB_OUTPUT_AVAILABLE: {
+ int32_t index;
+ int64_t timeUs;
+ CHECK(msg->findInt32("index", &index));
+ CHECK(msg->findInt64("timeUs", &timeUs));
+ ALOGD("CB_OUTPUT_AVAILABLE received, index is %d", index);
+ sp<FrameDecoder> frameDecoder = mFrameDecoder.promote();
+ if (frameDecoder != nullptr) {
+ frameDecoder->handleOutputBufferAsync(index, timeUs);
+ }
+ break;
+ }
+ case MediaCodec::CB_OUTPUT_FORMAT_CHANGED: {
+ ALOGD("CB_OUTPUT_FORMAT_CHANGED received");
+ sp<AMessage> format;
+ if (!msg->findMessage("format", &format) || format == nullptr) {
+ ALOGE("CB_OUTPUT_FORMAT_CHANGED: format is expected.");
+ break;
+ }
+ sp<FrameDecoder> frameDecoder = mFrameDecoder.promote();
+ if (frameDecoder != nullptr) {
+ frameDecoder->handleOutputFormatChangeAsync(format);
+ }
+ break;
+ }
+ case MediaCodec::CB_ERROR: {
+ status_t err;
+ int32_t actionCode;
+ AString detail;
+ if (!msg->findInt32("err", &err)) {
+ ALOGE("CB_ERROR: err is expected.");
+ break;
+ }
+ if (!msg->findInt32("actionCode", &actionCode)) {
+ ALOGE("CB_ERROR: actionCode is expected.");
+ break;
+ }
+ msg->findString("detail", &detail);
+ ALOGE("Codec reported error(0x%x/%s), actionCode(%d), detail(%s)", err,
+ StrMediaError(err).c_str(), actionCode, detail.c_str());
+ break;
+ }
+ default:
+ ALOGE("kWhatCallbackNotify: callbackID(%d) is unexpected.", callbackId);
+ break;
+ }
+ break;
+ default:
+ ALOGE("unexpected message received: %s", msg->debugString().c_str());
+ break;
+ }
+}
+
+void InputBufferIndexQueue::enqueue(int32_t index) {
+ std::scoped_lock<std::mutex> lock(mMutex);
+ mQueue.push(index);
+ mCondition.notify_one();
+}
+
+bool InputBufferIndexQueue::dequeue(int32_t* index, int32_t timeOutUs) {
+ std::unique_lock<std::mutex> lock(mMutex);
+ bool hasAvailableIndex = mCondition.wait_for(lock, std::chrono::microseconds(timeOutUs),
+ [this] { return !mQueue.empty(); });
+ if (hasAvailableIndex) {
+ *index = mQueue.front();
+ mQueue.pop();
+ return true;
+ } else {
+ return false;
+ }
+}
+
//static
sp<IMemory> FrameDecoder::getMetadataOnly(
const sp<MetaData> &trackMeta, int colorFormat, bool thumbnail, uint32_t bitDepth) {
@@ -281,6 +385,7 @@
const sp<MetaData> &trackMeta,
const sp<IMediaSource> &source)
: mComponentName(componentName),
+ mUseBlockModel(false),
mTrackMeta(trackMeta),
mSource(source),
mDstFormat(OMX_COLOR_Format16bitRGB565),
@@ -290,6 +395,10 @@
}
FrameDecoder::~FrameDecoder() {
+ if (mHandler != NULL) {
+ mAsyncLooper->stop();
+ mAsyncLooper->unregisterHandler(mHandler->id());
+ }
if (mDecoder != NULL) {
mDecoder->release();
mSource->stop();
@@ -333,8 +442,18 @@
return (decoder.get() == NULL) ? NO_MEMORY : err;
}
+ if (mUseBlockModel) {
+ mAsyncLooper = new ALooper;
+ mAsyncLooper->start();
+ mHandler = new AsyncCodecHandler(wp<FrameDecoder>(this));
+ mAsyncLooper->registerHandler(mHandler);
+ sp<AMessage> callbackMsg = new AMessage(kWhatCallbackNotify, mHandler);
+ decoder->setCallback(callbackMsg);
+ }
+
err = decoder->configure(
- videoFormat, mSurface, NULL /* crypto */, 0 /* flags */);
+ videoFormat, mSurface, NULL /* crypto */,
+ mUseBlockModel ? MediaCodec::CONFIGURE_FLAG_USE_BLOCK_MODEL : 0 /* flags */);
if (err != OK) {
ALOGW("configure returned error %d (%s)", err, asString(err));
decoder->release();
@@ -362,10 +481,18 @@
sp<IMemory> FrameDecoder::extractFrame(FrameRect *rect) {
ScopedTrace trace(ATRACE_TAG, "FrameDecoder::ExtractFrame");
status_t err = onExtractRect(rect);
- if (err == OK) {
+ if (err != OK) {
+ ALOGE("onExtractRect error %d", err);
+ return NULL;
+ }
+
+ if (!mUseBlockModel) {
err = extractInternal();
+ } else {
+ err = extractInternalUsingBlockModel();
}
if (err != OK) {
+ ALOGE("extractInternal error %d", err);
return NULL;
}
@@ -380,6 +507,7 @@
ALOGE("decoder is not initialized");
return NO_INIT;
}
+
do {
size_t index;
int64_t ptsUs = 0LL;
@@ -433,7 +561,8 @@
(const uint8_t*)mediaBuffer->data() + mediaBuffer->range_offset(),
mediaBuffer->range_length());
- onInputReceived(codecBuffer, mediaBuffer->meta_data(), mFirstSample, &flags);
+ onInputReceived(codecBuffer->data(), codecBuffer->size(), mediaBuffer->meta_data(),
+ mFirstSample, &flags);
mFirstSample = false;
}
@@ -487,11 +616,14 @@
ALOGE("failed to get output buffer %zu", index);
break;
}
+ uint8_t* frameData = videoFrameBuffer->data();
+ sp<ABuffer> imageData;
+ videoFrameBuffer->meta()->findBuffer("image-data", &imageData);
if (mSurface != nullptr) {
mDecoder->renderOutputBufferAndRelease(index);
- err = onOutputReceived(videoFrameBuffer, mOutputFormat, ptsUs, &done);
+ err = onOutputReceived(frameData, imageData, mOutputFormat, ptsUs, &done);
} else {
- err = onOutputReceived(videoFrameBuffer, mOutputFormat, ptsUs, &done);
+ err = onOutputReceived(frameData, imageData, mOutputFormat, ptsUs, &done);
mDecoder->releaseOutputBuffer(index);
}
} else {
@@ -510,6 +642,73 @@
return err;
}
+status_t FrameDecoder::extractInternalUsingBlockModel() {
+ status_t err = OK;
+ MediaBufferBase* mediaBuffer = NULL;
+ int64_t ptsUs = 0LL;
+ uint32_t flags = 0;
+ int32_t index;
+ mHandleOutputBufferAsyncDone = false;
+
+ err = mSource->read(&mediaBuffer, &mReadOptions);
+ mReadOptions.clearSeekTo();
+ if (err != OK) {
+ ALOGW("Input Error: err=%d", err);
+ mediaBuffer->release();
+ return err;
+ }
+
+ size_t inputSize = mediaBuffer->range_length();
+ std::shared_ptr<C2LinearBlock> block =
+ MediaCodec::FetchLinearBlock(inputSize, {std::string{mComponentName.c_str()}});
+ C2WriteView view{block->map().get()};
+ if (view.error() != C2_OK) {
+ ALOGE("Fatal error: failed to allocate and map a block");
+ mediaBuffer->release();
+ return NO_MEMORY;
+ }
+ if (inputSize > view.capacity()) {
+ ALOGE("Fatal error: allocated block is too small "
+ "(input size %zu; block cap %u)",
+ inputSize, view.capacity());
+ mediaBuffer->release();
+ return BAD_VALUE;
+ }
+ CHECK(mediaBuffer->meta_data().findInt64(kKeyTime, &ptsUs));
+ memcpy(view.base(), (const uint8_t*)mediaBuffer->data() + mediaBuffer->range_offset(),
+ inputSize);
+ std::shared_ptr<C2Buffer> c2Buffer =
+ C2Buffer::CreateLinearBuffer(block->share(0, inputSize, C2Fence{}));
+ onInputReceived(view.base(), inputSize, mediaBuffer->meta_data(), true /* firstSample */,
+ &flags);
+ flags |= MediaCodec::BUFFER_FLAG_EOS;
+ mediaBuffer->release();
+
+ std::vector<AccessUnitInfo> infoVec;
+ infoVec.emplace_back(flags, inputSize, ptsUs);
+ sp<BufferInfosWrapper> infos = new BufferInfosWrapper{std::move(infoVec)};
+
+ if (!mInputBufferIndexQueue.dequeue(&index, kAsyncBufferTimeOutUs)) {
+ ALOGE("No available input buffer index for async mode.");
+ return TIMED_OUT;
+ }
+
+ AString errorDetailMsg;
+ ALOGD("QueueLinearBlock: index=%d size=%zu ts=%" PRId64 " us flags=%x",
+ index, inputSize, ptsUs,flags);
+ err = mDecoder->queueBuffer(index, c2Buffer, infos, nullptr, &errorDetailMsg);
+ if (err != OK) {
+ ALOGE("failed to queueBuffer (err %d): %s", err, errorDetailMsg.c_str());
+ return err;
+ }
+
+ // wait for handleOutputBufferAsync() to finish
+ std::unique_lock _lk(mMutex);
+ mOutputFramePending.wait_for(_lk, std::chrono::microseconds(kAsyncBufferTimeOutUs),
+ [this] { return mHandleOutputBufferAsyncDone; });
+ return mHandleOutputBufferAsyncDone ? OK : TIMED_OUT;
+}
+
//////////////////////////////////////////////////////////////////////
VideoFrameDecoder::VideoFrameDecoder(
@@ -525,6 +724,81 @@
mDefaultSampleDurationUs(0) {
}
+status_t FrameDecoder::handleOutputFormatChangeAsync(sp<AMessage> format) {
+ // Here format is MediaCodec's internal copy of output format.
+ // Make a copy since the client might modify it.
+ mOutputFormat = format->dup();
+ ALOGD("receive output format in async mode: %s", mOutputFormat->debugString().c_str());
+ return OK;
+}
+
+status_t FrameDecoder::handleInputBufferAsync(int32_t index) {
+ mInputBufferIndexQueue.enqueue(index);
+ return OK;
+}
+
+status_t FrameDecoder::handleOutputBufferAsync(int32_t index, int64_t timeUs) {
+ if (mHandleOutputBufferAsyncDone) {
+ // we have already processed an output buffer, skip others
+ return OK;
+ }
+
+ status_t err = OK;
+ sp<MediaCodecBuffer> videoFrameBuffer;
+ err = mDecoder->getOutputBuffer(index, &videoFrameBuffer);
+ if (err != OK || videoFrameBuffer == nullptr) {
+ ALOGE("failed to get output buffer %d", index);
+ return err;
+ }
+
+ bool onOutputReceivedDone = false;
+ if (mSurface != nullptr) {
+ mDecoder->renderOutputBufferAndRelease(index);
+ // frameData and imgObj will be fetched by captureSurface() inside onOutputReceived()
+ // explicitly pass null here
+ err = onOutputReceived(nullptr, nullptr, mOutputFormat, timeUs, &onOutputReceivedDone);
+ } else {
+ // get stride and frame data for block model buffer
+ std::shared_ptr<C2Buffer> c2buffer = videoFrameBuffer->asC2Buffer();
+ if (!c2buffer
+ || c2buffer->data().type() != C2BufferData::GRAPHIC
+ || c2buffer->data().graphicBlocks().size() == 0u) {
+ ALOGE("C2Buffer precond fail");
+ return ERROR_MALFORMED;
+ }
+
+ std::unique_ptr<const C2GraphicView> view(std::make_unique<const C2GraphicView>(
+ c2buffer->data().graphicBlocks()[0].map().get()));
+ GraphicView2MediaImageConverter converter(*view, mOutputFormat, false /* copy */);
+ if (converter.initCheck() != OK) {
+ ALOGE("Converter init failed: %d", converter.initCheck());
+ return NO_INIT;
+ }
+
+ uint8_t* frameData = converter.wrap()->data();
+ sp<ABuffer> imageData = converter.imageData();
+ if (imageData != nullptr) {
+ mOutputFormat->setBuffer("image-data", imageData);
+ MediaImage2 *img = (MediaImage2*) imageData->data();
+ if (img->mNumPlanes > 0 && img->mType != img->MEDIA_IMAGE_TYPE_UNKNOWN) {
+ int32_t stride = img->mPlane[0].mRowInc;
+ mOutputFormat->setInt32(KEY_STRIDE, stride);
+ ALOGD("updating stride = %d", stride);
+ }
+ }
+
+ err = onOutputReceived(frameData, imageData, mOutputFormat, timeUs, &onOutputReceivedDone);
+ mDecoder->releaseOutputBuffer(index);
+ }
+
+ if (err == OK && onOutputReceivedDone) {
+ std::lock_guard _lm(mMutex);
+ mHandleOutputBufferAsyncDone = true;
+ mOutputFramePending.notify_one();
+ }
+ return err;
+}
+
sp<AMessage> VideoFrameDecoder::onGetFormatAndSeekOptions(
int64_t frameTimeUs, int seekMode,
MediaSource::ReadOptions *options,
@@ -575,8 +849,13 @@
bool isSeekingClosest = (mSeekMode == MediaSource::ReadOptions::SEEK_CLOSEST)
|| (mSeekMode == MediaSource::ReadOptions::SEEK_FRAME_INDEX);
if (!isSeekingClosest) {
- videoFormat->setInt32("android._num-input-buffers", 1);
- videoFormat->setInt32("android._num-output-buffers", 1);
+ if (mComponentName.startsWithIgnoreCase("c2.")) {
+ mUseBlockModel = android::media::codec::provider_->thumbnail_block_model();
+ } else {
+ // OMX Codec
+ videoFormat->setInt32("android._num-input-buffers", 1);
+ videoFormat->setInt32("android._num-output-buffers", 1);
+ }
}
if (isHDR(videoFormat)) {
@@ -601,9 +880,8 @@
return videoFormat;
}
-status_t VideoFrameDecoder::onInputReceived(
- const sp<MediaCodecBuffer> &codecBuffer,
- MetaDataBase &sampleMeta, bool firstSample, uint32_t *flags) {
+status_t VideoFrameDecoder::onInputReceived(uint8_t* data, size_t size, MetaDataBase& sampleMeta,
+ bool firstSample, uint32_t* flags) {
bool isSeekingClosest = (mSeekMode == MediaSource::ReadOptions::SEEK_CLOSEST)
|| (mSeekMode == MediaSource::ReadOptions::SEEK_FRAME_INDEX);
@@ -612,10 +890,7 @@
ALOGV("Seeking closest: targetTimeUs=%lld", (long long)mTargetTimeUs);
}
- if (!isSeekingClosest
- && ((mIsAvc && IsIDR(codecBuffer->data(), codecBuffer->size()))
- || (mIsHevc && IsIDR(
- codecBuffer->data(), codecBuffer->size())))) {
+ if (!isSeekingClosest && ((mIsAvc && IsIDR(data, size)) || (mIsHevc && IsIDR(data, size)))) {
// Only need to decode one IDR frame, unless we're seeking with CLOSEST
// option, in which case we need to actually decode to targetTimeUs.
*flags |= MediaCodec::BUFFER_FLAG_EOS;
@@ -630,7 +905,8 @@
}
status_t VideoFrameDecoder::onOutputReceived(
- const sp<MediaCodecBuffer> &videoFrameBuffer,
+ uint8_t* frameData,
+ sp<ABuffer> imgObj,
const sp<AMessage> &outputFormat,
int64_t timeUs, bool *done) {
int64_t durationUs = mDefaultSampleDurationUs;
@@ -703,7 +979,6 @@
}
mFrame = static_cast<VideoFrame*>(frameMem->unsecurePointer());
-
setFrame(frameMem);
}
@@ -712,7 +987,7 @@
if (mCaptureLayer != nullptr) {
return captureSurface();
}
- ColorConverter converter((OMX_COLOR_FORMATTYPE)srcFormat, dstFormat());
+ ColorConverter colorConverter((OMX_COLOR_FORMATTYPE)srcFormat, dstFormat());
uint32_t standard, range, transfer;
if (!outputFormat->findInt32("color-standard", (int32_t*)&standard)) {
@@ -724,22 +999,25 @@
if (!outputFormat->findInt32("color-transfer", (int32_t*)&transfer)) {
transfer = 0;
}
- sp<ABuffer> imgObj;
- if (videoFrameBuffer->meta()->findBuffer("image-data", &imgObj)) {
+
+ if (imgObj != nullptr) {
MediaImage2 *imageData = nullptr;
imageData = (MediaImage2 *)(imgObj.get()->data());
if (imageData != nullptr) {
- converter.setSrcMediaImage2(*imageData);
+ colorConverter.setSrcMediaImage2(*imageData);
}
}
if (srcFormat == COLOR_FormatYUV420Flexible && imgObj.get() == nullptr) {
return ERROR_UNSUPPORTED;
}
- converter.setSrcColorSpace(standard, range, transfer);
- if (converter.isValid()) {
+ colorConverter.setSrcColorSpace(standard, range, transfer);
+ if (colorConverter.isValid()) {
ScopedTrace trace(ATRACE_TAG, "FrameDecoder::ColorConverter");
- converter.convert(
- (const uint8_t *)videoFrameBuffer->data(),
+ if (frameData == nullptr) {
+ ALOGD("frameData is null for ColorConverter");
+ }
+ colorConverter.convert(
+ (const uint8_t *)frameData,
width, height, stride,
crop_left, crop_top, crop_right, crop_bottom,
mFrame->getFlattenedData(),
@@ -955,7 +1233,8 @@
}
status_t MediaImageDecoder::onOutputReceived(
- const sp<MediaCodecBuffer> &videoFrameBuffer,
+ uint8_t* frameData,
+ sp<ABuffer> imgObj,
const sp<AMessage> &outputFormat, int64_t /*timeUs*/, bool *done) {
if (outputFormat == NULL) {
return ERROR_MALFORMED;
@@ -1008,8 +1287,8 @@
if (!outputFormat->findInt32("color-transfer", (int32_t*)&transfer)) {
transfer = 0;
}
- sp<ABuffer> imgObj;
- if (videoFrameBuffer->meta()->findBuffer("image-data", &imgObj)) {
+
+ if (imgObj != nullptr) {
MediaImage2 *imageData = nullptr;
imageData = (MediaImage2 *)(imgObj.get()->data());
if (imageData != nullptr) {
@@ -1058,7 +1337,7 @@
if (converter.isValid()) {
converter.convert(
- (const uint8_t *)videoFrameBuffer->data(),
+ (const uint8_t *)frameData,
width, height, stride,
crop_left, crop_top, crop_right, crop_bottom,
mFrame->getFlattenedData(),
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index b380ade..1422868 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -6699,8 +6699,8 @@
if (!mDetachedSurface) {
uint64_t usage = 0;
if (!mSurface || mSurface->getConsumerUsage(&usage) != OK) {
- // TODO: should we use a/the default consumer usage?
- usage = 0;
+ // By default prepare buffer to be displayed on any of the common surfaces
+ usage = (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER);
}
mDetachedSurface.reset(new ReleaseSurface(usage));
}
diff --git a/media/libstagefright/include/FrameDecoder.h b/media/libstagefright/include/FrameDecoder.h
index e417324..94c201f 100644
--- a/media/libstagefright/include/FrameDecoder.h
+++ b/media/libstagefright/include/FrameDecoder.h
@@ -18,12 +18,15 @@
#define FRAME_DECODER_H_
#include <memory>
+#include <mutex>
+#include <queue>
#include <vector>
-#include <media/stagefright/foundation/AString.h>
-#include <media/stagefright/foundation/ABase.h>
-#include <media/stagefright/MediaSource.h>
#include <media/openmax/OMX_Video.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/foundation/AString.h>
#include <ui/GraphicTypes.h>
namespace android {
@@ -34,11 +37,23 @@
class MediaCodecBuffer;
class Surface;
class VideoFrame;
+struct AsyncCodecHandler;
struct FrameRect {
int32_t left, top, right, bottom;
};
+struct InputBufferIndexQueue {
+public:
+ void enqueue(int32_t index);
+ bool dequeue(int32_t* index, int32_t timeOutUs);
+
+private:
+ std::queue<int32_t> mQueue;
+ std::mutex mMutex;
+ std::condition_variable mCondition;
+};
+
struct FrameDecoder : public RefBase {
FrameDecoder(
const AString &componentName,
@@ -53,7 +68,19 @@
const sp<MetaData> &trackMeta, int colorFormat,
bool thumbnail = false, uint32_t bitDepth = 0);
+ status_t handleInputBufferAsync(int32_t index);
+ status_t handleOutputBufferAsync(int32_t index, int64_t timeUs);
+ status_t handleOutputFormatChangeAsync(sp<AMessage> format);
+
+ enum {
+ kWhatCallbackNotify,
+ };
+
protected:
+ AString mComponentName;
+ sp<AMessage> mOutputFormat;
+ bool mUseBlockModel;
+
virtual ~FrameDecoder();
virtual sp<AMessage> onGetFormatAndSeekOptions(
@@ -64,14 +91,12 @@
virtual status_t onExtractRect(FrameRect *rect) = 0;
- virtual status_t onInputReceived(
- const sp<MediaCodecBuffer> &codecBuffer,
- MetaDataBase &sampleMeta,
- bool firstSample,
- uint32_t *flags) = 0;
+ virtual status_t onInputReceived(uint8_t* data, size_t size, MetaDataBase& sampleMeta,
+ bool firstSample, uint32_t* flags) = 0;
virtual status_t onOutputReceived(
- const sp<MediaCodecBuffer> &videoFrameBuffer,
+ uint8_t* data,
+ sp<ABuffer> imgObj,
const sp<AMessage> &outputFormat,
int64_t timeUs,
bool *done) = 0;
@@ -83,7 +108,6 @@
void setFrame(const sp<IMemory> &frameMem) { mFrameMemory = frameMem; }
private:
- AString mComponentName;
sp<MetaData> mTrackMeta;
sp<IMediaSource> mSource;
OMX_COLOR_FORMATTYPE mDstFormat;
@@ -92,17 +116,32 @@
sp<IMemory> mFrameMemory;
MediaSource::ReadOptions mReadOptions;
sp<MediaCodec> mDecoder;
- sp<AMessage> mOutputFormat;
+ sp<AsyncCodecHandler> mHandler;
+ sp<ALooper> mAsyncLooper;
bool mHaveMoreInputs;
bool mFirstSample;
+ bool mHandleOutputBufferAsyncDone;
sp<Surface> mSurface;
+ std::mutex mMutex;
+ std::condition_variable mOutputFramePending;
+ InputBufferIndexQueue mInputBufferIndexQueue;
status_t extractInternal();
+ status_t extractInternalUsingBlockModel();
DISALLOW_EVIL_CONSTRUCTORS(FrameDecoder);
};
struct FrameCaptureLayer;
+struct AsyncCodecHandler : public AHandler {
+public:
+ explicit AsyncCodecHandler(const wp<FrameDecoder>& frameDecoder);
+ virtual void onMessageReceived(const sp<AMessage>& msg);
+
+private:
+ wp<FrameDecoder> mFrameDecoder;
+};
+
struct VideoFrameDecoder : public FrameDecoder {
VideoFrameDecoder(
const AString &componentName,
@@ -121,14 +160,12 @@
return (rect == NULL) ? OK : ERROR_UNSUPPORTED;
}
- virtual status_t onInputReceived(
- const sp<MediaCodecBuffer> &codecBuffer,
- MetaDataBase &sampleMeta,
- bool firstSample,
- uint32_t *flags) override;
+ virtual status_t onInputReceived(uint8_t* data, size_t size, MetaDataBase& sampleMeta,
+ bool firstSample, uint32_t* flags) override;
virtual status_t onOutputReceived(
- const sp<MediaCodecBuffer> &videoFrameBuffer,
+ uint8_t* data,
+ sp<ABuffer> imgObj,
const sp<AMessage> &outputFormat,
int64_t timeUs,
bool *done) override;
@@ -162,14 +199,13 @@
virtual status_t onExtractRect(FrameRect *rect) override;
- virtual status_t onInputReceived(
- const sp<MediaCodecBuffer> &codecBuffer __unused,
- MetaDataBase &sampleMeta __unused,
- bool firstSample __unused,
- uint32_t *flags __unused) override { return OK; }
+ virtual status_t onInputReceived(uint8_t* __unused, size_t __unused,
+ MetaDataBase& sampleMeta __unused, bool firstSample __unused,
+ uint32_t* flags __unused) override { return OK; }
virtual status_t onOutputReceived(
- const sp<MediaCodecBuffer> &videoFrameBuffer,
+ uint8_t* data,
+ sp<ABuffer> imgObj,
const sp<AMessage> &outputFormat,
int64_t timeUs,
bool *done) override;
diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp
index 5d68890..979edab 100644
--- a/media/mtp/MtpFfsHandle.cpp
+++ b/media/mtp/MtpFfsHandle.cpp
@@ -297,9 +297,10 @@
}
void MtpFfsHandle::close() {
- auto timeout = std::chrono::seconds(2);
- std::unique_lock lk(m);
- cv.wait_for(lk, timeout ,[this]{return child_threads==0;});
+ // Join all child threads before destruction
+ for (auto& thread : mChildThreads) {
+ thread.join();
+ }
io_destroy(mCtx);
closeEndpoints();
@@ -677,12 +678,10 @@
memcpy(temp, me.data, me.length);
me.data = temp;
- std::unique_lock lk(m);
- child_threads++;
- lk.unlock();
-
std::thread t([this, me]() { return this->doSendEvent(me); });
- t.detach();
+
+ // Store the thread object for later joining
+ mChildThreads.emplace_back(std::move(t));
return 0;
}
@@ -692,11 +691,6 @@
if (static_cast<unsigned>(ret) != length)
PLOG(ERROR) << "Mtp error sending event thread!";
delete[] reinterpret_cast<char*>(me.data);
-
- std::unique_lock lk(m);
- child_threads--;
- lk.unlock();
- cv.notify_one();
}
} // namespace android
diff --git a/media/mtp/MtpFfsHandle.h b/media/mtp/MtpFfsHandle.h
index 51cdef0..8f4b769 100644
--- a/media/mtp/MtpFfsHandle.h
+++ b/media/mtp/MtpFfsHandle.h
@@ -60,9 +60,7 @@
bool mCanceled;
bool mBatchCancel;
- std::mutex m;
- std::condition_variable cv;
- std::atomic<int> child_threads{0};
+ std::vector<std::thread> mChildThreads;
android::base::unique_fd mControl;
// "in" from the host's perspective => sink for mtp server
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index 3d873df..b250a03 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -52,9 +52,6 @@
symbol_file: "libmediandk.map.txt",
first_version: "21",
unversioned_until: "current",
- export_header_libs: [
- "libmediandk_headers",
- ],
}
ndk_headers {
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index ffcde42..0315ac9 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -473,35 +473,38 @@
}
}
+namespace mediautils {
+
// How long we hold info before we re-fetch it (24 hours) if we found it previously.
static constexpr nsecs_t INFO_EXPIRATION_NS = 24 * 60 * 60 * NANOS_PER_SECOND;
// Maximum info records we retain before clearing everything.
static constexpr size_t INFO_CACHE_MAX = 1000;
// The original code is from MediaMetricsService.cpp.
-mediautils::UidInfo::Info mediautils::UidInfo::getInfo(uid_t uid)
+std::shared_ptr<const UidInfo::Info> UidInfo::getCachedInfo(uid_t uid)
{
+ std::shared_ptr<const UidInfo::Info> info;
+
const nsecs_t now = systemTime(SYSTEM_TIME_REALTIME);
- struct mediautils::UidInfo::Info info;
{
std::lock_guard _l(mLock);
auto it = mInfoMap.find(uid);
if (it != mInfoMap.end()) {
info = it->second;
ALOGV("%s: uid %d expiration %lld now %lld",
- __func__, uid, (long long)info.expirationNs, (long long)now);
- if (info.expirationNs <= now) {
+ __func__, uid, (long long)info->expirationNs, (long long)now);
+ if (info->expirationNs <= now) {
// purge the stale entry and fall into re-fetching
ALOGV("%s: entry for uid %d expired, now %lld",
__func__, uid, (long long)now);
mInfoMap.erase(it);
- info.uid = (uid_t)-1; // this is always fully overwritten
+ info.reset(); // force refetch
}
}
}
// if we did not find it in our map, look it up
- if (info.uid == (uid_t)(-1)) {
+ if (!info) {
sp<IServiceManager> sm = defaultServiceManager();
sp<content::pm::IPackageManagerNative> package_mgr;
if (sm.get() == nullptr) {
@@ -586,17 +589,30 @@
// first clear if we have too many cached elements. This would be rare.
if (mInfoMap.size() >= INFO_CACHE_MAX) mInfoMap.clear();
- // always overwrite
- info.uid = uid;
- info.package = std::move(pkg);
- info.installer = std::move(installer);
- info.versionCode = versionCode;
- info.expirationNs = now + (notFound ? 0 : INFO_EXPIRATION_NS);
+ info = std::make_shared<const UidInfo::Info>(
+ uid,
+ std::move(pkg),
+ std::move(installer),
+ versionCode,
+ now + (notFound ? 0 : INFO_EXPIRATION_NS));
ALOGV("%s: adding uid %d package '%s' expirationNs: %lld",
- __func__, uid, info.package.c_str(), (long long)info.expirationNs);
+ __func__, uid, info->package.c_str(), (long long)info->expirationNs);
mInfoMap[uid] = info;
}
return info;
}
+/* static */
+UidInfo& UidInfo::getUidInfo() {
+ [[clang::no_destroy]] static UidInfo uidInfo;
+ return uidInfo;
+}
+
+/* static */
+std::shared_ptr<const UidInfo::Info> UidInfo::getInfo(uid_t uid) {
+ return UidInfo::getUidInfo().getCachedInfo(uid);
+}
+
+} // namespace mediautils
+
} // namespace android
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index e0fabfd..b365648 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -20,6 +20,7 @@
#include <unistd.h>
#include <android/content/pm/IPackageManagerNative.h>
+#include <android-base/thread_annotations.h>
#include <binder/IMemory.h>
#include <binder/PermissionController.h>
#include <cutils/multiuser.h>
@@ -167,12 +168,18 @@
*
* \param uid is the uid of the app or service.
*/
- Info getInfo(uid_t uid);
+ std::shared_ptr<const Info> getCachedInfo(uid_t uid);
+
+ /* return a singleton */
+ static UidInfo& getUidInfo();
+
+ /* returns a non-null pointer to a const Info struct */
+ static std::shared_ptr<const Info> getInfo(uid_t uid);
private:
std::mutex mLock;
// TODO: use concurrent hashmap with striped lock.
- std::unordered_map<uid_t, Info> mInfoMap; // GUARDED_BY(mLock)
+ std::unordered_map<uid_t, std::shared_ptr<const Info>> mInfoMap GUARDED_BY(mLock);
};
} // namespace mediautils
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index bf2915a..264fc4f 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -152,6 +152,7 @@
"audiopermissioncontroller",
"av-types-aidl-cpp",
"com.android.media.audio-aconfig-cc",
+ "com.android.media.audioserver-aconfig-cc",
"effect-aidl-cpp",
"libactivitymanager_aidl",
"libaudioclient",
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 3bf1d72..d94862a 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -187,6 +187,7 @@
BINDER_METHOD_ENTRY(masterMute) \
BINDER_METHOD_ENTRY(setStreamVolume) \
BINDER_METHOD_ENTRY(setStreamMute) \
+BINDER_METHOD_ENTRY(setPortsVolume) \
BINDER_METHOD_ENTRY(setMode) \
BINDER_METHOD_ENTRY(setMicMute) \
BINDER_METHOD_ENTRY(getMicMute) \
@@ -617,6 +618,7 @@
std::vector<audio_io_handle_t> secondaryOutputs;
bool isSpatialized;
bool isBitPerfect;
+ float volume;
ret = AudioSystem::getOutputForAttr(&localAttr, &io,
actualSessionId,
&streamType, adjAttributionSource,
@@ -624,7 +626,8 @@
(audio_output_flags_t)(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ |
AUDIO_OUTPUT_FLAG_DIRECT),
deviceId, &portId, &secondaryOutputs, &isSpatialized,
- &isBitPerfect);
+ &isBitPerfect,
+ &volume);
if (ret != NO_ERROR) {
config->sample_rate = fullConfig.sample_rate;
config->channel_mask = fullConfig.channel_mask;
@@ -748,20 +751,22 @@
result.append("Notification Clients:\n");
result.append(" pid uid name\n");
- for (size_t i = 0; i < mNotificationClients.size(); ++i) {
- const pid_t pid = mNotificationClients[i]->getPid();
- const uid_t uid = mNotificationClients[i]->getUid();
- const mediautils::UidInfo::Info info = mUidInfo.getInfo(uid);
- result.appendFormat("%6d %6u %s\n", pid, uid, info.package.c_str());
+ for (const auto& [ _, client ] : mNotificationClients) {
+ const uid_t uid = client->getUid();
+ const std::shared_ptr<const mediautils::UidInfo::Info> info =
+ mediautils::UidInfo::getInfo(uid);
+ result.appendFormat("%6d %6u %s\n",
+ client->getPid(), uid, info->package.c_str());
}
result.append("Global session refs:\n");
result.append(" session cnt pid uid name\n");
for (size_t i = 0; i < mAudioSessionRefs.size(); i++) {
AudioSessionRef *r = mAudioSessionRefs[i];
- const mediautils::UidInfo::Info info = mUidInfo.getInfo(r->mUid);
+ const std::shared_ptr<const mediautils::UidInfo::Info> info =
+ mediautils::UidInfo::getInfo(r->mUid);
result.appendFormat(" %7d %4d %7d %6u %s\n", r->mSessionid, r->mCnt, r->mPid,
- r->mUid, info.package.c_str());
+ r->mUid, info->package.c_str());
}
write(fd, result.c_str(), result.size());
}
@@ -1061,6 +1066,7 @@
std::vector<audio_io_handle_t> secondaryOutputs;
bool isSpatialized = false;
bool isBitPerfect = false;
+ float volume;
audio_io_handle_t effectThreadId = AUDIO_IO_HANDLE_NONE;
std::vector<int> effectIds;
@@ -1121,7 +1127,7 @@
lStatus = AudioSystem::getOutputForAttr(&localAttr, &output.outputId, sessionId, &streamType,
adjAttributionSource, &input.config, input.flags,
&output.selectedDeviceId, &portId, &secondaryOutputs,
- &isSpatialized, &isBitPerfect);
+ &isSpatialized, &isBitPerfect, &volume);
if (lStatus != NO_ERROR || output.outputId == AUDIO_IO_HANDLE_NONE) {
ALOGE("createTrack() getOutputForAttr() return error %d or invalid output handle", lStatus);
@@ -1178,7 +1184,7 @@
if (effectThread == nullptr) {
effectChain = getOrphanEffectChain_l(sessionId);
}
- ALOGV("createTrack() sessionId: %d", sessionId);
+ ALOGV("createTrack() sessionId: %d volume: %f", sessionId, volume);
output.sampleRate = input.config.sample_rate;
output.frameCount = input.frameCount;
@@ -1193,7 +1199,7 @@
input.sharedBuffer, sessionId, &output.flags,
callingPid, adjAttributionSource, input.clientInfo.clientTid,
&lStatus, portId, input.audioTrackCallback, isSpatialized,
- isBitPerfect, &output.afTrackFlags);
+ isBitPerfect, &output.afTrackFlags, volume);
LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (track == 0));
// we don't abort yet if lStatus != NO_ERROR; there is still work to be done regardless
@@ -1644,6 +1650,33 @@
return NO_ERROR;
}
+status_t AudioFlinger::setPortsVolume(
+ const std::vector<audio_port_handle_t>& ports, float volume, audio_io_handle_t output)
+{
+ for (const auto& port : ports) {
+ if (port == AUDIO_PORT_HANDLE_NONE) {
+ return BAD_VALUE;
+ }
+ }
+ if (isnan(volume) || volume > 1.0f || volume < 0.0f) {
+ return BAD_VALUE;
+ }
+ if (output == AUDIO_IO_HANDLE_NONE) {
+ return BAD_VALUE;
+ }
+ audio_utils::lock_guard lock(mutex());
+ IAfPlaybackThread *thread = checkPlaybackThread_l(output);
+ if (thread != nullptr) {
+ return thread->setPortsVolume(ports, volume);
+ }
+ const sp<IAfMmapThread> mmapThread = checkMmapThread_l(output);
+ if (mmapThread != nullptr && mmapThread->isOutput()) {
+ IAfMmapPlaybackThread *mmapPlaybackThread = mmapThread->asIAfMmapPlaybackThread().get();
+ return mmapPlaybackThread->setPortsVolume(ports, volume);
+ }
+ return BAD_VALUE;
+}
+
status_t AudioFlinger::setRequestedLatencyMode(
audio_io_handle_t output, audio_latency_mode_t mode) {
if (output == AUDIO_IO_HANDLE_NONE) {
@@ -2131,24 +2164,22 @@
void AudioFlinger::registerClient(const sp<media::IAudioFlingerClient>& client)
{
- audio_utils::lock_guard _l(mutex());
if (client == 0) {
return;
}
- pid_t pid = IPCThreadState::self()->getCallingPid();
+ const pid_t pid = IPCThreadState::self()->getCallingPid();
const uid_t uid = IPCThreadState::self()->getCallingUid();
+
+ audio_utils::lock_guard _l(mutex());
{
audio_utils::lock_guard _cl(clientMutex());
- if (mNotificationClients.indexOfKey(pid) < 0) {
- sp<NotificationClient> notificationClient = new NotificationClient(this,
- client,
- pid,
- uid);
+ if (mNotificationClients.count(pid) == 0) {
+ auto notificationClient = sp<NotificationClient>::make(
+ this, client, pid, uid);
ALOGV("registerClient() client %p, pid %d, uid %u",
notificationClient.get(), pid, uid);
- mNotificationClients.add(pid, notificationClient);
-
+ mNotificationClients[pid] = notificationClient;
sp<IBinder> binder = IInterface::asBinder(client);
binder->linkToDeath(notificationClient);
}
@@ -2175,7 +2206,7 @@
audio_utils::lock_guard _l(mutex());
{
audio_utils::lock_guard _cl(clientMutex());
- mNotificationClients.removeItem(pid);
+ mNotificationClients.erase(pid);
}
ALOGV("%d died, releasing its sessions", pid);
@@ -2216,11 +2247,13 @@
legacy2aidl_AudioIoDescriptor_AudioIoDescriptor(ioDesc));
audio_utils::lock_guard _l(clientMutex());
- size_t size = mNotificationClients.size();
- for (size_t i = 0; i < size; i++) {
- if ((pid == 0) || (mNotificationClients.keyAt(i) == pid)) {
- mNotificationClients.valueAt(i)->audioFlingerClient()->ioConfigChanged(eventAidl,
- descAidl);
+ if (pid != 0) {
+ if (auto it = mNotificationClients.find(pid); it != mNotificationClients.end()) {
+ it->second->audioFlingerClient()->ioConfigChanged(eventAidl, descAidl);
+ }
+ } else {
+ for (const auto& [ client_pid, client] : mNotificationClients) {
+ client->audioFlingerClient()->ioConfigChanged(eventAidl, descAidl);
}
}
}
@@ -2234,9 +2267,8 @@
audio_utils::lock_guard _l(clientMutex());
size_t size = mNotificationClients.size();
- for (size_t i = 0; i < size; i++) {
- mNotificationClients.valueAt(i)->audioFlingerClient()
- ->onSupportedLatencyModesChanged(outputAidl, modesAidl);
+ for (const auto& [_, client] : mNotificationClients) {
+ client->audioFlingerClient()->onSupportedLatencyModesChanged(outputAidl, modesAidl);
}
}
@@ -2304,7 +2336,7 @@
void AudioFlinger::NotificationClient::binderDied(const wp<IBinder>& who __unused)
{
- sp<NotificationClient> keep(this);
+ const auto keep = sp<NotificationClient>::fromExisting(this);
mAudioFlinger->removeNotificationClient(mPid);
}
@@ -3571,7 +3603,7 @@
// is likely proxied by mediaserver (e.g CameraService) and releaseAudioSessionId() can be
// called from a different pid leaving a stale session reference. Also we don't know how
// to clear this reference if the client process dies.
- if (mNotificationClients.indexOfKey(caller) < 0) {
+ if (mNotificationClients.count(caller) == 0) {
ALOGW("acquireAudioSessionId() unknown client %d for session %d", caller, audioSession);
return;
}
@@ -3832,8 +3864,7 @@
// checkPlaybackThread_l() must be called with AudioFlinger::mutex() held
-sp<VolumeInterface> AudioFlinger::getVolumeInterface_l(audio_io_handle_t output) const
-{
+sp<VolumeInterface> AudioFlinger::getVolumeInterface_l(audio_io_handle_t output) const {
sp<VolumeInterface> volumeInterface = mPlaybackThreads.valueFor(output).get();
if (volumeInterface == nullptr) {
IAfMmapThread* const mmapThread = mMmapThreads.valueFor(output).get();
@@ -4032,7 +4063,8 @@
outputFlags,
0ns /* timeout */,
frameCountToBeReady,
- track->getSpeed());
+ track->getSpeed(),
+ 1.f /* volume */);
status = patchTrack->initCheck();
if (status != NO_ERROR) {
ALOGE("Secondary output patchTrack init failed: %d", status);
@@ -5131,6 +5163,7 @@
case TransactionCode::GET_AUDIO_MIX_PORT:
case TransactionCode::SET_TRACKS_INTERNAL_MUTE:
case TransactionCode::RESET_REFERENCES_FOR_TEST:
+ case TransactionCode::SET_PORTS_VOLUME:
ALOGW("%s: transaction %d received from PID %d",
__func__, static_cast<int>(code), IPCThreadState::self()->getCallingPid());
// return status only for non void methods
@@ -5218,7 +5251,7 @@
}
}, mediautils::TimeCheck::getDefaultTimeoutDuration(),
mediautils::TimeCheck::getDefaultSecondChanceDuration(),
- true /* crashOnTimeout */);
+ !property_get_bool("audio.timecheck.disabled", false) /* crashOnTimeout */);
return delegate();
}
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 9513327..7c58c96 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -96,6 +96,9 @@
status_t setStreamMute(audio_stream_type_t stream, bool muted) final
EXCLUDES_AudioFlinger_Mutex;
+ status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume,
+ audio_io_handle_t output) final EXCLUDES_AudioFlinger_Mutex;
+
status_t setMode(audio_mode_t mode) final EXCLUDES_AudioFlinger_Mutex;
status_t setMicMute(bool state) final EXCLUDES_AudioFlinger_Mutex;
@@ -552,6 +555,7 @@
IAfPlaybackThread* checkMixerThread_l(audio_io_handle_t output) const REQUIRES(mutex());
sp<VolumeInterface> getVolumeInterface_l(audio_io_handle_t output) const REQUIRES(mutex());
+
std::vector<sp<VolumeInterface>> getAllVolumeInterfaces_l() const REQUIRES(mutex());
@@ -694,8 +698,7 @@
DefaultKeyedVector<audio_io_handle_t, sp<IAfRecordThread>> mRecordThreads GUARDED_BY(mutex());
- DefaultKeyedVector<pid_t, sp<NotificationClient>> mNotificationClients
- GUARDED_BY(clientMutex());
+ std::map<pid_t, sp<NotificationClient>> mNotificationClients GUARDED_BY(clientMutex());
// updated by atomic_fetch_add_explicit
volatile atomic_uint_fast32_t mNextUniqueIds[AUDIO_UNIQUE_ID_USE_MAX]; // ctor init
@@ -773,8 +776,6 @@
bool mSystemReady GUARDED_BY(mutex()) = false;
std::atomic<bool> mAudioPolicyReady = false;
- mediautils::UidInfo mUidInfo GUARDED_BY(mutex());
-
// no mutex needed.
SimpleLog mRejectedSetParameterLog;
SimpleLog mAppSetParameterLog;
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 6273570..84505d3 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -3266,7 +3266,9 @@
}
if (mThreadType == IAfThreadBase::SPATIALIZER) {
- if (c->sessionId() == AUDIO_SESSION_OUTPUT_STAGE) {
+ if (c->sessionId() == AUDIO_SESSION_OUTPUT_MIX) {
+ return t->mixerChannelMask();
+ } else if (c->sessionId() == AUDIO_SESSION_OUTPUT_STAGE) {
if (c->isFirstEffect_l(id)) {
return t->mixerChannelMask();
} else {
@@ -3313,7 +3315,8 @@
return t->channelMask();
}
} else {
- return t->channelMask();
+ return (c->sessionId() == AUDIO_SESSION_OUTPUT_MIX) ? t->mixerChannelMask()
+ : t->channelMask();
}
} else {
return t->channelMask();
diff --git a/services/audioflinger/IAfThread.h b/services/audioflinger/IAfThread.h
index 4d26aa0..8596acb 100644
--- a/services/audioflinger/IAfThread.h
+++ b/services/audioflinger/IAfThread.h
@@ -26,6 +26,7 @@
#include <datapath/AudioStreamIn.h>
#include <datapath/AudioStreamOut.h>
#include <datapath/VolumeInterface.h>
+#include <datapath/VolumePortInterface.h>
#include <fastpath/FastMixerDumpState.h>
#include <media/DeviceDescriptorBase.h>
#include <media/MmapStreamInterface.h>
@@ -479,7 +480,8 @@
const sp<media::IAudioTrackCallback>& callback,
bool isSpatialized,
bool isBitPerfect,
- audio_output_flags_t* afTrackFlags)
+ audio_output_flags_t* afTrackFlags,
+ float volume)
REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
virtual status_t addTrack_l(const sp<IAfTrack>& track) REQUIRES(mutex()) = 0;
@@ -555,6 +557,9 @@
virtual void setTracksInternalMute(std::map<audio_port_handle_t, bool>* tracksInternalMute)
EXCLUDES_ThreadBase_Mutex = 0;
+
+ virtual status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume)
+ EXCLUDES_ThreadBase_Mutex = 0;
};
class IAfDirectOutputThread : public virtual IAfPlaybackThread {
@@ -694,6 +699,9 @@
AudioHwDevice* hwDev, AudioStreamOut* output, bool systemReady);
virtual AudioStreamOut* clearOutput() EXCLUDES_ThreadBase_Mutex = 0;
+
+ virtual status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume)
+ EXCLUDES_ThreadBase_Mutex = 0;
};
class IAfMmapCaptureThread : public virtual IAfMmapThread {
diff --git a/services/audioflinger/IAfTrack.h b/services/audioflinger/IAfTrack.h
index a9c87ad..ee834d6 100644
--- a/services/audioflinger/IAfTrack.h
+++ b/services/audioflinger/IAfTrack.h
@@ -21,6 +21,7 @@
#include <audio_utils/mutex.h>
#include <audiomanager/IAudioManager.h>
#include <binder/IMemory.h>
+#include <datapath/VolumePortInterface.h>
#include <fastpath/FastMixerDumpState.h>
#include <media/AudioSystem.h>
#include <media/VolumeShaper.h>
@@ -254,7 +255,7 @@
};
// Common interface for Playback tracks.
-class IAfTrack : public virtual IAfTrackBase {
+class IAfTrack : public virtual IAfTrackBase, public virtual VolumePortInterface {
public:
// FillingStatus is used for suppressing volume ramp at begin of playing
enum FillingStatus { FS_INVALID, FS_FILLING, FS_FILLED, FS_ACTIVE };
@@ -289,7 +290,8 @@
size_t frameCountToBeReady = SIZE_MAX,
float speed = 1.0f,
bool isSpatialized = false,
- bool isBitPerfect = false);
+ bool isBitPerfect = false,
+ float volume = 0.0f);
virtual void pause() = 0;
virtual void flush() = 0;
@@ -452,7 +454,7 @@
virtual ExtendedTimestamp getClientProxyTimestamp() const = 0;
};
-class IAfMmapTrack : public virtual IAfTrackBase {
+class IAfMmapTrack : public virtual IAfTrackBase, public virtual VolumePortInterface {
public:
static sp<IAfMmapTrack> create(IAfThreadBase* thread,
const audio_attributes_t& attr,
@@ -463,7 +465,8 @@
bool isOut,
const android::content::AttributionSourceState& attributionSource,
pid_t creatorPid,
- audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
+ float volume = 0.0f);
// protected by MMapThread::mLock
virtual void setSilenced_l(bool silenced) = 0;
@@ -583,7 +586,8 @@
* as soon as possible to have
* the lowest possible latency
* even if it might glitch. */
- float speed = 1.0f);
+ float speed = 1.0f,
+ float volume = 1.0f);
};
class IAfPatchRecord : public virtual IAfRecordTrack, public virtual IAfPatchTrackBase {
diff --git a/services/audioflinger/MmapTracks.h b/services/audioflinger/MmapTracks.h
index 85ce142..8758bd0 100644
--- a/services/audioflinger/MmapTracks.h
+++ b/services/audioflinger/MmapTracks.h
@@ -35,7 +35,8 @@
bool isOut,
const android::content::AttributionSourceState& attributionSource,
pid_t creatorPid,
- audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
+ float volume = 0.0f);
~MmapTrack() override;
status_t initCheck() const final;
@@ -65,6 +66,13 @@
void processMuteEvent_l(const sp<IAudioManager>& audioManager,
mute_state_t muteState)
/* REQUIRES(MmapPlaybackThread::mLock) */ final;
+
+ // VolumePortInterface implementation
+ void setPortVolume(float volume) override {
+ mVolume = volume;
+ }
+ float getPortVolume() const override { return mVolume; }
+
private:
DISALLOW_COPY_AND_ASSIGN(MmapTrack);
@@ -87,6 +95,8 @@
/* GUARDED_BY(MmapPlaybackThread::mLock) */;
mute_state_t mMuteState
/* GUARDED_BY(MmapPlaybackThread::mLock) */;
+
+ float mVolume = 0.0f;
}; // end of Track
} // namespace android
\ No newline at end of file
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index 35f17c1..02d4fc2 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -649,7 +649,8 @@
outputFlags,
{} /*timeout*/,
frameCountToBeReady,
- 1.0f);
+ 1.0f /*speed*/,
+ 1.0f /*volume*/);
status = mPlayback.checkTrack(tempPatchTrack.get());
if (status != NO_ERROR) {
return status;
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 2cc6236..84758a4 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -96,7 +96,8 @@
size_t frameCountToBeReady = SIZE_MAX,
float speed = 1.0f,
bool isSpatialized = false,
- bool isBitPerfect = false);
+ bool isBitPerfect = false,
+ float volume = 0.0f);
~Track() override;
status_t initCheck() const final;
void appendDumpHeader(String8& result) const final;
@@ -222,6 +223,11 @@
bool getInternalMute() const final { return mInternalMute; }
void setInternalMute(bool muted) final { mInternalMute = muted; }
+
+ // VolumePortInterface implementation
+ void setPortVolume(float volume) override;
+ float getPortVolume() const override { return mVolume; }
+
protected:
DISALLOW_COPY_AND_ASSIGN(Track);
@@ -362,6 +368,8 @@
for (auto& tp : mTeePatches) { f(tp.patchTrack); }
};
+ void populateUsageAndContentTypeFromStreamType();
+
size_t mPresentationCompleteFrames = 0; // (Used for Mixed tracks)
// The number of frames written to the
// audio HAL when this track is considered fully rendered.
@@ -403,8 +411,8 @@
// access these two variables only when holding player thread lock.
std::unique_ptr<os::PersistableBundle> mMuteEventExtras;
mute_state_t mMuteState;
-
bool mInternalMute = false;
+ std::atomic<float> mVolume = 0.0f;
}; // end of Track
@@ -501,7 +509,8 @@
* as soon as possible to have
* the lowest possible latency
* even if it might glitch. */
- float speed = 1.0f);
+ float speed = 1.0f,
+ float volume = 1.0f);
~PatchTrack() override;
size_t framesReady() const final;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 583552a..406b832 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -49,6 +49,7 @@
#include <binder/IServiceManager.h>
#include <binder/PersistableBundle.h>
#include <com_android_media_audio.h>
+#include <com_android_media_audioserver.h>
#include <cutils/bitops.h>
#include <cutils/properties.h>
#include <fastpath/AutoPark.h>
@@ -122,6 +123,7 @@
}
using com::android::media::permission::ValidatedAttributionSourceState;
+namespace audioserver_flags = com::android::media::audioserver;
namespace android {
@@ -1194,6 +1196,8 @@
return String16("MmapCapture");
case SPATIALIZER:
return String16("AudioSpatial");
+ case BIT_PERFECT:
+ return String16("AudioBitPerfect");
default:
ALOG_ASSERT(false);
return String16("AudioUnknown");
@@ -1578,14 +1582,13 @@
}
break;
case SPATIALIZER:
- // Global effects (AUDIO_SESSION_OUTPUT_MIX) are not supported on spatializer mixer
- // as there is no common accumulation buffer for sptialized and non sptialized tracks.
+ // Global effects (AUDIO_SESSION_OUTPUT_MIX) are supported on spatializer mixer, but only
+ // the spatialized track have global effects applied for now.
// Post processing effects (AUDIO_SESSION_OUTPUT_STAGE or AUDIO_SESSION_DEVICE)
// are supported and added after the spatializer.
if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
- ALOGW("%s: global effect %s not supported on spatializer thread %s",
- __func__, desc->name, mThreadName);
- return BAD_VALUE;
+ ALOGD("%s: global effect %s on spatializer thread %s", __func__, desc->name,
+ mThreadName);
} else if (sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
// only post processing , downmixer or spatializer effects on output stage session
if (IAfEffectModule::isSpatializer(&desc->type)
@@ -2217,17 +2220,18 @@
(int64_t)(mIsMsdDevice ? AUDIO_DEVICE_OUT_BUS // turn on by default for MSD
: AUDIO_DEVICE_NONE));
}
-
- for (int i = AUDIO_STREAM_MIN; i < AUDIO_STREAM_FOR_POLICY_CNT; ++i) {
- const audio_stream_type_t stream{static_cast<audio_stream_type_t>(i)};
- mStreamTypes[stream].volume = 0.0f;
- mStreamTypes[stream].mute = mAfThreadCallback->streamMute_l(stream);
+ if (!audioserver_flags::portid_volume_management()) {
+ for (int i = AUDIO_STREAM_MIN; i < AUDIO_STREAM_FOR_POLICY_CNT; ++i) {
+ const audio_stream_type_t stream{static_cast<audio_stream_type_t>(i)};
+ mStreamTypes[stream].volume = 0.0f;
+ mStreamTypes[stream].mute = mAfThreadCallback->streamMute_l(stream);
+ }
+ // Audio patch and call assistant volume are always max
+ mStreamTypes[AUDIO_STREAM_PATCH].volume = 1.0f;
+ mStreamTypes[AUDIO_STREAM_PATCH].mute = false;
+ mStreamTypes[AUDIO_STREAM_CALL_ASSISTANT].volume = 1.0f;
+ mStreamTypes[AUDIO_STREAM_CALL_ASSISTANT].mute = false;
}
- // Audio patch and call assistant volume are always max
- mStreamTypes[AUDIO_STREAM_PATCH].volume = 1.0f;
- mStreamTypes[AUDIO_STREAM_PATCH].mute = false;
- mStreamTypes[AUDIO_STREAM_CALL_ASSISTANT].volume = 1.0f;
- mStreamTypes[AUDIO_STREAM_CALL_ASSISTANT].mute = false;
}
PlaybackThread::~PlaybackThread()
@@ -2278,16 +2282,17 @@
void PlaybackThread::dumpTracks_l(int fd, const Vector<String16>& /* args */)
{
String8 result;
-
- result.appendFormat(" Stream volumes in dB: ");
- for (int i = 0; i < AUDIO_STREAM_CNT; ++i) {
- const stream_type_t *st = &mStreamTypes[i];
- if (i > 0) {
- result.appendFormat(", ");
- }
- result.appendFormat("%d:%.2g", i, 20.0 * log10(st->volume));
- if (st->mute) {
- result.append("M");
+ if (!audioserver_flags::portid_volume_management()) {
+ result.appendFormat(" Stream volumes in dB: ");
+ for (int i = 0; i < AUDIO_STREAM_CNT; ++i) {
+ const stream_type_t *st = &mStreamTypes[i];
+ if (i > 0) {
+ result.appendFormat(", ");
+ }
+ result.appendFormat("%d:%.2g", i, 20.0 * log10(st->volume));
+ if (st->mute) {
+ result.append("M");
+ }
}
}
result.append("\n");
@@ -2395,7 +2400,8 @@
const sp<media::IAudioTrackCallback>& callback,
bool isSpatialized,
bool isBitPerfect,
- audio_output_flags_t *afTrackFlags)
+ audio_output_flags_t *afTrackFlags,
+ float volume)
{
size_t frameCount = *pFrameCount;
size_t notificationFrameCount = *pNotificationFrameCount;
@@ -2724,7 +2730,7 @@
nullptr /* buffer */, (size_t)0 /* bufferSize */, sharedBuffer,
sessionId, creatorPid, attributionSource, trackFlags,
IAfTrackBase::TYPE_DEFAULT, portId, SIZE_MAX /*frameCountToBeReady*/,
- speed, isSpatialized, isBitPerfect);
+ speed, isSpatialized, isBitPerfect, volume);
lStatus = track != 0 ? track->initCheck() : (status_t) NO_MEMORY;
if (lStatus != NO_ERROR) {
@@ -2852,6 +2858,22 @@
return mStreamTypes[stream].volume;
}
+status_t PlaybackThread::setPortsVolume(
+ const std::vector<audio_port_handle_t>& portIds, float volume) {
+ audio_utils::lock_guard _l(mutex());
+ for (const auto& portId : portIds) {
+ for (size_t i = 0; i < mTracks.size(); i++) {
+ sp<IAfTrack> track = mTracks[i].get();
+ if (portId == track->portId()) {
+ track->setPortVolume(volume);
+ break;
+ }
+ }
+ }
+ broadcast_l();
+ return NO_ERROR;
+}
+
void PlaybackThread::setVolumeForOutput_l(float left, float right) const
{
mOutput->stream->setVolume(left, right);
@@ -3803,19 +3825,31 @@
ALOGV("addEffectChain_l() creating new input buffer %p session %d",
buffer, session);
} else {
- // A global session on a SPATIALIZER thread is either OUTPUT_STAGE or DEVICE
- // - OUTPUT_STAGE session uses the mEffectBuffer as input buffer and
- // mPostSpatializerBuffer as output buffer
- // - DEVICE session uses the mPostSpatializerBuffer as input and output buffer.
- status_t result = mAfThreadCallback->getEffectsFactoryHal()->mirrorBuffer(
- mEffectBuffer, mEffectBufferSize, &halInBuffer);
- if (result != OK) return result;
- result = mAfThreadCallback->getEffectsFactoryHal()->mirrorBuffer(
- mPostSpatializerBuffer, mPostSpatializerBufferSize, &halOutBuffer);
- if (result != OK) return result;
+ status_t result = INVALID_OPERATION;
+ // Buffer configuration for global sessions on a SPATIALIZER thread:
+ // - AUDIO_SESSION_OUTPUT_MIX session uses the mEffectBuffer as input and output buffer
+ // - AUDIO_SESSION_OUTPUT_STAGE session uses the mEffectBuffer as input buffer and
+ // mPostSpatializerBuffer as output buffer
+ // - AUDIO_SESSION_DEVICE session uses the mPostSpatializerBuffer as input and output
+ // buffer
+ if (session == AUDIO_SESSION_OUTPUT_MIX || session == AUDIO_SESSION_OUTPUT_STAGE) {
+ result = mAfThreadCallback->getEffectsFactoryHal()->mirrorBuffer(
+ mEffectBuffer, mEffectBufferSize, &halInBuffer);
+ if (result != OK) return result;
- if (session == AUDIO_SESSION_DEVICE) {
- halInBuffer = halOutBuffer;
+ if (session == AUDIO_SESSION_OUTPUT_MIX) {
+ halOutBuffer = halInBuffer;
+ }
+ }
+
+ if (session == AUDIO_SESSION_OUTPUT_STAGE || session == AUDIO_SESSION_DEVICE) {
+ result = mAfThreadCallback->getEffectsFactoryHal()->mirrorBuffer(
+ mPostSpatializerBuffer, mPostSpatializerBufferSize, &halOutBuffer);
+ if (result != OK) return result;
+
+ if (session == AUDIO_SESSION_DEVICE) {
+ halInBuffer = halOutBuffer;
+ }
}
}
} else {
@@ -5783,12 +5817,19 @@
}
sp<AudioTrackServerProxy> proxy = track->audioTrackServerProxy();
float volume;
- if (track->isPlaybackRestricted() || mStreamTypes[track->streamType()].mute) {
- volume = 0.f;
+ if (!audioserver_flags::portid_volume_management()) {
+ if (track->isPlaybackRestricted() || mStreamTypes[track->streamType()].mute) {
+ volume = 0.f;
+ } else {
+ volume = masterVolume * mStreamTypes[track->streamType()].volume;
+ }
} else {
- volume = masterVolume * mStreamTypes[track->streamType()].volume;
+ if (track->isPlaybackRestricted()) {
+ volume = 0.f;
+ } else {
+ volume = masterVolume * track->getPortVolume();
+ }
}
-
handleVoipVolume_l(&volume);
// cache the combined master volume and stream type volume for fast mixer; this
@@ -5800,15 +5841,23 @@
gain_minifloat_packed_t vlr = proxy->getVolumeLR();
float vlf = float_from_gain(gain_minifloat_unpack_left(vlr));
float vrf = float_from_gain(gain_minifloat_unpack_right(vlr));
-
- track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
- /*muteState=*/{masterVolume == 0.f,
- mStreamTypes[track->streamType()].volume == 0.f,
- mStreamTypes[track->streamType()].mute,
- track->isPlaybackRestricted(),
- vlf == 0.f && vrf == 0.f,
- vh == 0.f});
-
+ if (!audioserver_flags::portid_volume_management()) {
+ track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
+ /*muteState=*/{masterVolume == 0.f,
+ mStreamTypes[track->streamType()].volume == 0.f,
+ mStreamTypes[track->streamType()].mute,
+ track->isPlaybackRestricted(),
+ vlf == 0.f && vrf == 0.f,
+ vh == 0.f});
+ } else {
+ track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
+ /*muteState=*/{masterVolume == 0.f,
+ track->getPortVolume() == 0.f,
+ /* muteFromStreamMuted= */ false,
+ track->isPlaybackRestricted(),
+ vlf == 0.f && vrf == 0.f,
+ vh == 0.f});
+ }
vlf *= volume;
vrf *= volume;
@@ -5959,16 +6008,22 @@
uint32_t vl, vr; // in U8.24 integer format
float vlf, vrf, vaf; // in [0.0, 1.0] float format
// read original volumes with volume control
- float v = masterVolume * mStreamTypes[track->streamType()].volume;
// Always fetch volumeshaper volume to ensure state is updated.
const sp<AudioTrackServerProxy> proxy = track->audioTrackServerProxy();
const float vh = track->getVolumeHandler()->getVolume(
track->audioTrackServerProxy()->framesReleased()).first;
-
- if (mStreamTypes[track->streamType()].mute || track->isPlaybackRestricted()) {
- v = 0;
+ float v;
+ if (!audioserver_flags::portid_volume_management()) {
+ v = masterVolume * mStreamTypes[track->streamType()].volume;
+ if (mStreamTypes[track->streamType()].mute || track->isPlaybackRestricted()) {
+ v = 0;
+ }
+ } else {
+ v = masterVolume * track->getPortVolume();
+ if (track->isPlaybackRestricted()) {
+ v = 0;
+ }
}
-
handleVoipVolume_l(&v);
if (track->isPausing()) {
@@ -5988,15 +6043,23 @@
ALOGV("Track right volume out of range: %.3g", vrf);
vrf = GAIN_FLOAT_UNITY;
}
-
- track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
- /*muteState=*/{masterVolume == 0.f,
- mStreamTypes[track->streamType()].volume == 0.f,
- mStreamTypes[track->streamType()].mute,
- track->isPlaybackRestricted(),
- vlf == 0.f && vrf == 0.f,
- vh == 0.f});
-
+ if (!audioserver_flags::portid_volume_management()) {
+ track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
+ /*muteState=*/{masterVolume == 0.f,
+ mStreamTypes[track->streamType()].volume == 0.f,
+ mStreamTypes[track->streamType()].mute,
+ track->isPlaybackRestricted(),
+ vlf == 0.f && vrf == 0.f,
+ vh == 0.f});
+ } else {
+ track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
+ /*muteState=*/{masterVolume == 0.f,
+ track->getPortVolume() == 0.f,
+ /* muteFromStreamMuted= */ false,
+ track->isPlaybackRestricted(),
+ vlf == 0.f && vrf == 0.f,
+ vh == 0.f});
+ }
// now apply the master volume and stream type volume and shaper volume
vlf *= v * vh;
vrf *= v * vh;
@@ -6722,34 +6785,64 @@
const bool clientVolumeMute = (left == 0.f && right == 0.f);
- if (mMasterMute || mStreamTypes[track->streamType()].mute || track->isPlaybackRestricted()) {
- left = right = 0;
- } else {
- float typeVolume = mStreamTypes[track->streamType()].volume;
- const float v = mMasterVolume * typeVolume * shaperVolume;
+ if (!audioserver_flags::portid_volume_management()) {
+ if (mMasterMute || mStreamTypes[track->streamType()].mute ||
+ track->isPlaybackRestricted()) {
+ left = right = 0;
+ } else {
+ float typeVolume = mStreamTypes[track->streamType()].volume;
+ const float v = mMasterVolume * typeVolume * shaperVolume;
- if (left > GAIN_FLOAT_UNITY) {
- left = GAIN_FLOAT_UNITY;
- }
- if (right > GAIN_FLOAT_UNITY) {
- right = GAIN_FLOAT_UNITY;
- }
- left *= v;
- right *= v;
- if (mAfThreadCallback->getMode() != AUDIO_MODE_IN_COMMUNICATION
+ if (left > GAIN_FLOAT_UNITY) {
+ left = GAIN_FLOAT_UNITY;
+ }
+ if (right > GAIN_FLOAT_UNITY) {
+ right = GAIN_FLOAT_UNITY;
+ }
+ left *= v;
+ right *= v;
+ if (mAfThreadCallback->getMode() != AUDIO_MODE_IN_COMMUNICATION
|| audio_channel_count_from_out_mask(mChannelMask) > 1) {
- left *= mMasterBalanceLeft; // DirectOutputThread balance applied as track volume
- right *= mMasterBalanceRight;
+ left *= mMasterBalanceLeft; // DirectOutputThread balance applied as track volume
+ right *= mMasterBalanceRight;
+ }
}
- }
+ track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
+ /*muteState=*/{mMasterMute,
+ mStreamTypes[track->streamType()].volume == 0.f,
+ mStreamTypes[track->streamType()].mute,
+ track->isPlaybackRestricted(),
+ clientVolumeMute,
+ shaperVolume == 0.f});
+ } else {
+ if (mMasterMute || track->isPlaybackRestricted()) {
+ left = right = 0;
+ } else {
+ float typeVolume = track->getPortVolume();
+ const float v = mMasterVolume * typeVolume * shaperVolume;
- track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
- /*muteState=*/{mMasterMute,
- mStreamTypes[track->streamType()].volume == 0.f,
- mStreamTypes[track->streamType()].mute,
- track->isPlaybackRestricted(),
- clientVolumeMute,
- shaperVolume == 0.f});
+ if (left > GAIN_FLOAT_UNITY) {
+ left = GAIN_FLOAT_UNITY;
+ }
+ if (right > GAIN_FLOAT_UNITY) {
+ right = GAIN_FLOAT_UNITY;
+ }
+ left *= v;
+ right *= v;
+ if (mAfThreadCallback->getMode() != AUDIO_MODE_IN_COMMUNICATION
+ || audio_channel_count_from_out_mask(mChannelMask) > 1) {
+ left *= mMasterBalanceLeft; // DirectOutputThread balance applied as track volume
+ right *= mMasterBalanceRight;
+ }
+ }
+ track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
+ /*muteState=*/{mMasterMute,
+ track->getPortVolume() == 0.f,
+ /* muteFromStreamMuted= */ false,
+ track->isPlaybackRestricted(),
+ clientVolumeMute,
+ shaperVolume == 0.f});
+ }
if (lastTrack) {
track->setFinalVolume(left, right);
@@ -7771,6 +7864,9 @@
audio_utils::lock_guard l(mutex());
localTracks = std::move(mOutputTracks);
mOutputTracks.clear();
+ for (size_t i = 0; i < localTracks.size(); ++i) {
+ localTracks[i]->destroy();
+ }
}
localTracks.clear();
outputTracks.clear();
@@ -7843,7 +7939,9 @@
ALOGE("addOutputTrack() initCheck failed %d", status);
return;
}
- thread->setStreamVolume(AUDIO_STREAM_PATCH, 1.0f);
+ if (!audioserver_flags::portid_volume_management()) {
+ thread->setStreamVolume(AUDIO_STREAM_PATCH, 1.0f);
+ }
mOutputTracks.add(outputTrack);
ALOGV("addOutputTrack() track %p, on thread %p", outputTrack.get(), thread);
updateWaitTime_l();
@@ -10330,6 +10428,7 @@
const auto localSessionId = mSessionId;
auto localAttr = mAttr;
+ float volume = 0.0f;
if (isOutput()) {
audio_config_t config = AUDIO_CONFIG_INITIALIZER;
config.sample_rate = mSampleRate;
@@ -10353,7 +10452,8 @@
&portId,
&secondaryOutputs,
&isSpatialized,
- &isBitPerfect);
+ &isBitPerfect,
+ &volume);
mutex().lock();
mAttr = localAttr;
ALOGD_IF(!secondaryOutputs.empty(),
@@ -10422,7 +10522,8 @@
this, attr == nullptr ? mAttr : *attr, mSampleRate, mFormat,
mChannelMask, mSessionId, isOutput(),
client.attributionSource,
- IPCThreadState::self()->getCallingPid(), portId);
+ IPCThreadState::self()->getCallingPid(), portId,
+ volume);
if (!isOutput()) {
track->setSilenced_l(isClientSilenced_l(portId));
}
@@ -11007,18 +11108,18 @@
mChannelCount = audio_channel_count_from_out_mask(mChannelMask);
mMasterVolume = afThreadCallback->masterVolume_l();
mMasterMute = afThreadCallback->masterMute_l();
-
- for (int i = AUDIO_STREAM_MIN; i < AUDIO_STREAM_FOR_POLICY_CNT; ++i) {
- const audio_stream_type_t stream{static_cast<audio_stream_type_t>(i)};
- mStreamTypes[stream].volume = 0.0f;
- mStreamTypes[stream].mute = mAfThreadCallback->streamMute_l(stream);
+ if (!audioserver_flags::portid_volume_management()) {
+ for (int i = AUDIO_STREAM_MIN; i < AUDIO_STREAM_FOR_POLICY_CNT; ++i) {
+ const audio_stream_type_t stream{static_cast<audio_stream_type_t>(i)};
+ mStreamTypes[stream].volume = 0.0f;
+ mStreamTypes[stream].mute = mAfThreadCallback->streamMute_l(stream);
+ }
+ // Audio patch and call assistant volume are always max
+ mStreamTypes[AUDIO_STREAM_PATCH].volume = 1.0f;
+ mStreamTypes[AUDIO_STREAM_PATCH].mute = false;
+ mStreamTypes[AUDIO_STREAM_CALL_ASSISTANT].volume = 1.0f;
+ mStreamTypes[AUDIO_STREAM_CALL_ASSISTANT].mute = false;
}
- // Audio patch and call assistant volume are always max
- mStreamTypes[AUDIO_STREAM_PATCH].volume = 1.0f;
- mStreamTypes[AUDIO_STREAM_PATCH].mute = false;
- mStreamTypes[AUDIO_STREAM_CALL_ASSISTANT].volume = 1.0f;
- mStreamTypes[AUDIO_STREAM_CALL_ASSISTANT].mute = false;
-
if (mAudioHwDev) {
if (mAudioHwDev->canSetMasterVolume()) {
mMasterVolume = 1.0;
@@ -11097,6 +11198,21 @@
}
}
+status_t MmapPlaybackThread::setPortsVolume(
+ const std::vector<audio_port_handle_t>& portIds, float volume) {
+ audio_utils::lock_guard _l(mutex());
+ for (const auto& portId : portIds) {
+ for (const sp<IAfMmapTrack>& track : mActiveTracks) {
+ if (portId == track->portId()) {
+ track->setPortVolume(volume);
+ break;
+ }
+ }
+ }
+ broadcast_l();
+ return NO_ERROR;
+}
+
void MmapPlaybackThread::invalidateTracks(audio_stream_type_t streamType)
{
audio_utils::lock_guard _l(mutex());
@@ -11130,14 +11246,26 @@
void MmapPlaybackThread::processVolume_l()
NO_THREAD_SAFETY_ANALYSIS // access of track->processMuteEvent_l
{
- float volume;
-
- if (mMasterMute || streamMuted_l()) {
- volume = 0;
+ float volume = 0;
+ if (!audioserver_flags::portid_volume_management()) {
+ if (mMasterMute || streamMuted_l()) {
+ volume = 0;
+ } else {
+ volume = mMasterVolume * streamVolume_l();
+ }
} else {
- volume = mMasterVolume * streamVolume_l();
+ if (mMasterMute) {
+ volume = 0;
+ } else {
+ // All mmap tracks are declared with the same audio attributes to the audio policy
+ // manager. Hence, they follow the same routing / volume group. Any change of volume
+ // will be broadcasted to all tracks. Thus, take arbitrarily first track volume.
+ size_t numtracks = mActiveTracks.size();
+ if (numtracks) {
+ volume = mMasterVolume * mActiveTracks[0]->getPortVolume();
+ }
+ }
}
-
if (volume != mHalVolFloat) {
// Convert volumes from float to 8.24
uint32_t vol = (uint32_t)(volume * (1 << 24));
@@ -11170,14 +11298,25 @@
}
for (const sp<IAfMmapTrack>& track : mActiveTracks) {
track->setMetadataHasChanged();
- track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
- /*muteState=*/{mMasterMute,
- streamVolume_l() == 0.f,
- streamMuted_l(),
- // TODO(b/241533526): adjust logic to include mute from AppOps
- false /*muteFromPlaybackRestricted*/,
- false /*muteFromClientVolume*/,
- false /*muteFromVolumeShaper*/});
+ if (!audioserver_flags::portid_volume_management()) {
+ track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
+ /*muteState=*/{mMasterMute,
+ streamVolume_l() == 0.f,
+ streamMuted_l(),
+ // TODO(b/241533526): adjust logic to include mute from AppOps
+ false /*muteFromPlaybackRestricted*/,
+ false /*muteFromClientVolume*/,
+ false /*muteFromVolumeShaper*/});
+ } else {
+ track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
+ /*muteState=*/{mMasterMute,
+ track->getPortVolume() == 0.f,
+ /* muteFromStreamMuted= */ false,
+ // TODO(b/241533526): adjust logic to include mute from AppOps
+ false /*muteFromPlaybackRestricted*/,
+ false /*muteFromClientVolume*/,
+ false /*muteFromVolumeShaper*/});
+ }
}
}
}
@@ -11284,9 +11423,13 @@
void MmapPlaybackThread::dumpInternals_l(int fd, const Vector<String16>& args)
{
MmapThread::dumpInternals_l(fd, args);
-
- dprintf(fd, " Stream type: %d Stream volume: %f HAL volume: %f Stream mute %d\n",
- mStreamType, streamVolume_l(), mHalVolFloat, streamMuted_l());
+ if (!audioserver_flags::portid_volume_management()) {
+ dprintf(fd, " Stream type: %d Stream volume: %f HAL volume: %f Stream mute %d",
+ mStreamType, streamVolume_l(), mHalVolFloat, streamMuted_l());
+ } else {
+ dprintf(fd, " HAL volume: %f", mHalVolFloat);
+ }
+ dprintf(fd, "\n");
dprintf(fd, " Master volume: %f Master mute %d\n", mMasterVolume, mMasterMute);
}
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 10a77ef..a7a2630 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -836,6 +836,12 @@
typename SortedVector<sp<T>>::iterator end() {
return mActiveTracks.end();
}
+ typename SortedVector<const sp<T>>::iterator begin() const {
+ return mActiveTracks.begin();
+ }
+ typename SortedVector<const sp<T>>::iterator end() const {
+ return mActiveTracks.end();
+ }
// Due to Binder recursion optimization, clear() and updatePowerState()
// cannot be called from a Binder thread because they may call back into
@@ -1011,6 +1017,9 @@
void setStreamVolume(audio_stream_type_t stream, float value) final EXCLUDES_ThreadBase_Mutex;
void setStreamMute(audio_stream_type_t stream, bool muted) final EXCLUDES_ThreadBase_Mutex;
float streamVolume(audio_stream_type_t stream) const final EXCLUDES_ThreadBase_Mutex;
+ status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume)
+ final EXCLUDES_ThreadBase_Mutex;
+
void setVolumeForOutput_l(float left, float right) const final;
sp<IAfTrack> createTrack_l(
@@ -1035,7 +1044,8 @@
const sp<media::IAudioTrackCallback>& callback,
bool isSpatialized,
bool isBitPerfect,
- audio_output_flags_t* afTrackFlags) final
+ audio_output_flags_t* afTrackFlags,
+ float volume) final
REQUIRES(audio_utils::AudioFlinger_Mutex);
bool isTrackActive(const sp<IAfTrack>& track) const final {
@@ -2385,6 +2395,8 @@
void setStreamVolume(audio_stream_type_t stream, float value) final EXCLUDES_ThreadBase_Mutex;
void setStreamMute(audio_stream_type_t stream, bool muted) final EXCLUDES_ThreadBase_Mutex;
float streamVolume(audio_stream_type_t stream) const final EXCLUDES_ThreadBase_Mutex;
+ status_t setPortsVolume(const std::vector<audio_port_handle_t>& portIds, float volume)
+ final EXCLUDES_ThreadBase_Mutex;
void setMasterMute_l(bool muted) REQUIRES(mutex()) { mMasterMute = muted; }
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index a0b85f7..1342b7b 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -347,7 +347,7 @@
size_t mBufferSize; // size of mBuffer in bytes
// we don't really need a lock for these
MirroredVariable<track_state> mState;
- const audio_attributes_t mAttr;
+ audio_attributes_t mAttr;
const uint32_t mSampleRate; // initial sample rate only; for tracks which
// support dynamic rates, the current value is in control block
const audio_format_t mFormat;
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index f5f11cc..5aa58a2 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -715,7 +715,8 @@
size_t frameCountToBeReady,
float speed,
bool isSpatialized,
- bool isBitPerfect) {
+ bool isBitPerfect,
+ float volume) {
return sp<Track>::make(thread,
client,
streamType,
@@ -736,7 +737,8 @@
frameCountToBeReady,
speed,
isSpatialized,
- isBitPerfect);
+ isBitPerfect,
+ volume);
}
// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
@@ -761,7 +763,8 @@
size_t frameCountToBeReady,
float speed,
bool isSpatialized,
- bool isBitPerfect)
+ bool isBitPerfect,
+ float volume)
: TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
// TODO: Using unsecurePointer() has some associated security pitfalls
// (see declaration for details).
@@ -797,7 +800,8 @@
mFlags(flags),
mSpeed(speed),
mIsSpatialized(isSpatialized),
- mIsBitPerfect(isBitPerfect)
+ mIsBitPerfect(isBitPerfect),
+ mVolume(volume)
{
// client == 0 implies sharedBuffer == 0
ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));
@@ -843,6 +847,14 @@
thread->fastTrackAvailMask_l() &= ~(1 << i);
}
+ populateUsageAndContentTypeFromStreamType();
+
+ // Audio patch and call assistant volume are always max
+ if (mAttr.usage == AUDIO_USAGE_CALL_ASSISTANT
+ || mAttr.usage == AUDIO_USAGE_VIRTUAL_SOURCE) {
+ mVolume = 1.0f;
+ }
+
mServerLatencySupported = checkServerLatencySupported(format, flags);
#ifdef TEE_SINK
mTee.setId(std::string("_") + std::to_string(mThreadIoHandle)
@@ -865,6 +877,62 @@
mTrackMetrics.logConstructor(creatorPid, uid, id(), traits, streamType);
}
+// When attributes are undefined, derive default values from stream type.
+// See AudioAttributes.java, usageForStreamType() and Builder.setInternalLegacyStreamType()
+void Track::populateUsageAndContentTypeFromStreamType() {
+ if (mAttr.usage == AUDIO_USAGE_UNKNOWN) {
+ switch (mStreamType) {
+ case AUDIO_STREAM_VOICE_CALL:
+ mAttr.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
+ mAttr.content_type = AUDIO_CONTENT_TYPE_SPEECH;
+ break;
+ case AUDIO_STREAM_SYSTEM:
+ mAttr.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
+ mAttr.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
+ break;
+ case AUDIO_STREAM_RING:
+ mAttr.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
+ mAttr.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
+ break;
+ case AUDIO_STREAM_MUSIC:
+ mAttr.usage = AUDIO_USAGE_MEDIA;
+ mAttr.content_type = AUDIO_CONTENT_TYPE_MUSIC;
+ break;
+ case AUDIO_STREAM_ALARM:
+ mAttr.usage = AUDIO_USAGE_ALARM;
+ mAttr.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
+ break;
+ case AUDIO_STREAM_NOTIFICATION:
+ mAttr.usage = AUDIO_USAGE_NOTIFICATION;
+ mAttr.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
+ break;
+ case AUDIO_STREAM_DTMF:
+ mAttr.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
+ mAttr.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
+ break;
+ case AUDIO_STREAM_ACCESSIBILITY:
+ mAttr.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
+ mAttr.content_type = AUDIO_CONTENT_TYPE_SPEECH;
+ break;
+ case AUDIO_STREAM_ASSISTANT:
+ mAttr.usage = AUDIO_USAGE_ASSISTANT;
+ mAttr.content_type = AUDIO_CONTENT_TYPE_SPEECH;
+ break;
+ case AUDIO_STREAM_REROUTING:
+ case AUDIO_STREAM_PATCH:
+ mAttr.usage = AUDIO_USAGE_VIRTUAL_SOURCE;
+ // unknown content type
+ break;
+ case AUDIO_STREAM_CALL_ASSISTANT:
+ mAttr.usage = AUDIO_USAGE_CALL_ASSISTANT;
+ mAttr.content_type = AUDIO_CONTENT_TYPE_SPEECH;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
Track::~Track()
{
ALOGV("%s(%d)", __func__, mId);
@@ -923,7 +991,7 @@
result.appendFormat("Type Id Active Client Session Port Id S Flags "
" Format Chn mask SRate "
"ST Usg CT "
- " G db L dB R dB VS dB "
+ " G db L dB R dB VS dB PortVol dB "
" Server FrmCnt FrmRdy F Underruns Flushed BitPerfect InternalMute"
"%s\n",
isServerLatencySupported() ? " Latency" : "");
@@ -1009,7 +1077,7 @@
result.appendFormat("%7s %6u %7u %7u %2s 0x%03X "
"%08X %08X %6u "
"%2u %3x %2x "
- "%5.2g %5.2g %5.2g %5.2g%c "
+ "%5.2g %5.2g %5.2g %5.2g%c %11.2g "
"%08X %6zu%c %6zu %c %9u%c %7u %10s %12s",
active ? "yes" : "no",
(mClient == 0) ? getpid() : mClient->pid(),
@@ -1031,6 +1099,7 @@
20.0 * log10(float_from_gain(gain_minifloat_unpack_right(vlr))),
20.0 * log10(vsVolume.first), // VolumeShaper(s) total volume
vsVolume.second ? 'A' : ' ', // if any VolumeShapers active
+ 20.0 * log10(mVolume),
mCblk->mServer,
bufferSizeInFrames,
@@ -1532,6 +1601,16 @@
return INVALID_OPERATION;
}
+void Track::setPortVolume(float volume) {
+ mVolume = volume;
+ if (mType != TYPE_PATCH) {
+ // Do not recursively propagate a PatchTrack setPortVolume to
+ // downstream PatchTracks.
+ forEachTeePatchTrack_l([volume](const auto& patchTrack) {
+ patchTrack->setPortVolume(volume); });
+ }
+}
+
VolumeShaper::Status Track::applyVolumeShaper(
const sp<VolumeShaper::Configuration>& configuration,
const sp<VolumeShaper::Operation>& operation)
@@ -1587,59 +1666,6 @@
.gain = mFinalVolume,
};
- // When attributes are undefined, derive default values from stream type.
- // See AudioAttributes.java, usageForStreamType() and Builder.setInternalLegacyStreamType()
- if (mAttr.usage == AUDIO_USAGE_UNKNOWN) {
- switch (mStreamType) {
- case AUDIO_STREAM_VOICE_CALL:
- metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
- metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
- break;
- case AUDIO_STREAM_SYSTEM:
- metadata.base.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
- metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
- break;
- case AUDIO_STREAM_RING:
- metadata.base.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
- metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
- break;
- case AUDIO_STREAM_MUSIC:
- metadata.base.usage = AUDIO_USAGE_MEDIA;
- metadata.base.content_type = AUDIO_CONTENT_TYPE_MUSIC;
- break;
- case AUDIO_STREAM_ALARM:
- metadata.base.usage = AUDIO_USAGE_ALARM;
- metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
- break;
- case AUDIO_STREAM_NOTIFICATION:
- metadata.base.usage = AUDIO_USAGE_NOTIFICATION;
- metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
- break;
- case AUDIO_STREAM_DTMF:
- metadata.base.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
- metadata.base.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
- break;
- case AUDIO_STREAM_ACCESSIBILITY:
- metadata.base.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
- metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
- break;
- case AUDIO_STREAM_ASSISTANT:
- metadata.base.usage = AUDIO_USAGE_ASSISTANT;
- metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
- break;
- case AUDIO_STREAM_REROUTING:
- metadata.base.usage = AUDIO_USAGE_VIRTUAL_SOURCE;
- // unknown content type
- break;
- case AUDIO_STREAM_CALL_ASSISTANT:
- metadata.base.usage = AUDIO_USAGE_CALL_ASSISTANT;
- metadata.base.content_type = AUDIO_CONTENT_TYPE_SPEECH;
- break;
- default:
- break;
- }
- }
-
metadata.channel_mask = mChannelMask;
strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
*backInserter++ = metadata;
@@ -2191,14 +2217,13 @@
size_t frameCount,
const AttributionSourceState& attributionSource)
: Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
- audio_attributes_t{} /* currently unused for output track */,
+ AUDIO_ATTRIBUTES_INITIALIZER ,
sampleRate, format, channelMask, frameCount,
nullptr /* buffer */, (size_t)0 /* bufferSize */, nullptr /* sharedBuffer */,
AUDIO_SESSION_NONE, getpid(), attributionSource, AUDIO_OUTPUT_FLAG_NONE,
TYPE_OUTPUT),
mActive(false), mSourceThread(sourceThread)
{
-
if (mCblk != NULL) {
mOutBuffer.frameCount = 0;
playbackThread->addOutputTrack_l(this);
@@ -2464,7 +2489,8 @@
* as soon as possible to have
* the lowest possible latency
* even if it might glitch. */
- float speed)
+ float speed,
+ float volume)
{
return sp<PatchTrack>::make(
playbackThread,
@@ -2478,7 +2504,8 @@
flags,
timeout,
frameCountToBeReady,
- speed);
+ speed,
+ volume);
}
PatchTrack::PatchTrack(IAfPlaybackThread* playbackThread,
@@ -2492,13 +2519,15 @@
audio_output_flags_t flags,
const Timeout& timeout,
size_t frameCountToBeReady,
- float speed)
+ float speed,
+ float volume)
: Track(playbackThread, NULL, streamType,
- audio_attributes_t{} /* currently unused for patch track */,
+ AUDIO_ATTRIBUTES_INITIALIZER,
sampleRate, format, channelMask, frameCount,
buffer, bufferSize, nullptr /* sharedBuffer */,
AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags,
- TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady, speed),
+ TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady, speed,
+ false /*isSpatialized*/, false /*isBitPerfect*/, volume),
PatchTrackBase(mCblk ? new AudioTrackClientProxy(mCblk, mBuffer, frameCount, mFrameSize,
true /*clientInServer*/) : nullptr,
playbackThread, timeout)
@@ -3482,7 +3511,8 @@
bool isOut,
const android::content::AttributionSourceState& attributionSource,
pid_t creatorPid,
- audio_port_handle_t portId)
+ audio_port_handle_t portId,
+ float volume)
{
return sp<MmapTrack>::make(
thread,
@@ -3494,7 +3524,8 @@
isOut,
attributionSource,
creatorPid,
- portId);
+ portId,
+ volume);
}
MmapTrack::MmapTrack(IAfThreadBase* thread,
@@ -3506,7 +3537,8 @@
bool isOut,
const AttributionSourceState& attributionSource,
pid_t creatorPid,
- audio_port_handle_t portId)
+ audio_port_handle_t portId,
+ float volume)
: TrackBase(thread, NULL, attr, sampleRate, format,
channelMask, (size_t)0 /* frameCount */,
nullptr /* buffer */, (size_t)0 /* bufferSize */,
@@ -3517,10 +3549,15 @@
TYPE_DEFAULT, portId,
std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_MMAP) + std::to_string(portId)),
mPid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.pid))),
- mSilenced(false), mSilencedNotified(false)
+ mSilenced(false), mSilencedNotified(false), mVolume(volume)
{
// Once this item is logged by the server, the client can add properties.
mTrackMetrics.logConstructor(creatorPid, uid(), id());
+ if (isOut && (attr.usage == AUDIO_USAGE_CALL_ASSISTANT
+ || attr.usage == AUDIO_USAGE_VIRTUAL_SOURCE)) {
+ // Audio patch and call assistant volume are always max
+ mVolume = 1.0f;
+ }
}
MmapTrack::~MmapTrack()
@@ -3599,8 +3636,8 @@
void MmapTrack::appendDumpHeader(String8& result) const
{
- result.appendFormat("Client Session Port Id Format Chn mask SRate Flags %s\n",
- isOut() ? "Usg CT": "Source");
+ result.appendFormat("Client Session Port Id Format Chn mask SRate Flags %s %s\n",
+ isOut() ? "Usg CT": "Source", isOut() ? "PortVol dB" : "");
}
void MmapTrack::appendDump(String8& result, bool active __unused) const
@@ -3615,6 +3652,7 @@
mAttr.flags);
if (isOut()) {
result.appendFormat("%3x %2x", mAttr.usage, mAttr.content_type);
+ result.appendFormat("%11.2g", 20.0 * log10(mVolume));
} else {
result.appendFormat("%6x", mAttr.source);
}
diff --git a/services/audioflinger/datapath/VolumePortInterface.h b/services/audioflinger/datapath/VolumePortInterface.h
new file mode 100644
index 0000000..fb1c463
--- /dev/null
+++ b/services/audioflinger/datapath/VolumePortInterface.h
@@ -0,0 +1,29 @@
+/*
+ * 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 <system/audio.h>
+
+namespace android {
+
+class VolumePortInterface : public virtual RefBase {
+public:
+ virtual void setPortVolume(float volume) = 0;
+ virtual float getPortVolume() const = 0;
+};
+
+} // namespace android
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 1bac259..e849bb4 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -147,7 +147,8 @@
std::vector<audio_io_handle_t> *secondaryOutputs,
output_type_t *outputType,
bool *isSpatialized,
- bool *isBitPerfect) = 0;
+ bool *isBitPerfect,
+ float *volume) = 0;
// indicates to the audio policy manager that the output starts being used by corresponding
// stream.
virtual status_t startOutput(audio_port_handle_t portId) = 0;
@@ -515,6 +516,18 @@
// for each output (destination device) it is attached to.
virtual status_t setStreamVolume(audio_stream_type_t stream, float volume,
audio_io_handle_t output, int delayMs = 0) = 0;
+ /**
+ * Set volume for given AudioTrack port ids for a particular output.
+ * For the same user setting, a given volume group and associated output port id
+ * can have different volumes for each output (destination device) it is attached to.
+ * @param ports to consider
+ * @param volume to apply
+ * @param output to consider
+ * @param delayMs to use
+ * @return NO_ERROR if successful
+ */
+ virtual status_t setPortsVolume(const std::vector<audio_port_handle_t>& ports, float volume,
+ audio_io_handle_t output, int delayMs = 0) = 0;
// function enabling to send proprietary informations directly from audio policy manager to
// audio hardware interface.
diff --git a/services/audiopolicy/common/include/SpatializerHelper.h b/services/audiopolicy/common/include/SpatializerHelper.h
new file mode 100644
index 0000000..2eb6613
--- /dev/null
+++ b/services/audiopolicy/common/include/SpatializerHelper.h
@@ -0,0 +1,42 @@
+/*
+ * 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 <com_android_media_audio.h>
+#include <cutils/properties.h>
+
+namespace android {
+
+class SpatializerHelper {
+ public:
+ /**
+ * @brief Check if the stereo spatialization feature turned on by:
+ * - sysprop "ro.audio.stereo_spatialization_enabled" is true
+ * - com_android_media_audio_stereo_spatialization flag is on
+ *
+ * @return true if the stereo spatialization feature is enabled
+ * @return false if the stereo spatialization feature is not enabled
+ */
+ static bool isStereoSpatializationFeatureEnabled() {
+ static const bool stereoSpatializationEnabled =
+ property_get_bool("ro.audio.stereo_spatialization_enabled", false) &&
+ com_android_media_audio_stereo_spatialization();
+ return stereoSpatializationEnabled;
+ }
+};
+
+} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/Android.bp b/services/audiopolicy/common/managerdefinitions/Android.bp
index 051e975..4dedcd6 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.bp
+++ b/services/audiopolicy/common/managerdefinitions/Android.bp
@@ -39,6 +39,8 @@
"android.media.audiopolicy-aconfig-cc",
"audioclient-types-aidl-cpp",
"audiopolicy-types-aidl-cpp",
+ "com.android.media.audioserver-aconfig-cc",
+ "libaconfig_storage_read_api_cc",
"libaudioclient_aidl_conversion",
"libaudiofoundation",
"libaudiopolicy",
@@ -51,6 +53,7 @@
"libmedia_helper",
"libutils",
"libxml2",
+ "server_configurable_flags",
],
export_shared_lib_headers: [
"libaudiofoundation",
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index bfb28a5..3c296e7 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -491,6 +491,13 @@
virtual std::string info() const override;
+ /**
+ * Finds all ports matching the given volume source.
+ * @param vs to be considered
+ * @return vector of ports following the given volume source.
+ */
+ std::vector<audio_port_handle_t> getPortsForVolumeSource(const VolumeSource& vs);
+
const sp<IOProfile> mProfile; // I/O profile this output derives from
audio_io_handle_t mIoHandle; // output handle
uint32_t mLatency; //
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 6fef215..848051c 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -27,6 +27,7 @@
#include "HwModule.h"
#include "TypeConverter.h"
#include "policy.h"
+#include <com_android_media_audioserver.h>
#include <media/AudioGain.h>
#include <media/AudioParameter.h>
#include <media/AudioPolicy.h>
@@ -34,6 +35,8 @@
// A device mask for all audio output devices that are considered "remote" when evaluating
// active output devices in isStreamActiveRemotely()
+namespace audioserver_flags = com::android::media::audioserver;
+
namespace android {
static const DeviceTypeSet& getAllOutRemoteDevices() {
@@ -498,17 +501,33 @@
const DeviceTypeSet& deviceTypes, uint32_t delayMs) {
// volume source active and more than one volume source is active, otherwise, no-op or let
// setVolume controlling SW and/or HW Gains
- if (!streamTypes.empty() && isActive(vs) && (getActiveVolumeSources().size() > 1)) {
- for (const auto& devicePort : devices()) {
- if (isSingleDeviceType(deviceTypes, devicePort->type()) &&
+ if (!audioserver_flags::portid_volume_management()) {
+ if (!streamTypes.empty() && isActive(vs) && (getActiveVolumeSources().size() > 1)) {
+ for (const auto& devicePort : devices()) {
+ if (isSingleDeviceType(deviceTypes, devicePort->type()) &&
devicePort->hasGainController(true /*canUseForVolume*/)) {
- float volumeAmpl = muted ? 0.0f : Volume::DbToAmpl(0);
- ALOGV("%s: output: %d, vs: %d, muted: %d, active vs count: %zu", __func__,
- mIoHandle, vs, muted, getActiveVolumeSources().size());
- for (const auto &stream : streamTypes) {
- mClientInterface->setStreamVolume(stream, volumeAmpl, mIoHandle, delayMs);
+ float volumeAmpl = muted ? 0.0f : Volume::DbToAmpl(0);
+ ALOGV("%s: output: %d, vs: %d, muted: %d, active vs count: %zu", __func__,
+ mIoHandle, vs, muted, getActiveVolumeSources().size());
+ for (const auto &stream : streamTypes) {
+ mClientInterface->setStreamVolume(stream, volumeAmpl, mIoHandle, delayMs);
+ }
+ return;
}
- return;
+ }
+ }
+ } else {
+ if (isActive(vs) && (getActiveVolumeSources().size() > 1)) {
+ for (const auto &devicePort: devices()) {
+ if (isSingleDeviceType(deviceTypes, devicePort->type()) &&
+ devicePort->hasGainController(true /*canUseForVolume*/)) {
+ float volumeAmpl = muted ? 0.0f : Volume::DbToAmpl(0);
+ ALOGV("%s: output: %d, vs: %d, muted: %d, active vs count: %zu", __func__,
+ mIoHandle, vs, muted, getActiveVolumeSources().size());
+ mClientInterface->setPortsVolume(
+ getPortsForVolumeSource(vs), volumeAmpl, mIoHandle, delayMs);
+ return;
+ }
}
}
}
@@ -528,8 +547,14 @@
VolumeSource callVolSrc = getVoiceSource();
if (callVolSrc != VOLUME_SOURCE_NONE && volumeDb != getCurVolume(callVolSrc)) {
setCurVolume(callVolSrc, volumeDb, true);
- mClientInterface->setStreamVolume(
- AUDIO_STREAM_VOICE_CALL, Volume::DbToAmpl(volumeDb), mIoHandle, delayMs);
+ float volumeAmpl = Volume::DbToAmpl(volumeDb);
+ if (audioserver_flags::portid_volume_management()) {
+ mClientInterface->setPortsVolume(getPortsForVolumeSource(callVolSrc),
+ volumeAmpl, mIoHandle, delayMs);
+ } else {
+ mClientInterface->setStreamVolume(AUDIO_STREAM_VOICE_CALL,
+ volumeAmpl, mIoHandle, delayMs);
+ }
}
}
return false;
@@ -539,25 +564,34 @@
}
for (const auto& devicePort : devices()) {
// APM loops on all group, so filter on active group to set the port gain,
- // let the other groups set the stream volume as per legacy
+ // let the other groups set the sw volume as per legacy
// TODO: Pass in the device address and check against it.
if (isSingleDeviceType(deviceTypes, devicePort->type()) &&
devicePort->hasGainController(true) && isActive(vs)) {
ALOGV("%s: device %s has gain controller", __func__, devicePort->toString().c_str());
// @todo: here we might be in trouble if the SwOutput has several active clients with
// different Volume Source (or if we allow several curves within same volume group)
- //
- // @todo: default stream volume to max (0) when using HW Port gain?
- // Allows to set SW Gain on AudioFlinger if:
- // -volume group has explicit stream(s) associated
- // -volume group with no explicit stream(s) is the only active source on this output
- // Allows to mute SW Gain on AudioFlinger only for volume group with explicit stream(s)
- if (!streamTypes.empty() || (getActiveVolumeSources().size() == 1)) {
- const bool canMute = muted && (volumeDb != 0.0f) && !streamTypes.empty();
- float volumeAmpl = canMute ? 0.0f : Volume::DbToAmpl(0);
- for (const auto &stream : streams) {
- mClientInterface->setStreamVolume(stream, volumeAmpl, mIoHandle, delayMs);
+ if (!audioserver_flags::portid_volume_management()) {
+ // @todo: default stream volume to max (0) when using HW Port gain?
+ // Allows to set SW Gain on AudioFlinger if:
+ // -volume group has explicit stream(s) associated
+ // -volume group with no explicit stream(s) is the only active source on this
+ // output
+ // Allows to mute SW Gain on AudioFlinger only for volume group with explicit
+ // stream(s)
+ if (!streamTypes.empty() || (getActiveVolumeSources().size() == 1)) {
+ const bool canMute = muted && (volumeDb != 0.0f) && !streamTypes.empty();
+ float volumeAmpl = canMute ? 0.0f : Volume::DbToAmpl(0);
+ for (const auto &stream: streams) {
+ mClientInterface->setStreamVolume(stream, volumeAmpl, mIoHandle, delayMs);
+ }
}
+ } else {
+ float volumeAmpl = (muted && volumeDb != 0.0f) ? 0.0f : Volume::DbToAmpl(0);
+ ALOGV("%s: output: %d, vs: %d, active vs count: %zu", __func__,
+ mIoHandle, vs, getActiveVolumeSources().size());
+ mClientInterface->setPortsVolume(
+ getPortsForVolumeSource(vs), volumeAmpl, mIoHandle, delayMs);
}
AudioGains gains = devicePort->getGains();
int gainMinValueInMb = gains[0]->getMinValueInMb();
@@ -577,20 +611,47 @@
// Force VOICE_CALL to track BLUETOOTH_SCO stream volume when bluetooth audio is enabled
float volumeAmpl = Volume::DbToAmpl(getCurVolume(vs));
if (hasStream(streams, AUDIO_STREAM_BLUETOOTH_SCO)) {
- mClientInterface->setStreamVolume(AUDIO_STREAM_VOICE_CALL, volumeAmpl, mIoHandle, delayMs);
VolumeSource callVolSrc = getVoiceSource();
+ if (audioserver_flags::portid_volume_management()) {
+ if (callVolSrc != VOLUME_SOURCE_NONE) {
+ mClientInterface->setPortsVolume(getPortsForVolumeSource(callVolSrc), volumeAmpl,
+ mIoHandle, delayMs);
+ }
+ } else {
+ mClientInterface->setStreamVolume(AUDIO_STREAM_VOICE_CALL, volumeAmpl, mIoHandle,
+ delayMs);
+ }
if (callVolSrc != VOLUME_SOURCE_NONE) {
setCurVolume(callVolSrc, getCurVolume(vs), true);
}
}
- for (const auto &stream : streams) {
- ALOGV("%s output %d for volumeSource %d, volume %f, delay %d stream=%s", __func__,
- mIoHandle, vs, volumeDb, delayMs, toString(stream).c_str());
- mClientInterface->setStreamVolume(stream, volumeAmpl, mIoHandle, delayMs);
+ if (audioserver_flags::portid_volume_management()) {
+ ALOGV("%s output %d for volumeSource %d, volume %f, delay %d active=%d", __func__,
+ mIoHandle, vs, volumeDb, delayMs, isActive(vs));
+ mClientInterface->setPortsVolume(getPortsForVolumeSource(vs), volumeAmpl, mIoHandle,
+ delayMs);
+ } else {
+ for (const auto &stream : streams) {
+ ALOGV("%s output %d for volumeSource %d, volume %f, delay %d stream=%s", __func__,
+ mIoHandle, vs, volumeDb, delayMs, toString(stream).c_str());
+ mClientInterface->setStreamVolume(stream, volumeAmpl, mIoHandle, delayMs);
+ }
}
return true;
}
+std::vector<audio_port_handle_t> SwAudioOutputDescriptor::getPortsForVolumeSource(
+ const VolumeSource& vs)
+{
+ std::vector<audio_port_handle_t> portsForVolumeSource;
+ for (const auto& client : getClientIterable()) {
+ if (client->volumeSource() == vs) {
+ portsForVolumeSource.push_back(client->portId());
+ }
+ }
+ return portsForVolumeSource;
+}
+
status_t SwAudioOutputDescriptor::open(const audio_config_t *halConfig,
const audio_config_base_t *mixerConfig,
const DeviceVector &devices,
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp
index 3dc2229..c9a77a4 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp
@@ -38,6 +38,8 @@
shared_libs: [
"libaudiopolicycomponents",
"libaudiopolicyengineconfigurable",
+ "libbase",
+ "libcutils",
"liblog",
"libmedia_helper",
"libparameter",
diff --git a/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-0 b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-0
new file mode 100644
index 0000000..4d539b7
--- /dev/null
+++ b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-0
Binary files differ
diff --git a/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-1 b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-1
new file mode 100644
index 0000000..8af7d2f
--- /dev/null
+++ b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-1
Binary files differ
diff --git a/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-2 b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-2
new file mode 100644
index 0000000..b89b77e
--- /dev/null
+++ b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-2
Binary files differ
diff --git a/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-3 b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-3
new file mode 100644
index 0000000..6e966e9
--- /dev/null
+++ b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-3
Binary files differ
diff --git a/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-4 b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-4
new file mode 100644
index 0000000..8ccf24d
--- /dev/null
+++ b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-4
Binary files differ
diff --git a/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-5 b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-5
new file mode 100644
index 0000000..223d1df
--- /dev/null
+++ b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-5
Binary files differ
diff --git a/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-6 b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-6
new file mode 100644
index 0000000..ad54b83
--- /dev/null
+++ b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-6
Binary files differ
diff --git a/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-7 b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-7
new file mode 100644
index 0000000..f4eabf4
--- /dev/null
+++ b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-7
Binary files differ
diff --git a/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp b/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
index 6416a47..fd40c04 100644
--- a/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
+++ b/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
@@ -265,6 +265,7 @@
AudioPolicyInterface::output_type_t outputType;
bool isSpatialized;
bool isBitPerfect;
+ float volume;
// TODO b/182392769: use attribution source util
AttributionSourceState attributionSource;
@@ -272,7 +273,7 @@
attributionSource.token = sp<BBinder>::make();
if (mManager->getOutputForAttr(&attr, output, AUDIO_SESSION_NONE, &stream, attributionSource,
&config, &flags, selectedDeviceId, portId, {}, &outputType, &isSpatialized,
- &isBitPerfect) != OK) {
+ &isBitPerfect, &volume) != OK) {
return false;
}
if (*output == AUDIO_IO_HANDLE_NONE || *portId == AUDIO_PORT_HANDLE_NONE) {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index d7d5e40..718f958 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -45,7 +45,6 @@
#include <android_media_audiopolicy.h>
#include <com_android_media_audioserver.h>
#include <cutils/bitops.h>
-#include <cutils/properties.h>
#include <media/AudioParameter.h>
#include <policy.h>
#include <private/android_filesystem_config.h>
@@ -55,6 +54,7 @@
#include <utils/Log.h>
#include "AudioPolicyManager.h"
+#include "SpatializerHelper.h"
#include "TypeConverter.h"
namespace android {
@@ -1489,7 +1489,8 @@
std::vector<audio_io_handle_t> *secondaryOutputs,
output_type_t *outputType,
bool *isSpatialized,
- bool *isBitPerfect)
+ bool *isBitPerfect,
+ float *volume)
{
// The supplied portId must be AUDIO_PORT_HANDLE_NONE
if (*portId != AUDIO_PORT_HANDLE_NONE) {
@@ -1545,6 +1546,8 @@
outputDesc->mPolicyMix);
outputDesc->addClient(clientDesc);
+ *volume = Volume::DbToAmpl(outputDesc->getCurVolume(toVolumeSource(resultAttr)));
+
ALOGV("%s() returns output %d requestedPortId %d selectedDeviceId %d for port ID %d", __func__,
*output, requestedPortId, *selectedDeviceId, *portId);
@@ -3797,9 +3800,10 @@
// 1: An offloaded output. If the effect ends up not being offloadable,
// AudioFlinger will invalidate the track and the offloaded output
// will be closed causing the effect to be moved to a PCM output.
- // 2: A deep buffer output
- // 3: The primary output
- // 4: the first output in the list
+ // 2: Spatializer output if the stereo spatializer feature enabled
+ // 3: A deep buffer output
+ // 4: The primary output
+ // 5: the first output in the list
DeviceVector devices = mEngine->getOutputDevicesForAttributes(
attributes_initializer(AUDIO_USAGE_MEDIA), nullptr, false /*fromCache*/);
@@ -3814,28 +3818,36 @@
while (output == AUDIO_IO_HANDLE_NONE) {
audio_io_handle_t outputOffloaded = AUDIO_IO_HANDLE_NONE;
+ audio_io_handle_t outputSpatializer = AUDIO_IO_HANDLE_NONE;
audio_io_handle_t outputDeepBuffer = AUDIO_IO_HANDLE_NONE;
audio_io_handle_t outputPrimary = AUDIO_IO_HANDLE_NONE;
- for (audio_io_handle_t output : outputs) {
- sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(output);
+ for (audio_io_handle_t outputLoop : outputs) {
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(outputLoop);
if (activeOnly && !desc->isActive(toVolumeSource(AUDIO_STREAM_MUSIC))) {
continue;
}
ALOGV("selectOutputForMusicEffects activeOnly %d output %d flags 0x%08x",
- activeOnly, output, desc->mFlags);
+ activeOnly, outputLoop, desc->mFlags);
if ((desc->mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
- outputOffloaded = output;
+ outputOffloaded = outputLoop;
+ }
+ if ((desc->mFlags & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0) {
+ if (SpatializerHelper::isStereoSpatializationFeatureEnabled()) {
+ outputSpatializer = outputLoop;
+ }
}
if ((desc->mFlags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) != 0) {
- outputDeepBuffer = output;
+ outputDeepBuffer = outputLoop;
}
if ((desc->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) != 0) {
- outputPrimary = output;
+ outputPrimary = outputLoop;
}
}
if (outputOffloaded != AUDIO_IO_HANDLE_NONE) {
output = outputOffloaded;
+ } else if (outputSpatializer != AUDIO_IO_HANDLE_NONE) {
+ output = outputSpatializer;
} else if (outputDeepBuffer != AUDIO_IO_HANDLE_NONE) {
output = outputDeepBuffer;
} else if (outputPrimary != AUDIO_IO_HANDLE_NONE) {
@@ -6363,13 +6375,10 @@
// mode is not requested.
if (config != nullptr && *config != AUDIO_CONFIG_INITIALIZER) {
- static const bool stereo_spatialization_prop_enabled =
- property_get_bool("ro.audio.stereo_spatialization_enabled", false);
const bool channel_mask_spatialized =
- (stereo_spatialization_prop_enabled
- && com_android_media_audio_stereo_spatialization())
- ? audio_channel_mask_contains_stereo(config->channel_mask)
- : audio_is_channel_mask_spatialized(config->channel_mask);
+ SpatializerHelper::isStereoSpatializationFeatureEnabled()
+ ? audio_channel_mask_contains_stereo(config->channel_mask)
+ : audio_is_channel_mask_spatialized(config->channel_mask);
if (!channel_mask_spatialized) {
return false;
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index c0a5012..4736980 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -128,7 +128,8 @@
std::vector<audio_io_handle_t> *secondaryOutputs,
output_type_t *outputType,
bool *isSpatialized,
- bool *isBitPerfect) override;
+ bool *isBitPerfect,
+ float *volume) override;
virtual status_t startOutput(audio_port_handle_t portId);
virtual status_t stopOutput(audio_port_handle_t portId);
virtual bool releaseOutput(audio_port_handle_t portId);
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index 22fc151..9a5365c 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -191,6 +191,16 @@
delay_ms);
}
+status_t AudioPolicyService::AudioPolicyClient::setPortsVolume(
+ const std::vector<audio_port_handle_t> &ports, float volume, audio_io_handle_t output,
+ int delayMs)
+{
+ if (ports.empty()) {
+ return NO_ERROR;
+ }
+ return mAudioPolicyService->setPortsVolume(ports, volume, output, delayMs);
+}
+
void AudioPolicyService::AudioPolicyClient::setParameters(audio_io_handle_t io_handle,
const String8& keyValuePairs,
int delay_ms)
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index e598897..bb41d00 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -423,6 +423,7 @@
AudioPolicyInterface::output_type_t outputType;
bool isSpatialized = false;
bool isBitPerfect = false;
+ float volume;
status_t result = mAudioPolicyManager->getOutputForAttr(&attr, &output, session,
&stream,
attributionSource,
@@ -431,7 +432,8 @@
&secondaryOutputs,
&outputType,
&isSpatialized,
- &isBitPerfect);
+ &isBitPerfect,
+ &volume);
// FIXME: Introduce a way to check for the the telephony device before opening the output
if (result == NO_ERROR) {
@@ -495,6 +497,7 @@
_aidl_return->isBitPerfect = isBitPerfect;
_aidl_return->attr = VALUE_OR_RETURN_BINDER_STATUS(
legacy2aidl_audio_attributes_t_AudioAttributes(attr));
+ _aidl_return->volume = volume;
} else {
_aidl_return->configBase.format = VALUE_OR_RETURN_BINDER_STATUS(
legacy2aidl_audio_format_t_AudioFormatDescription(config.format));
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index cbc0b41..2e0aa3c 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -1418,7 +1418,7 @@
}
}, mediautils::TimeCheck::getDefaultTimeoutDuration(),
mediautils::TimeCheck::getDefaultSecondChanceDuration(),
- true /* crashOnTimeout */);
+ !property_get_bool("audio.timecheck.disabled", false) /* crashOnTimeout */);
switch (code) {
case SHELL_COMMAND_TRANSACTION: {
@@ -1816,6 +1816,16 @@
data->mIO);
ul.lock();
}break;
+ case SET_PORTS_VOLUME: {
+ VolumePortsData *data = (VolumePortsData *)command->mParam.get();
+ ALOGV("AudioCommandThread() processing set volume Ports %s volume %f, \
+ output %d", data->dumpPorts().c_str(), data->mVolume, data->mIO);
+ ul.unlock();
+ command->mStatus = AudioSystem::setPortsVolume(data->mPorts,
+ data->mVolume,
+ data->mIO);
+ ul.lock();
+ } break;
case SET_PARAMETERS: {
ParametersData *data = (ParametersData *)command->mParam.get();
ALOGV("AudioCommandThread() processing set parameters string %s, io %d",
@@ -2128,6 +2138,23 @@
return sendCommand(command, delayMs);
}
+status_t AudioPolicyService::AudioCommandThread::volumePortsCommand(
+ const std::vector<audio_port_handle_t> &ports, float volume, audio_io_handle_t output,
+ int delayMs)
+{
+ sp<AudioCommand> command = new AudioCommand();
+ command->mCommand = SET_PORTS_VOLUME;
+ sp<VolumePortsData> data = new VolumePortsData();
+ data->mPorts = ports;
+ data->mVolume = volume;
+ data->mIO = output;
+ command->mParam = data;
+ command->mWaitStatus = true;
+ ALOGV("AudioCommandThread() adding set volume ports %s, volume %f, output %d",
+ data->dumpPorts().c_str(), volume, output);
+ return sendCommand(command, delayMs);
+}
+
status_t AudioPolicyService::AudioCommandThread::parametersCommand(audio_io_handle_t ioHandle,
const char *keyValuePairs,
int delayMs)
@@ -2458,6 +2485,31 @@
delayMs = 1;
} break;
+ case SET_PORTS_VOLUME: {
+ VolumePortsData *data = (VolumePortsData *)command->mParam.get();
+ VolumePortsData *data2 = (VolumePortsData *)command2->mParam.get();
+ if (data->mIO != data2->mIO) break;
+ // Can remove command only if port ids list is the same, otherwise, remove from
+ // command 2 all port whose volume will be replaced with command 1 volume.
+ std::vector<audio_port_handle_t> portsOnlyInCommand2{};
+ std::copy_if(data2->mPorts.begin(), data2->mPorts.end(),
+ std::back_inserter(portsOnlyInCommand2), [&](const auto &portId) {
+ return std::find(data->mPorts.begin(), data->mPorts.end(), portId) ==
+ data->mPorts.end();
+ });
+ if (!portsOnlyInCommand2.empty()) {
+ data2->mPorts = portsOnlyInCommand2;
+ break;
+ }
+ ALOGV("Filtering out volume command on output %d for ports %s",
+ data->mIO, data->dumpPorts().c_str());
+ removedCommands.add(command2);
+ command->mTime = command2->mTime;
+ // force delayMs to non 0 so that code below does not request to wait for
+ // command status as the command is now delayed
+ delayMs = 1;
+ } break;
+
case SET_VOICE_VOLUME: {
VoiceVolumeData *data = (VoiceVolumeData *)command->mParam.get();
VoiceVolumeData *data2 = (VoiceVolumeData *)command2->mParam.get();
@@ -2604,6 +2656,12 @@
output, delayMs);
}
+int AudioPolicyService::setPortsVolume(const std::vector<audio_port_handle_t> &ports, float volume,
+ audio_io_handle_t output, int delayMs)
+{
+ return (int)mAudioCommandThread->volumePortsCommand(ports, volume, output, delayMs);
+}
+
int AudioPolicyService::setVoiceVolume(float volume, int delayMs)
{
return (int)mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 92c162f..d5d4f97 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -47,6 +47,7 @@
#include <android/hardware/BnSensorPrivacyListener.h>
#include <android/content/AttributionSourceState.h>
+#include <numeric>
#include <unordered_map>
namespace android {
@@ -354,6 +355,21 @@
float volume,
audio_io_handle_t output,
int delayMs = 0);
+
+ /**
+ * Set a volume on AudioTrack port id(s) for a particular output.
+ * For the same user setting, a volume group (and associated given port of the
+ * client's track) can have different volumes for each output destination device
+ * it is attached to.
+ *
+ * @param ports to consider
+ * @param volume to set
+ * @param output to consider
+ * @param delayMs to use
+ * @return NO_ERROR if successful
+ */
+ virtual status_t setPortsVolume(const std::vector<audio_port_handle_t> &ports, float volume,
+ audio_io_handle_t output, int delayMs = 0);
virtual status_t setVoiceVolume(float volume, int delayMs = 0);
void doOnNewAudioModulesAvailable();
@@ -577,6 +593,7 @@
// commands for tone AudioCommand
enum {
SET_VOLUME,
+ SET_PORTS_VOLUME,
SET_PARAMETERS,
SET_VOICE_VOLUME,
STOP_OUTPUT,
@@ -610,6 +627,8 @@
void exit();
status_t volumeCommand(audio_stream_type_t stream, float volume,
audio_io_handle_t output, int delayMs = 0);
+ status_t volumePortsCommand(const std::vector<audio_port_handle_t> &ports,
+ float volume, audio_io_handle_t output, int delayMs = 0);
status_t parametersCommand(audio_io_handle_t ioHandle,
const char *keyValuePairs, int delayMs = 0);
status_t voiceVolumeCommand(float volume, int delayMs = 0);
@@ -684,6 +703,20 @@
audio_io_handle_t mIO;
};
+ class VolumePortsData : public AudioCommandData {
+ public:
+ std::vector<audio_port_handle_t> mPorts;
+ float mVolume;
+ audio_io_handle_t mIO;
+ std::string dumpPorts() {
+ return std::string("volume ") + std::to_string(mVolume) + " on IO " +
+ std::to_string(mIO) + " and ports " +
+ std::accumulate(std::begin(mPorts), std::end(mPorts), std::string{},
+ [] (const std::string& ls, int rs) {
+ return ls + std::to_string(rs) + " "; });
+ }
+ };
+
class ParametersData : public AudioCommandData {
public:
audio_io_handle_t mIO;
@@ -824,6 +857,19 @@
// set a stream volume for a particular output. For the same user setting, a given stream type can have different volumes
// for each output (destination device) it is attached to.
virtual status_t setStreamVolume(audio_stream_type_t stream, float volume, audio_io_handle_t output, int delayMs = 0);
+ /**
+ * Set a volume on port(s) for a particular output. For the same user setting, a volume
+ * group (and associated given port of the client's track) can have different volumes for
+ * each output (destination device) it is attached to.
+ *
+ * @param ports to consider
+ * @param volume to set
+ * @param output to consider
+ * @param delayMs to use
+ * @return NO_ERROR if successful
+ */
+ status_t setPortsVolume(const std::vector<audio_port_handle_t> &ports, float volume,
+ audio_io_handle_t output, int delayMs = 0) override;
// function enabling to send proprietary informations directly from audio policy manager to audio hardware interface.
virtual void setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs, int delayMs = 0);
diff --git a/services/audiopolicy/service/AudioRecordClient.cpp b/services/audiopolicy/service/AudioRecordClient.cpp
index 6d8b3cf..733f0d6 100644
--- a/services/audiopolicy/service/AudioRecordClient.cpp
+++ b/services/audiopolicy/service/AudioRecordClient.cpp
@@ -18,15 +18,17 @@
#include "AudioRecordClient.h"
#include "AudioPolicyService.h"
+#include "binder/AppOpsManager.h"
#include <android_media_audiopolicy.h>
+#include <algorithm>
+
namespace android::media::audiopolicy {
namespace audiopolicy_flags = android::media::audiopolicy;
using android::AudioPolicyService;
namespace {
-bool isAppOpSource(audio_source_t source)
-{
+bool isAppOpSource(audio_source_t source) {
switch (source) {
case AUDIO_SOURCE_FM_TUNER:
case AUDIO_SOURCE_ECHO_REFERENCE:
@@ -55,7 +57,40 @@
bool doesPackageTargetAtLeastU(std::string_view packageName) {
return getTargetSdkForPackageName(packageName) >= __ANDROID_API_U__;
}
-}
+
+class AttrSourceItr {
+ public:
+ using iterator_category = std::forward_iterator_tag;
+ using difference_type = std::ptrdiff_t;
+ using value_type = AttributionSourceState;
+ using pointer = const value_type*;
+ using reference = const value_type&;
+
+ AttrSourceItr() : mAttr(nullptr) {}
+
+ AttrSourceItr(const AttributionSourceState& attr) : mAttr(&attr) {}
+
+ reference operator*() const { return *mAttr; }
+ pointer operator->() const { return mAttr; }
+
+ AttrSourceItr& operator++() {
+ mAttr = !mAttr->next.empty() ? mAttr->next.data() : nullptr;
+ return *this;
+ }
+
+ AttrSourceItr operator++(int) {
+ AttrSourceItr tmp = *this;
+ ++(*this);
+ return tmp;
+ }
+
+ friend bool operator==(const AttrSourceItr& a, const AttrSourceItr& b) = default;
+
+ static AttrSourceItr end() { return AttrSourceItr{}; }
+private:
+ const AttributionSourceState * mAttr;
+};
+} // anonymous
// static
sp<OpRecordAudioMonitor>
@@ -110,15 +145,24 @@
mOpCallback = new RecordAudioOpCallback(this);
ALOGV("start watching op %d for %s", mAppOp, mAttributionSource.toString().c_str());
- int flags = doesPackageTargetAtLeastU(
- mAttributionSource.packageName.value_or("")) ?
- AppOpsManager::WATCH_FOREGROUND_CHANGES : 0;
- // TODO: We need to always watch AppOpsManager::OP_RECORD_AUDIO too
- // since it controls the mic permission for legacy apps.
- mAppOpsManager.startWatchingMode(mAppOp, VALUE_OR_FATAL(aidl2legacy_string_view_String16(
- mAttributionSource.packageName.value_or(""))),
- flags,
- mOpCallback);
+ int flags = doesPackageTargetAtLeastU(mAttributionSource.packageName.value_or(""))
+ ? AppOpsManager::WATCH_FOREGROUND_CHANGES
+ : 0;
+
+ const auto reg = [&](int32_t op) {
+ std::for_each(AttrSourceItr{mAttributionSource}, AttrSourceItr::end(),
+ [&](const auto& attr) {
+ mAppOpsManager.startWatchingMode(
+ op,
+ VALUE_OR_FATAL(aidl2legacy_string_view_String16(
+ attr.packageName.value_or(""))),
+ flags, mOpCallback);
+ });
+ };
+ reg(mAppOp);
+ if (mAppOp != AppOpsManager::OP_RECORD_AUDIO) {
+ reg(AppOpsManager::OP_RECORD_AUDIO);
+ }
}
bool OpRecordAudioMonitor::hasOp() const {
@@ -131,14 +175,20 @@
// due to the UID in createIfNeeded(). As a result for those record track, it's:
// - not called from constructor,
// - not called from RecordAudioOpCallback because the callback is not installed in this case
-void OpRecordAudioMonitor::checkOp(bool updateUidStates)
-{
- // TODO: We need to always check AppOpsManager::OP_RECORD_AUDIO too
- // since it controls the mic permission for legacy apps.
- const int32_t mode = mAppOpsManager.checkOp(mAppOp,
- mAttributionSource.uid, VALUE_OR_FATAL(aidl2legacy_string_view_String16(
- mAttributionSource.packageName.value_or(""))));
- bool hasIt = (mode == AppOpsManager::MODE_ALLOWED);
+void OpRecordAudioMonitor::checkOp(bool updateUidStates) {
+ const auto check = [&](int32_t op) -> bool {
+ return std::all_of(
+ AttrSourceItr{mAttributionSource}, AttrSourceItr::end(), [&](const auto& x) {
+ return mAppOpsManager.checkOp(op, x.uid,
+ VALUE_OR_FATAL(aidl2legacy_string_view_String16(
+ x.packageName.value_or("")))) ==
+ AppOpsManager::MODE_ALLOWED;
+ });
+ };
+ bool hasIt = check(mAppOp);
+ if (mAppOp != AppOpsManager::OP_RECORD_AUDIO) {
+ hasIt = hasIt && check(AppOpsManager::OP_RECORD_AUDIO);
+ }
if (audiopolicy_flags::record_audio_device_aware_permission()) {
const bool canRecord = recordingAllowed(mAttributionSource, mVirtualDeviceId, mAttr.source);
@@ -173,4 +223,4 @@
}
}
-} // android::media::audiopolicy::internal
+} // namespace android::media::audiopolicy
diff --git a/services/audiopolicy/service/Spatializer.cpp b/services/audiopolicy/service/Spatializer.cpp
index 9cc3b8f..c7740ad 100644
--- a/services/audiopolicy/service/Spatializer.cpp
+++ b/services/audiopolicy/service/Spatializer.cpp
@@ -29,9 +29,7 @@
#include <android/content/AttributionSourceState.h>
#include <android/sysprop/BluetoothProperties.sysprop.h>
#include <audio_utils/fixedfft.h>
-#include <com_android_media_audio.h>
#include <cutils/bitops.h>
-#include <cutils/properties.h>
#include <hardware/sensors.h>
#include <media/stagefright/foundation/AHandler.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -43,6 +41,7 @@
#include <utils/Thread.h>
#include "Spatializer.h"
+#include "SpatializerHelper.h"
namespace android {
@@ -398,12 +397,10 @@
return status;
}
for (const auto channelMask : channelMasks) {
- static const bool stereo_spatialization_enabled =
- property_get_bool("ro.audio.stereo_spatialization_enabled", false);
const bool channel_mask_spatialized =
- (stereo_spatialization_enabled && com_android_media_audio_stereo_spatialization())
- ? audio_channel_mask_contains_stereo(channelMask)
- : audio_is_channel_mask_spatialized(channelMask);
+ SpatializerHelper::isStereoSpatializationFeatureEnabled()
+ ? audio_channel_mask_contains_stereo(channelMask)
+ : audio_is_channel_mask_spatialized(channelMask);
if (!channel_mask_spatialized) {
ALOGW("%s: ignoring channelMask:%#x", __func__, channelMask);
continue;
@@ -1272,12 +1269,9 @@
mDisplayOrientation);
// 4. Show flag or property state.
- static const bool stereo_spatialization_prop_enabled =
- property_get_bool("ro.audio.stereo_spatialization_enabled", false);
- const bool stereo_spatialization = com_android_media_audio_stereo_spatialization()
- && stereo_spatialization_prop_enabled;
- base::StringAppendF(&ss, "%sStereo Spatialization: %s\n", prefixSpace.c_str(),
- stereo_spatialization ? "true" : "false");
+ base::StringAppendF(
+ &ss, "%sStereo Spatialization: %s\n", prefixSpace.c_str(),
+ SpatializerHelper::isStereoSpatializationFeatureEnabled() ? "true" : "false");
ss.append(prefixSpace + "CommandLog:\n");
ss += mLocalLog.dumpToString((prefixSpace + " ").c_str(), mMaxLocalLogLine);
diff --git a/services/audiopolicy/tests/AudioPolicyTestClient.h b/services/audiopolicy/tests/AudioPolicyTestClient.h
index 0299160..6f63721 100644
--- a/services/audiopolicy/tests/AudioPolicyTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyTestClient.h
@@ -58,6 +58,10 @@
float /*volume*/,
audio_io_handle_t /*output*/,
int /*delayMs*/) override { return NO_INIT; }
+
+ status_t setPortsVolume(const std::vector<audio_port_handle_t>& /*ports*/, float /*volume*/,
+ audio_io_handle_t /*output*/, int /*delayMs*/) override { return NO_INIT; }
+
void setParameters(audio_io_handle_t /*ioHandle*/,
const String8& /*keyValuePairs*/,
int /*delayMs*/) override { }
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index f66b911..43b451f 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -299,11 +299,12 @@
AudioPolicyInterface::output_type_t outputType;
bool isSpatialized;
bool isBitPerfectInternal;
+ float volume;
AttributionSourceState attributionSource = createAttributionSourceState(uid);
ASSERT_EQ(OK, mManager->getOutputForAttr(
&attr, output, session, &stream, attributionSource, &config, &flags,
selectedDeviceId, portId, {}, &outputType, &isSpatialized,
- isBitPerfect == nullptr ? &isBitPerfectInternal : isBitPerfect));
+ isBitPerfect == nullptr ? &isBitPerfectInternal : isBitPerfect, &volume));
ASSERT_NE(AUDIO_PORT_HANDLE_NONE, *portId);
ASSERT_NE(AUDIO_IO_HANDLE_NONE, *output);
}
@@ -2065,6 +2066,7 @@
audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
bool mIsSpatialized;
bool mIsBitPerfect;
+ float mVolume;
};
TEST_P(AudioPolicyManagerTestMMapPlaybackRerouting, MmapPlaybackStreamMatchingLoopbackDapMixFails) {
@@ -2083,7 +2085,7 @@
mManager->getOutputForAttr(&attr, &mOutput, AUDIO_SESSION_NONE, &mStream,
createAttributionSourceState(testUid), &audioConfig,
&outputFlags, &mSelectedDeviceId, &mPortId, {},
- &mOutputType, &mIsSpatialized, &mIsBitPerfect));
+ &mOutputType, &mIsSpatialized, &mIsBitPerfect, &mVolume));
}
TEST_P(AudioPolicyManagerTestMMapPlaybackRerouting,
@@ -2102,7 +2104,7 @@
mManager->getOutputForAttr(&attr, &mOutput, AUDIO_SESSION_NONE, &mStream,
createAttributionSourceState(testUid), &audioConfig,
&outputFlags, &mSelectedDeviceId, &mPortId, {},
- &mOutputType, &mIsSpatialized, &mIsBitPerfect));
+ &mOutputType, &mIsSpatialized, &mIsBitPerfect, &mVolume));
}
TEST_F(AudioPolicyManagerTestMMapPlaybackRerouting,
@@ -2133,7 +2135,7 @@
mManager->getOutputForAttr(&attr, &mOutput, AUDIO_SESSION_NONE, &mStream,
createAttributionSourceState(testUid), &audioConfig,
&outputFlags, &mSelectedDeviceId, &mPortId, {},
- &mOutputType, &mIsSpatialized, &mIsBitPerfect));
+ &mOutputType, &mIsSpatialized, &mIsBitPerfect, &mVolume));
ASSERT_EQ(usbDevicePort.id, mSelectedDeviceId);
auto outputDesc = mManager->getOutputs().valueFor(mOutput);
ASSERT_NE(nullptr, outputDesc);
@@ -2149,7 +2151,7 @@
mManager->getOutputForAttr(&attr, &mOutput, AUDIO_SESSION_NONE, &mStream,
createAttributionSourceState(testUid), &audioConfig,
&outputFlags, &mSelectedDeviceId, &mPortId, {},
- &mOutputType, &mIsSpatialized, &mIsBitPerfect));
+ &mOutputType, &mIsSpatialized, &mIsBitPerfect, &mVolume));
ASSERT_EQ(usbDevicePort.id, mSelectedDeviceId);
outputDesc = mManager->getOutputs().valueFor(mOutput);
ASSERT_NE(nullptr, outputDesc);
@@ -2178,7 +2180,7 @@
mManager->getOutputForAttr(&attr, &mOutput, AUDIO_SESSION_NONE, &mStream,
createAttributionSourceState(testUid), &audioConfig,
&outputFlags, &mSelectedDeviceId, &mPortId, {},
- &mOutputType, &mIsSpatialized, &mIsBitPerfect));
+ &mOutputType, &mIsSpatialized, &mIsBitPerfect, &mVolume));
}
INSTANTIATE_TEST_SUITE_P(
@@ -3634,11 +3636,12 @@
AudioPolicyInterface::output_type_t outputType;
bool isSpatialized;
bool isBitPerfect;
+ float volume;
EXPECT_EQ(expected,
mManager->getOutputForAttr(&sMediaAttr, &mBitPerfectOutput, AUDIO_SESSION_NONE,
&stream, attributionSource, &config, &flags,
&mSelectedDeviceId, &mBitPerfectPortId, {}, &outputType,
- &isSpatialized, &isBitPerfect));
+ &isSpatialized, &isBitPerfect, &volume));
}
class AudioPolicyManagerTestBitPerfect : public AudioPolicyManagerTestBitPerfectBase {
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp b/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
index 53234f0..3858410 100644
--- a/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
@@ -32,7 +32,13 @@
cc_defaults {
name: "camera_service_fuzzer_defaults",
header_libs: [
+ "libaudioflinger_headers",
+ "libaudiohal_headers",
+ "libaudioutils_headers",
+ "libbinder_headers",
"libmedia_headers",
+ "libmediautils_headers",
+ "mediautils_headers",
],
shared_libs: [
"framework-permission-aidl-cpp",
@@ -59,7 +65,22 @@
"android.hardware.camera.device@3.6",
"android.hardware.camera.device@3.7",
"camera_platform_flags_c_lib",
+ "libactivitymanager_aidl",
+ "libaudioclient",
+ "libaudioflinger",
+ "libaudiohal",
+ "libaudioprocessing",
+ "libmediaplayerservice",
+ "libmediautils",
+ "libnbaio",
+ "libnblog",
+ "libpermission",
+ "libpowermanager",
+ "libsensorprivacy",
+ "libvibrator",
+ "packagemanager_aidl-cpp",
],
+ static_libs: ["libbinder_random_parcel"],
fuzz_config: {
cc: [
"android-camera-fwk-eng@google.com",
@@ -85,6 +106,9 @@
srcs: [
"camera_service_fuzzer.cpp",
],
+ static_libs: [
+ "libfakeservicemanager",
+ ],
defaults: [
"camera_service_fuzzer_defaults",
],
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp b/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
index 718e1d6..12ac33f 100644
--- a/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
@@ -21,20 +21,29 @@
#define LOG_TAG "CameraServiceFuzzer"
//#define LOG_NDEBUG 0
+#include <AudioFlinger.h>
#include <CameraService.h>
+#include <ISchedulingPolicyService.h>
+#include <MediaPlayerService.h>
+#include <android-base/logging.h>
#include <android/content/AttributionSourceState.h>
#include <android/hardware/BnCameraServiceListener.h>
#include <android/hardware/ICameraServiceListener.h>
#include <android/hardware/camera2/BnCameraDeviceCallbacks.h>
#include <android/hardware/camera2/ICameraDeviceUser.h>
+#include <binder/IActivityManager.h>
+#include <binder/IAppOpsService.h>
#include <camera/CameraUtils.h>
#include <camera/camera2/OutputConfiguration.h>
#include <com_android_graphics_libgui_flags.h>
#include <device3/Camera3StreamInterface.h>
+#include <fakeservicemanager/FakeServiceManager.h>
+#include <fuzzbinder/random_binder.h>
#include <gui/BufferItemConsumer.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
+#include <media/IAudioFlinger.h>
#include <private/android_filesystem_config.h>
#include "fuzzer/FuzzedDataProvider.h"
@@ -100,6 +109,196 @@
const size_t kNumCameraMsg = size(kCameraMsg);
const size_t kNumSoundKind = size(kSoundKind);
const size_t kNumShellCmd = size(kShellCmd);
+static std::once_flag gSmOnce;
+sp<CameraService> gCameraService;
+
+void addService(const String16& serviceName, const sp<FakeServiceManager>& fakeServiceManager,
+ FuzzedDataProvider* fdp) {
+ sp<IBinder> binder = getRandomBinder(fdp);
+ if (!binder) {
+ return;
+ }
+
+ CHECK_EQ(NO_ERROR, fakeServiceManager->addService(serviceName, binder));
+ return;
+}
+
+class FuzzerActivityManager : public BnInterface<IActivityManager> {
+ public:
+ int32_t openContentUri(const String16& /*stringUri*/) override { return 0; }
+
+ status_t registerUidObserver(const sp<IUidObserver>& /*observer*/, const int32_t /*event*/,
+ const int32_t /*cutpoint*/,
+ const String16& /*callingPackage*/) override {
+ return OK;
+ }
+
+ status_t unregisterUidObserver(const sp<IUidObserver>& /*observer*/) override { return OK; }
+
+ status_t registerUidObserverForUids(const sp<IUidObserver>& /*observer*/,
+ const int32_t /*event*/, const int32_t /*cutpoint*/,
+ const String16& /*callingPackage*/,
+ const int32_t* /*uids[]*/, size_t /*nUids*/,
+ /*out*/ sp<IBinder>& /*observerToken*/) override {
+ return OK;
+ }
+
+ status_t addUidToObserver(const sp<IBinder>& /*observerToken*/,
+ const String16& /*callingPackage*/, int32_t /*uid*/) override {
+ return OK;
+ }
+
+ status_t removeUidFromObserver(const sp<IBinder>& /*observerToken*/,
+ const String16& /*callingPackage*/, int32_t /*uid*/) override {
+ return OK;
+ }
+
+ bool isUidActive(const uid_t /*uid*/, const String16& /*callingPackage*/) override {
+ return true;
+ }
+
+ int32_t getUidProcessState(const uid_t /*uid*/, const String16& /*callingPackage*/) override {
+ return ActivityManager::PROCESS_STATE_UNKNOWN;
+ }
+
+ status_t checkPermission(const String16& /*permission*/, const pid_t /*pid*/,
+ const uid_t /*uid*/, int32_t* /*outResult*/) override {
+ return NO_ERROR;
+ }
+
+ status_t logFgsApiBegin(int32_t /*apiType*/, int32_t /*appUid*/, int32_t /*appPid*/) override {
+ return OK;
+ }
+ status_t logFgsApiEnd(int32_t /*apiType*/, int32_t /*appUid*/, int32_t /*appPid*/) override {
+ return OK;
+ }
+ status_t logFgsApiStateChanged(int32_t /*apiType*/, int32_t /*state*/, int32_t /*appUid*/,
+ int32_t /*appPid*/) override {
+ return OK;
+ }
+};
+
+class FuzzerSensorPrivacyManager : public BnInterface<hardware::ISensorPrivacyManager> {
+ public:
+ binder::Status supportsSensorToggle(int32_t /*toggleType*/, int32_t /*sensor*/,
+ bool* /*_aidl_return*/) override {
+ return binder::Status::fromStatusT(UNKNOWN_TRANSACTION);
+ }
+ binder::Status addSensorPrivacyListener(
+ const sp<hardware::ISensorPrivacyListener>& /*listener*/) override {
+ return binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+ }
+ binder::Status addToggleSensorPrivacyListener(
+ const sp<hardware::ISensorPrivacyListener>& /*listener*/) override {
+ return binder::Status::fromStatusT(UNKNOWN_TRANSACTION);
+ }
+ binder::Status removeSensorPrivacyListener(
+ const sp<hardware::ISensorPrivacyListener>& /*listener*/) override {
+ return binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+ }
+ binder::Status removeToggleSensorPrivacyListener(
+ const sp<hardware::ISensorPrivacyListener>& /*listener*/) override {
+ return binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+ }
+ binder::Status isSensorPrivacyEnabled(bool* /*_aidl_return*/) override {
+ return binder::Status::fromStatusT(UNKNOWN_TRANSACTION);
+ }
+ binder::Status isCombinedToggleSensorPrivacyEnabled(int32_t /*sensor*/,
+ bool* /*_aidl_return*/) override {
+ return binder::Status::fromStatusT(UNKNOWN_TRANSACTION);
+ }
+ binder::Status isToggleSensorPrivacyEnabled(int32_t /*toggleType*/, int32_t /*sensor*/,
+ bool* /*_aidl_return*/) override {
+ return binder::Status::fromStatusT(UNKNOWN_TRANSACTION);
+ }
+ binder::Status setSensorPrivacy(bool /*enable*/) override {
+ return binder::Status::fromStatusT(UNKNOWN_TRANSACTION);
+ }
+ binder::Status setToggleSensorPrivacy(int32_t /*userId*/, int32_t /*source*/,
+ int32_t /*sensor*/, bool /*enable*/) override {
+ return binder::Status::fromStatusT(UNKNOWN_TRANSACTION);
+ }
+ binder::Status setToggleSensorPrivacyForProfileGroup(int32_t /*userId*/, int32_t /*source*/,
+ int32_t /*sensor*/,
+ bool /*enable*/) override {
+ return binder::Status::fromStatusT(UNKNOWN_TRANSACTION);
+ }
+ binder::Status getCameraPrivacyAllowlist(
+ ::std::vector<::android::String16>* /*_aidl_return*/) override {
+ return binder::Status::fromStatusT(UNKNOWN_TRANSACTION);
+ }
+ binder::Status getToggleSensorPrivacyState(int32_t /*toggleType*/, int32_t /*sensor*/,
+ int32_t* /* _aidl_return*/) override {
+ return binder::Status::fromStatusT(UNKNOWN_TRANSACTION);
+ }
+ binder::Status setToggleSensorPrivacyState(int32_t /*userId*/, int32_t /*source*/,
+ int32_t /*sensor*/, int32_t /*state*/) override {
+ return binder::Status::fromStatusT(UNKNOWN_TRANSACTION);
+ }
+ binder::Status setToggleSensorPrivacyStateForProfileGroup(int32_t /*userId*/,
+ int32_t /*source*/,
+ int32_t /*sensor*/,
+ int32_t /*state*/) override {
+ return binder::Status::fromStatusT(UNKNOWN_TRANSACTION);
+ }
+ binder::Status isCameraPrivacyEnabled(const ::android::String16& /*packageName*/,
+ bool* /*_aidl_return*/) override {
+ return binder::Status::fromStatusT(UNKNOWN_TRANSACTION);
+ }
+};
+
+class FuzzAppOpsService : public BnAppOpsService {
+ public:
+ int32_t checkOperation(int32_t /*code*/, int32_t /*uid*/,
+ const String16& /*packageName*/) override {
+ return 0;
+ }
+
+ int32_t noteOperation(int32_t /*code*/, int32_t /*uid*/, const String16& /*packageName*/,
+ const std::optional<String16>& /*attributionTag*/,
+ bool /*shouldCollectAsyncNotedOp*/, const String16& /*message*/,
+ bool /*shouldCollectMessage*/) override {
+ return 0;
+ }
+
+ void startWatchingModeWithFlags(int32_t /*op*/, const String16& /*packageName*/,
+ int32_t /*flags*/,
+ const sp<IAppOpsCallback>& /*callback*/) override {
+ return;
+ }
+
+ int32_t startOperation(const sp<IBinder>& /*token*/, int32_t /*code*/, int32_t /*uid*/,
+ const String16& /*packageName*/,
+ const std::optional<String16>& /*attributionTag*/,
+ bool /*startIfModeDefault*/, bool /*shouldCollectAsyncNotedOp*/,
+ const String16& /*message*/, bool /*shouldCollectMessage*/) override {
+ return 0;
+ }
+
+ void finishOperation(const sp<IBinder>& /*token*/, int32_t /*code*/, int32_t /*uid*/,
+ const String16& /*packageName*/,
+ const std::optional<String16>& /*attributionTag*/) override {
+ return;
+ }
+
+ void startWatchingMode(int32_t /*op*/, const String16& /*packageName*/,
+ const sp<IAppOpsCallback>& /*callback*/) override {
+ return;
+ }
+
+ void stopWatchingMode(const sp<IAppOpsCallback>& /*callback*/) override { return; }
+
+ int32_t permissionToOpCode(const String16& /*permission*/) override { return 0; }
+
+ int32_t checkAudioOperation(int32_t /*code*/, int32_t /*usage*/, int32_t /*uid*/,
+ const String16& /*packageName*/) override {
+ return 0;
+ }
+
+ void setCameraAudioRestriction(int32_t /*mode*/) override { return; }
+
+ bool shouldCollectNotes(int32_t /*opCode*/) override { return true; }
+};
class CameraFuzzer : public ::android::hardware::BnCameraClient {
public:
@@ -687,14 +886,38 @@
}
setuid(AID_CAMERASERVER);
std::shared_ptr<FuzzedDataProvider> fp = std::make_shared<FuzzedDataProvider>(data, size);
- sp<CameraService> cs = new CameraService();
- cs->clearCachedVariables();
- sp<CameraFuzzer> camerafuzzer = new CameraFuzzer(cs, fp);
+
+ std::call_once(gSmOnce, [&] {
+ /* Create a FakeServiceManager instance and add required services */
+ sp<FakeServiceManager> fsm = sp<FakeServiceManager>::make();
+ setDefaultServiceManager(fsm);
+ for (const char* service :
+ {"sensor_privacy", "permission", "media.camera.proxy", "batterystats", "media.metrics",
+ "media.extractor", "drm.drmManager", "permission_checker"}) {
+ addService(String16(service), fsm, fp.get());
+ }
+ const auto audioFlinger = sp<AudioFlinger>::make();
+ const auto afAdapter = sp<AudioFlingerServerAdapter>::make(audioFlinger);
+ CHECK_EQ(NO_ERROR,
+ fsm->addService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME),
+ IInterface::asBinder(afAdapter), false /* allowIsolated */,
+ IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT));
+ sp<FuzzerActivityManager> am = new FuzzerActivityManager();
+ CHECK_EQ(NO_ERROR, fsm->addService(String16("activity"), IInterface::asBinder(am)));
+ sp<FuzzerSensorPrivacyManager> sensorPrivacyManager = new FuzzerSensorPrivacyManager();
+ CHECK_EQ(NO_ERROR, fsm->addService(String16("sensor_privacy"),
+ IInterface::asBinder(sensorPrivacyManager)));
+ sp<FuzzAppOpsService> appops = new FuzzAppOpsService();
+ CHECK_EQ(NO_ERROR, fsm->addService(String16("appops"), IInterface::asBinder(appops)));
+ MediaPlayerService::instantiate();
+ gCameraService = new CameraService();
+ });
+ sp<CameraFuzzer> camerafuzzer = new CameraFuzzer(gCameraService, fp);
if (!camerafuzzer) {
return 0;
}
camerafuzzer->process();
- Camera2Fuzzer camera2fuzzer(cs, fp);
+ Camera2Fuzzer camera2fuzzer(gCameraService, fp);
camera2fuzzer.process();
return 0;
}
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-0 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-0
new file mode 100644
index 0000000..4c56959
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-0
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-1 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-1
new file mode 100644
index 0000000..fc0e371
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-1
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-10 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-10
new file mode 100644
index 0000000..1266b3e
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-10
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-11 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-11
new file mode 100644
index 0000000..cb1c0e4
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-11
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-12 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-12
new file mode 100644
index 0000000..ab820a4
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-12
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-13 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-13
new file mode 100644
index 0000000..6051e9a
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-13
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-14 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-14
new file mode 100644
index 0000000..596e55b
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-14
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-15 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-15
new file mode 100644
index 0000000..20d7dcb
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-15
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-2 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-2
new file mode 100644
index 0000000..5bbfa56
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-2
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-3 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-3
new file mode 100644
index 0000000..cd148f6
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-3
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-4 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-4
new file mode 100644
index 0000000..e4ddb50
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-4
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-5 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-5
new file mode 100644
index 0000000..3be3ce1
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-5
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-6 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-6
new file mode 100644
index 0000000..3b51e41
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-6
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-7 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-7
new file mode 100644
index 0000000..3b929df
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-7
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-8 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-8
new file mode 100644
index 0000000..f92337b
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-8
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-9 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-9
new file mode 100644
index 0000000..0fe0f06
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-9
Binary files differ
diff --git a/services/mediametrics/MediaMetricsService.cpp b/services/mediametrics/MediaMetricsService.cpp
index f81db53..1309626 100644
--- a/services/mediametrics/MediaMetricsService.cpp
+++ b/services/mediametrics/MediaMetricsService.cpp
@@ -92,16 +92,12 @@
/* static */
std::pair<std::string, int64_t>
MediaMetricsService::getSanitizedPackageNameAndVersionCode(uid_t uid) {
- // Meyer's singleton, initialized on first access.
- // mUidInfo is locked internally.
- static mediautils::UidInfo uidInfo;
-
- // get info.
- mediautils::UidInfo::Info info = uidInfo.getInfo(uid);
- if (useUidForPackage(info.package, info.installer)) {
+ const std::shared_ptr<const mediautils::UidInfo::Info> info =
+ mediautils::UidInfo::getInfo(uid);
+ if (useUidForPackage(info->package, info->installer)) {
return { std::to_string(uid), /* versionCode */ 0 };
} else {
- return { info.package, info.versionCode };
+ return { info->package, info->versionCode };
}
}
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-0 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-0
new file mode 100644
index 0000000..802c2b5
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-0
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-1 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-1
new file mode 100644
index 0000000..9ee6a15
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-1
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-10 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-10
new file mode 100644
index 0000000..95006c8
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-10
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-11 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-11
new file mode 100644
index 0000000..853be96
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-11
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-12 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-12
new file mode 100644
index 0000000..c3e9848
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-12
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-13 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-13
new file mode 100644
index 0000000..08b7f0d
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-13
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-14 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-14
new file mode 100644
index 0000000..20e5e80
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-14
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-15 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-15
new file mode 100644
index 0000000..4e54f0b
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-15
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-2 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-2
new file mode 100644
index 0000000..2b2495d
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-2
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-3 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-3
new file mode 100644
index 0000000..753594d
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-3
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-4 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-4
new file mode 100644
index 0000000..0ed2010
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-4
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-5 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-5
new file mode 100644
index 0000000..f6141d1
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-5
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-6 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-6
new file mode 100644
index 0000000..b93f618
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-6
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-7 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-7
new file mode 100644
index 0000000..f8f296d
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-7
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-8 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-8
new file mode 100644
index 0000000..29bdbc1
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-8
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-9 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-9
new file mode 100644
index 0000000..315f25e
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-9
Binary files differ
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index 9c2fb7c..f12a5d6 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -310,6 +310,7 @@
mServiceLog->add(log);
std::scoped_lock lock{mLock};
+ ClientInfoParcel updatedClientInfo = clientInfo;
if (!mProcessInfo->isPidUidTrusted(pid, uid)) {
pid_t callingPid = IPCThreadState::self()->getCallingPid();
uid_t callingUid = IPCThreadState::self()->getCallingUid();
@@ -317,6 +318,8 @@
__FUNCTION__, pid, uid, callingPid, callingUid);
pid = callingPid;
uid = callingUid;
+ updatedClientInfo.pid = callingPid;
+ updatedClientInfo.uid = callingUid;
}
ResourceInfos& infos = getResourceInfosForEdit(pid, mMap);
ResourceInfo& info = getResourceInfoForEdit(clientInfo, client, infos);
@@ -342,7 +345,7 @@
}
if (info.deathNotifier == nullptr && client != nullptr) {
info.deathNotifier = DeathNotifier::Create(
- client, ref<ResourceManagerService>(), clientInfo);
+ client, ref<ResourceManagerService>(), updatedClientInfo);
}
if (mObserverService != nullptr && !resourceAdded.empty()) {
mObserverService->onResourceAdded(uid, pid, resourceAdded);