Merge "cameraserver: Fix convertToHidl for requestStreamBuffers return." into tm-dev am: f318881c19 am: debf116006
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/av/+/17385331
Change-Id: Icbef0ee49282203fc476cfde2bf6af97cf1a240f
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/drm/libmediadrm/DrmMetricsConsumer.cpp b/drm/libmediadrm/DrmMetricsConsumer.cpp
index c06f09b..fd095b7 100644
--- a/drm/libmediadrm/DrmMetricsConsumer.cpp
+++ b/drm/libmediadrm/DrmMetricsConsumer.cpp
@@ -42,7 +42,7 @@
}
return type_names[attribute];
}
-
+
static const char *type_names[] = {"PROVISION_REQUIRED", "KEY_NEEDED",
"KEY_EXPIRED", "VENDOR_DEFINED",
"SESSION_RECLAIMED"};
diff --git a/include/media/MmapStreamCallback.h b/include/media/MmapStreamCallback.h
index 31b8eb5..76ee6d7 100644
--- a/include/media/MmapStreamCallback.h
+++ b/include/media/MmapStreamCallback.h
@@ -37,12 +37,9 @@
/**
* The volume to be applied to the use case specified when opening the stream has changed
- * \param[in] channels a channel mask containing all channels the volume should be applied to.
- * \param[in] values the volume values to be applied to each channel. The size of the vector
- * should correspond to the channel count retrieved with
- * audio_channel_count_from_in_mask() or audio_channel_count_from_out_mask()
+ * \param[in] volume the new target volume
*/
- virtual void onVolumeChanged(audio_channel_mask_t channels, Vector<float> values) = 0;
+ virtual void onVolumeChanged(float volume) = 0;
/**
* The device the stream is routed to/from has changed
diff --git a/include/private/media/VideoFrame.h b/include/private/media/VideoFrame.h
index d4025e5..97e0b1d 100644
--- a/include/private/media/VideoFrame.h
+++ b/include/private/media/VideoFrame.h
@@ -85,8 +85,6 @@
uint32_t mSize; // Number of bytes of frame data
uint32_t mIccSize; // Number of bytes of ICC data
uint32_t mBitDepth; // number of bits per R / G / B channel
-
- // Adding new items must be 64-bit aligned.
};
}; // namespace android
diff --git a/media/audioserver/audioserver.rc b/media/audioserver/audioserver.rc
index c4a6601..0bd0d88 100644
--- a/media/audioserver/audioserver.rc
+++ b/media/audioserver/audioserver.rc
@@ -7,11 +7,9 @@
ioprio rt 4
task_profiles ProcessCapacityHigh HighPerformance
onrestart restart vendor.audio-hal
+ onrestart restart vendor.audio-hal-aidl
onrestart restart vendor.audio-hal-4-0-msd
onrestart restart audio_proxy_service
- # Keep the original service names for backward compatibility
- onrestart restart vendor.audio-hal-2-0
- onrestart restart audio-hal-2-0
on property:vts.native_server.on=1
stop audioserver
@@ -20,42 +18,34 @@
on property:init.svc.audioserver=stopped
stop vendor.audio-hal
+ stop vendor.audio-hal-aidl
stop vendor.audio-hal-4-0-msd
stop audio_proxy_service
- # Keep the original service names for backward compatibility
- stop vendor.audio-hal-2-0
- stop audio-hal-2-0
# See b/155364397. Need to have HAL service running for VTS.
# Can't use 'restart' because then HAL service would restart
# audioserver bringing it back into running state.
start vendor.audio-hal
+ start vendor.audio-hal-aidl
start vendor.audio-hal-4-0-msd
start audio_proxy_service
- # Keep the original service names for backward compatibility
- start vendor.audio-hal-2-0
- start audio-hal-2-0
on property:init.svc.audioserver=running
start vendor.audio-hal
+ start vendor.audio-hal-aidl
start vendor.audio-hal-4-0-msd
start audio_proxy_service
- # Keep the original service names for backward compatibility
- start vendor.audio-hal-2-0
- start audio-hal-2-0
on property:sys.audio.restart.hal=1
# See b/159966243. Avoid restart loop between audioserver and HAL.
# Keep the original service names for backward compatibility
stop vendor.audio-hal
+ stop vendor.audio-hal-aidl
stop vendor.audio-hal-4-0-msd
stop audio_proxy_service
- stop vendor.audio-hal-2-0
- stop audio-hal-2-0
start vendor.audio-hal
+ start vendor.audio-hal-aidl
start vendor.audio-hal-4-0-msd
start audio_proxy_service
- start vendor.audio-hal-2-0
- start audio-hal-2-0
# reset the property
setprop sys.audio.restart.hal 0
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index efa9941..26a7dc5 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -1433,7 +1433,10 @@
/**
* Asynchronous request for the stream to flush.
* Flushing will discard any pending data.
- * This call only works if the stream is pausing or paused. TODO review
+ * This call only works if the stream is OPEN, PAUSED, STOPPED, or FLUSHED.
+ * Calling this function when in other states,
+ * or calling from an AAudio callback function,
+ * will have no effect and an error will be returned.
* Frame counters are not reset by a flush. They may be advanced.
* After this call the state will be in {@link #AAUDIO_STREAM_STATE_FLUSHING} or
* {@link #AAUDIO_STREAM_STATE_FLUSHED}.
diff --git a/media/libaaudio/include/aaudio/AAudioTesting.h b/media/libaaudio/include/aaudio/AAudioTesting.h
index 0f2d7a2..edda6d0 100644
--- a/media/libaaudio/include/aaudio/AAudioTesting.h
+++ b/media/libaaudio/include/aaudio/AAudioTesting.h
@@ -91,6 +91,13 @@
*/
AAUDIO_API bool AAudioStream_isMMapUsed(AAudioStream* stream);
+/**
+ * Returns the count of audio server death.
+ *
+ * @return audio server death count.
+ */
+AAUDIO_API int AAudio_getAudioServerDeathCount();
+
#ifdef __cplusplus
}
#endif
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index 9f0564f..34ecd25 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -605,13 +605,6 @@
return AAUDIO_ERROR_INVALID_STATE;
}
-aaudio_result_t AudioStreamInternal::updateStateMachine() {
- if (isDataCallbackActive()) {
- return AAUDIO_OK; // state is getting updated by the callback thread read/write call
- }
- return processCommands();
-}
-
void AudioStreamInternal::logTimestamp(AAudioServiceMessage &command) {
static int64_t oldPosition = 0;
static int64_t oldTime = 0;
diff --git a/media/libaaudio/src/client/AudioStreamInternal.h b/media/libaaudio/src/client/AudioStreamInternal.h
index 2367572..4ea61d2 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.h
+++ b/media/libaaudio/src/client/AudioStreamInternal.h
@@ -48,7 +48,7 @@
int64_t *framePosition,
int64_t *timeNanoseconds) override;
- virtual aaudio_result_t updateStateMachine() override;
+ virtual aaudio_result_t processCommands() override;
aaudio_result_t open(const AudioStreamBuilder &builder) override;
@@ -110,8 +110,6 @@
aaudio_result_t drainTimestampsFromService();
- aaudio_result_t processCommands();
-
aaudio_result_t stopCallback_l();
virtual void prepareBuffersForStart() {}
diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp
index 90ff4a5..b0504c9 100644
--- a/media/libaaudio/src/core/AAudioAudio.cpp
+++ b/media/libaaudio/src/core/AAudioAudio.cpp
@@ -25,6 +25,7 @@
#include <aaudio/AAudio.h>
#include <aaudio/AAudioTesting.h>
+#include <media/AudioSystem.h>
#include "AudioClock.h"
#include "AudioGlobal.h"
#include "AudioStreamBuilder.h"
@@ -604,3 +605,7 @@
// Do not return channel index masks as they are not public.
return AAudio_isChannelIndexMask(channelMask) ? AAUDIO_UNSPECIFIED : channelMask;
}
+
+AAUDIO_API int AAudio_getAudioServerDeathCount() {
+ return android::AudioSystem::getAudioFlingerDeathCount();
+}
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 06f05b0..8a5186a 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -21,7 +21,9 @@
#include <atomic>
#include <stdint.h>
+#include <linux/futex.h>
#include <media/MediaMetricsItem.h>
+#include <sys/syscall.h>
#include <aaudio/AAudio.h>
@@ -362,34 +364,37 @@
}
void AudioStream::setState(aaudio_stream_state_t state) {
- ALOGD("%s(s#%d) from %d to %d", __func__, getId(), mState, state);
- if (state == mState) {
+ aaudio_stream_state_t oldState = mState.load();
+ ALOGD("%s(s#%d) from %d to %d", __func__, getId(), oldState, state);
+ if (state == oldState) {
return; // no change
}
// Track transition to DISCONNECTED state.
if (state == AAUDIO_STREAM_STATE_DISCONNECTED) {
android::mediametrics::LogItem(mMetricsId)
.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_DISCONNECT)
- .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
+ .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(oldState))
.record();
}
// CLOSED is a final state
- if (mState == AAUDIO_STREAM_STATE_CLOSED) {
+ if (oldState == AAUDIO_STREAM_STATE_CLOSED) {
ALOGW("%s(%d) tried to set to %d but already CLOSED", __func__, getId(), state);
// Once CLOSING, we can only move to CLOSED state.
- } else if (mState == AAUDIO_STREAM_STATE_CLOSING
+ } else if (oldState == AAUDIO_STREAM_STATE_CLOSING
&& state != AAUDIO_STREAM_STATE_CLOSED) {
ALOGW("%s(%d) tried to set to %d but already CLOSING", __func__, getId(), state);
// Once DISCONNECTED, we can only move to CLOSING or CLOSED state.
- } else if (mState == AAUDIO_STREAM_STATE_DISCONNECTED
+ } else if (oldState == AAUDIO_STREAM_STATE_DISCONNECTED
&& !(state == AAUDIO_STREAM_STATE_CLOSING
|| state == AAUDIO_STREAM_STATE_CLOSED)) {
ALOGW("%s(%d) tried to set to %d but already DISCONNECTED", __func__, getId(), state);
} else {
- mState = state;
+ mState.store(state);
+ // Wake up a wakeForStateChange thread if it exists.
+ syscall(SYS_futex, &mState, FUTEX_WAKE_PRIVATE, INT_MAX, NULL, NULL, 0);
}
}
@@ -408,9 +413,15 @@
if (durationNanos > timeoutNanoseconds) {
durationNanos = timeoutNanoseconds;
}
- AudioClock::sleepForNanos(durationNanos);
- timeoutNanoseconds -= durationNanos;
+ struct timespec time;
+ time.tv_sec = durationNanos / AAUDIO_NANOS_PER_SECOND;
+ // Add the fractional nanoseconds.
+ time.tv_nsec = durationNanos - (time.tv_sec * AAUDIO_NANOS_PER_SECOND);
+ // Sleep for durationNanos. If mState changes from the callback
+ // thread, this thread will wake up earlier.
+ syscall(SYS_futex, &mState, FUTEX_WAIT_PRIVATE, currentState, &time, NULL, 0);
+ timeoutNanoseconds -= durationNanos;
aaudio_result_t result = updateStateMachine();
if (result != AAUDIO_OK) {
return result;
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index 5fb4528..8dd5538 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -100,10 +100,17 @@
int64_t *timeNanoseconds) = 0;
/**
- * Update state machine.()
- * @return
+ * Update state machine.
+ * @return result of the operation.
*/
- virtual aaudio_result_t updateStateMachine() = 0;
+ aaudio_result_t updateStateMachine() {
+ if (isDataCallbackActive()) {
+ return AAUDIO_OK; // state is getting updated by the callback thread read/write call
+ }
+ return processCommands();
+ };
+
+ virtual aaudio_result_t processCommands() = 0;
// =========== End ABSTRACT methods ===========================
@@ -184,7 +191,7 @@
// ============== Queries ===========================
aaudio_stream_state_t getState() const {
- return mState;
+ return mState.load();
}
virtual int32_t getBufferSize() const {
@@ -674,6 +681,8 @@
const android::sp<MyPlayerBase> mPlayerBase;
+ std::atomic<aaudio_stream_state_t> mState{AAUDIO_STREAM_STATE_UNINITIALIZED};
+
// These do not change after open().
int32_t mSamplesPerFrame = AAUDIO_UNSPECIFIED;
aaudio_channel_mask_t mChannelMask = AAUDIO_UNSPECIFIED;
@@ -682,7 +691,6 @@
aaudio_sharing_mode_t mSharingMode = AAUDIO_SHARING_MODE_SHARED;
bool mSharingModeMatchRequired = false; // must match sharing mode requested
audio_format_t mFormat = AUDIO_FORMAT_DEFAULT;
- aaudio_stream_state_t mState = AAUDIO_STREAM_STATE_UNINITIALIZED;
aaudio_performance_mode_t mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
int32_t mFramesPerBurst = 0;
int32_t mBufferCapacity = 0;
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
index dd11169..f32ef65 100644
--- a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
@@ -127,7 +127,7 @@
mCallbackEnabled.store(false);
}
- if (updateStateMachine() != AAUDIO_OK) {
+ if (processCommands() != AAUDIO_OK) {
forceDisconnect();
mCallbackEnabled.store(false);
}
@@ -192,7 +192,7 @@
mCallbackEnabled.store(false);
}
- if (updateStateMachine() != AAUDIO_OK) {
+ if (processCommands() != AAUDIO_OK) {
forceDisconnect();
mCallbackEnabled.store(false);
}
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index 1e39e0f..9a136a7 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -364,8 +364,7 @@
return checkForDisconnectRequest(false);
}
-aaudio_result_t AudioStreamRecord::updateStateMachine()
-{
+aaudio_result_t AudioStreamRecord::processCommands() {
aaudio_result_t result = AAUDIO_OK;
aaudio_wrapping_frames_t position;
status_t err;
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.h b/media/libaaudio/src/legacy/AudioStreamRecord.h
index 5ce73f9..252ff3c 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.h
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.h
@@ -58,7 +58,7 @@
int64_t getFramesWritten() override;
- aaudio_result_t updateStateMachine() override;
+ aaudio_result_t processCommands() override;
aaudio_direction_t getDirection() const override {
return AAUDIO_DIRECTION_INPUT;
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index 6f1dc92..09caa5c 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -378,8 +378,7 @@
return checkForDisconnectRequest(false);;
}
-aaudio_result_t AudioStreamTrack::updateStateMachine()
-{
+aaudio_result_t AudioStreamTrack::processCommands() {
status_t err;
aaudio_wrapping_frames_t position;
switch (getState()) {
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.h b/media/libaaudio/src/legacy/AudioStreamTrack.h
index 0f4d72b..1f877b5 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.h
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.h
@@ -79,7 +79,7 @@
return AAUDIO_DIRECTION_OUTPUT;
}
- aaudio_result_t updateStateMachine() override;
+ aaudio_result_t processCommands() override;
int64_t incrementClientFrameCounter(int32_t frames) override {
return incrementFramesWritten(frames);
diff --git a/media/libaaudio/src/libaaudio.map.txt b/media/libaaudio/src/libaaudio.map.txt
index f45b816..f0cb595 100644
--- a/media/libaaudio/src/libaaudio.map.txt
+++ b/media/libaaudio/src/libaaudio.map.txt
@@ -3,6 +3,7 @@
AAudio_convertResultToText;
AAudio_convertStreamStateToText;
AAudio_createStreamBuilder;
+ AAudio_getAudioServerDeathCount; # introduced=33
AAudio_getMMapPolicy;
AAudio_setMMapPolicy;
AAudioStreamBuilder_setPerformanceMode;
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index 11724e0..b0c9a0c 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -1932,7 +1932,7 @@
case media::AudioPortType::SESSION:
legacy.session = VALUE_OR_RETURN(
aidl2legacy_int32_t_audio_port_config_session_ext(
- VALUE_OR_RETURN(UNION_GET(aidl, session))));
+ VALUE_OR_RETURN(UNION_GET(aidlSys, session))));
return legacy;
}
@@ -1966,9 +1966,9 @@
return OK;
}
case AUDIO_PORT_TYPE_SESSION:
- UNION_SET(*aidl, session, VALUE_OR_RETURN_STATUS(
+ UNION_SET(*aidl, unspecified, false);
+ UNION_SET(*aidlSys, session, VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_port_config_session_ext_int32_t(legacy.session)));
- UNION_SET(*aidlSys, unspecified, false);
return OK;
}
LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
@@ -2816,7 +2816,7 @@
case media::AudioPortType::SESSION:
legacy.session = VALUE_OR_RETURN(
aidl2legacy_int32_t_audio_port_session_ext(
- VALUE_OR_RETURN(UNION_GET(aidl, session))));
+ VALUE_OR_RETURN(UNION_GET(aidlSys, session))));
return legacy;
}
@@ -2852,9 +2852,9 @@
return OK;
}
case AUDIO_PORT_TYPE_SESSION:
- UNION_SET(*aidl, session, VALUE_OR_RETURN_STATUS(
+ UNION_SET(*aidl, unspecified, false);
+ UNION_SET(*aidlSys, session, VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_port_session_ext_int32_t(legacy.session)));
- UNION_SET(*aidlSys, unspecified, false);
return OK;
}
LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index a7b10b2..fe6a24a 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -17,6 +17,8 @@
#define LOG_TAG "AudioSystem"
//#define LOG_NDEBUG 0
+#include <atomic>
+
#include <utils/Log.h>
#include <android/media/IAudioPolicyService.h>
@@ -82,6 +84,8 @@
// HotwordDetectionService.
sp<IBinder> gAudioFlingerBinder = nullptr;
+std::atomic<int> gAudioFlingerDeathCount{0};
+
void AudioSystem::setAudioFlingerBinder(const sp<IBinder>& audioFlinger) {
if (audioFlinger->getInterfaceDescriptor() != media::IAudioFlingerService::descriptor) {
ALOGE("setAudioFlingerBinder: received a binder of type %s",
@@ -535,6 +539,8 @@
reportError(DEAD_OBJECT);
+ gAudioFlingerDeathCount += 1;
+
ALOGW("AudioFlinger server died!");
}
@@ -2410,6 +2416,10 @@
return af->getAAudioHardwareBurstMinUsec();
}
+int32_t AudioSystem::getAudioFlingerDeathCount() {
+ return gAudioFlingerDeathCount.load();
+}
+
// ---------------------------------------------------------------------------
int AudioSystem::AudioPolicyServiceClient::addAudioPortCallback(
diff --git a/media/libaudioclient/aidl/android/media/AudioPortExtSys.aidl b/media/libaudioclient/aidl/android/media/AudioPortExtSys.aidl
index 2cdf4f6..d9c6df4 100644
--- a/media/libaudioclient/aidl/android/media/AudioPortExtSys.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioPortExtSys.aidl
@@ -31,4 +31,6 @@
AudioPortDeviceExtSys device;
/** System-only parameters when the port is an audio mix. */
AudioPortMixExtSys mix;
+ /** Framework audio session identifier. */
+ int session;
}
diff --git a/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp b/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp
index 036e72e..5536bcb 100644
--- a/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp
+++ b/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp
@@ -84,13 +84,15 @@
};
template <typename T, typename X, typename FUNC>
-std::vector<T> getFlags(const xsdc_enum_range<X> &range, const FUNC &func,
- const std::string &findString = {}) {
+std::vector<T> getFlags(const xsdc_enum_range<X>& range, const FUNC& func,
+ const std::string& findString = {},
+ const std::set<X>& excludedValues = {}) {
std::vector<T> vec;
for (const auto &xsdEnumVal : range) {
T enumVal;
std::string enumString = toString(xsdEnumVal);
if (enumString.find(findString) != std::string::npos &&
+ (excludedValues.find(xsdEnumVal) == excludedValues.end()) &&
func(enumString.c_str(), &enumVal)) {
vec.push_back(enumVal);
}
@@ -102,13 +104,29 @@
getFlags<audio_stream_type_t, xsd::AudioStreamType, decltype(audio_stream_type_from_string)>(
xsdc_enum_range<xsd::AudioStreamType>{}, audio_stream_type_from_string);
+/**
+ * AudioFormat - AUDIO_FORMAT_HE_AAC_V1 and AUDIO_FORMAT_HE_AAC_V2
+ * are excluded from kFormats[] in order to avoid the abort triggered
+ * for these two types of AudioFormat in
+ * AidlConversion::legacy2aidl_audio_format_t_AudioFormatDescription()
+ */
static const std::vector<audio_format_t> kFormats =
- getFlags<audio_format_t, xsd::AudioFormat, decltype(audio_format_from_string)>(
- xsdc_enum_range<xsd::AudioFormat>{}, audio_format_from_string);
+ getFlags<audio_format_t, xsd::AudioFormat, decltype(audio_format_from_string)>(
+ xsdc_enum_range<xsd::AudioFormat>{}, audio_format_from_string, {},
+ {xsd::AudioFormat::AUDIO_FORMAT_HE_AAC_V1,
+ xsd::AudioFormat::AUDIO_FORMAT_HE_AAC_V2});
+/**
+ * AudioChannelMask - AUDIO_CHANNEL_IN_6
+ * is excluded from kChannelMasks[] in order to avoid the abort triggered
+ * for this type of AudioChannelMask in
+ * AidlConversion::legacy2aidl_audio_channel_mask_t_AudioChannelLayout()
+ */
static const std::vector<audio_channel_mask_t> kChannelMasks =
- getFlags<audio_channel_mask_t, xsd::AudioChannelMask, decltype(audio_channel_mask_from_string)>(
- xsdc_enum_range<xsd::AudioChannelMask>{}, audio_channel_mask_from_string);
+ getFlags<audio_channel_mask_t, xsd::AudioChannelMask,
+ decltype(audio_channel_mask_from_string)>(
+ xsdc_enum_range<xsd::AudioChannelMask>{}, audio_channel_mask_from_string, {},
+ {xsd::AudioChannelMask::AUDIO_CHANNEL_IN_6});
static const std::vector<audio_usage_t> kUsages =
getFlags<audio_usage_t, xsd::AudioUsage, decltype(audio_usage_from_string)>(
@@ -126,9 +144,17 @@
getFlags<audio_gain_mode_t, xsd::AudioGainMode, decltype(audio_gain_mode_from_string)>(
xsdc_enum_range<xsd::AudioGainMode>{}, audio_gain_mode_from_string);
+/**
+ * AudioDevice - AUDIO_DEVICE_IN_AMBIENT and AUDIO_DEVICE_IN_COMMUNICATION
+ * are excluded from kDevices[] in order to avoid the abort triggered
+ * for these two types of AudioDevice in
+ * AidlConversion::aidl2legacy_AudioDeviceDescription_audio_devices_t()
+ */
static const std::vector<audio_devices_t> kDevices =
- getFlags<audio_devices_t, xsd::AudioDevice, decltype(audio_device_from_string)>(
- xsdc_enum_range<xsd::AudioDevice>{}, audio_device_from_string);
+ getFlags<audio_devices_t, xsd::AudioDevice, decltype(audio_device_from_string)>(
+ xsdc_enum_range<xsd::AudioDevice>{}, audio_device_from_string, {},
+ {xsd::AudioDevice::AUDIO_DEVICE_IN_AMBIENT,
+ xsd::AudioDevice::AUDIO_DEVICE_IN_COMMUNICATION});
static const std::vector<audio_input_flags_t> kInputFlags =
getFlags<audio_input_flags_t, xsd::AudioInOutFlag, decltype(audio_input_flag_from_string)>(
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index e89ce15..01f22a8 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -565,6 +565,11 @@
static status_t getDirectProfilesForAttributes(const audio_attributes_t* attr,
std::vector<audio_profile>* audioProfiles);
+ /**
+ * @return count of AudioFlinger death.
+ */
+ static int32_t getAudioFlingerDeathCount();
+
// A listener for capture state changes.
class CaptureStateListener : public virtual RefBase {
public:
diff --git a/media/libheif/HeifDecoderImpl.cpp b/media/libheif/HeifDecoderImpl.cpp
index 1b8656d..923f5c1 100644
--- a/media/libheif/HeifDecoderImpl.cpp
+++ b/media/libheif/HeifDecoderImpl.cpp
@@ -735,9 +735,9 @@
HeifFrameInfo* info = &mImageInfo;
if (info != nullptr) {
return mImageInfo.mBitDepth;
+ } else {
+ return 0;
}
-
- return 0;
}
} // namespace android
diff --git a/media/libheif/include/HeifDecoderAPI.h b/media/libheif/include/HeifDecoderAPI.h
index dc12486..56f4765 100644
--- a/media/libheif/include/HeifDecoderAPI.h
+++ b/media/libheif/include/HeifDecoderAPI.h
@@ -47,7 +47,7 @@
int32_t mRotationAngle; // Rotation angle, clockwise, should be multiple of 90
uint32_t mBytesPerPixel; // Number of bytes for one pixel
int64_t mDurationUs; // Duration of the frame in us
- uint32_t mBitDepth; // Number of bits for each of the R/G/B channels
+ uint32_t mBitDepth; // Number of bits of R/G/B channel
std::vector<uint8_t> mIccData; // ICC data array
};
@@ -164,7 +164,7 @@
virtual size_t skipScanlines(size_t count) = 0;
/*
- * Returns color depth in bits for each of the R/G/B channels.
+ * Returns color depth of R/G/B channel.
*/
virtual uint32_t getColorDepth() = 0;
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index 3df8766..10a1ee4 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -913,7 +913,7 @@
return ERROR_MALFORMED;
}
- int32_t width, height, stride, srcFormat;
+ int32_t width, height, stride;
if (outputFormat->findInt32("width", &width) == false) {
ALOGE("MediaImageDecoder::onOutputReceived:width is missing in outputFormat");
return ERROR_MALFORMED;
@@ -926,10 +926,9 @@
ALOGE("MediaImageDecoder::onOutputReceived:stride is missing in outputFormat");
return ERROR_MALFORMED;
}
- if (outputFormat->findInt32("color-format", &srcFormat) == false) {
- ALOGE("MediaImageDecoder::onOutputReceived: color format is missing in outputFormat");
- return ERROR_MALFORMED;
- }
+
+ int32_t srcFormat;
+ CHECK(outputFormat->findInt32("color-format", &srcFormat));
uint32_t bitDepth = 8;
if (COLOR_FormatYUVP010 == srcFormat) {
diff --git a/media/libstagefright/VideoFrameScheduler.cpp b/media/libstagefright/VideoFrameScheduler.cpp
index 4e5b5e2..de8e425 100644
--- a/media/libstagefright/VideoFrameScheduler.cpp
+++ b/media/libstagefright/VideoFrameScheduler.cpp
@@ -22,8 +22,8 @@
#include <utils/String16.h>
#include <binder/IServiceManager.h>
-#include <gui/ISurfaceComposer.h>
-#include <ui/DisplayStatInfo.h>
+#include <android/gui/ISurfaceComposer.h>
+#include <android/gui/DisplayStatInfo.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AUtils.h>
@@ -39,21 +39,22 @@
mVsyncTime = 0;
mVsyncPeriod = 0;
+ // TODO(b/220021255): wrap this into SurfaceComposerClient
if (mComposer == NULL) {
- String16 name("SurfaceFlinger");
+ String16 name("SurfaceFlingerAIDL");
sp<IServiceManager> sm = defaultServiceManager();
- mComposer = interface_cast<ISurfaceComposer>(sm->checkService(name));
+ mComposer = interface_cast<gui::ISurfaceComposer>(sm->checkService(name));
}
if (mComposer != NULL) {
- DisplayStatInfo stats;
- status_t res = mComposer->getDisplayStats(NULL /* display */, &stats);
- if (res == OK) {
+ gui::DisplayStatInfo stats;
+ binder::Status status = mComposer->getDisplayStats(nullptr/* display */, &stats);
+ if (status.isOk()) {
ALOGV("vsync time:%lld period:%lld",
(long long)stats.vsyncTime, (long long)stats.vsyncPeriod);
mVsyncTime = stats.vsyncTime;
mVsyncPeriod = stats.vsyncPeriod;
} else {
- ALOGW("getDisplayStats returned %d", res);
+ ALOGW("getDisplayStats returned %d", status.transactionError());
}
} else {
ALOGW("could not get surface mComposer service");
diff --git a/media/libstagefright/include/media/stagefright/VideoFrameScheduler.h b/media/libstagefright/include/media/stagefright/VideoFrameScheduler.h
index fcfcbec..a4f512a 100644
--- a/media/libstagefright/include/media/stagefright/VideoFrameScheduler.h
+++ b/media/libstagefright/include/media/stagefright/VideoFrameScheduler.h
@@ -21,7 +21,9 @@
namespace android {
-class ISurfaceComposer;
+namespace gui {
+ class ISurfaceComposer;
+}
struct VideoFrameScheduler : public VideoFrameSchedulerBase {
VideoFrameScheduler();
@@ -32,7 +34,7 @@
private:
void updateVsync() override;
- sp<ISurfaceComposer> mComposer;
+ sp<gui::ISurfaceComposer> mComposer;
};
} // namespace android
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index ae5772d..d5100c4 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -10218,20 +10218,10 @@
} else {
sp<MmapStreamCallback> callback = mCallback.promote();
if (callback != 0) {
- int channelCount;
- if (isOutput()) {
- channelCount = audio_channel_count_from_out_mask(mChannelMask);
- } else {
- channelCount = audio_channel_count_from_in_mask(mChannelMask);
- }
- Vector<float> values;
- for (int i = 0; i < channelCount; i++) {
- values.add(volume);
- }
mHalVolFloat = volume; // SW volume control worked, so update value.
mNoCallbackWarningCount = 0;
mLock.unlock();
- callback->onVolumeChanged(mChannelMask, values);
+ callback->onVolumeChanged(volume);
mLock.lock();
} else {
if (mNoCallbackWarningCount < kMaxNoCallbackWarnings) {
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 1e2dccb..bf7d0c2 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -42,6 +42,7 @@
srcs: [
"CameraService.cpp",
+ "CameraServiceWatchdog.cpp",
"CameraFlashlight.cpp",
"common/Camera2ClientBase.cpp",
"common/CameraDeviceBase.cpp",
diff --git a/services/camera/libcameraservice/CameraServiceWatchdog.cpp b/services/camera/libcameraservice/CameraServiceWatchdog.cpp
new file mode 100644
index 0000000..fcd6ebe
--- /dev/null
+++ b/services/camera/libcameraservice/CameraServiceWatchdog.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "CameraServiceWatchdog"
+
+#include "CameraServiceWatchdog.h"
+
+namespace android {
+
+bool CameraServiceWatchdog::threadLoop()
+{
+ {
+ AutoMutex _l(mWatchdogLock);
+
+ while (mPause) {
+ mWatchdogCondition.wait(mWatchdogLock);
+ }
+ }
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(mCycleLengthMs));
+
+ {
+ AutoMutex _l(mWatchdogLock);
+
+ for (auto it = tidToCycleCounterMap.begin(); it != tidToCycleCounterMap.end(); it++) {
+ uint32_t currentThreadId = it->first;
+
+ tidToCycleCounterMap[currentThreadId]++;
+
+ if (tidToCycleCounterMap[currentThreadId] >= mMaxCycles) {
+ ALOGW("CameraServiceWatchdog triggering kill for pid: %d", getpid());
+ kill(getpid(), SIGKILL);
+ }
+ }
+ }
+
+ return true;
+}
+
+void CameraServiceWatchdog::requestExit()
+{
+ Thread::requestExit();
+
+ AutoMutex _l(mWatchdogLock);
+
+ tidToCycleCounterMap.clear();
+
+ if (mPause) {
+ mPause = false;
+ mWatchdogCondition.signal();
+ }
+}
+
+void CameraServiceWatchdog::stop(uint32_t tid)
+{
+ AutoMutex _l(mWatchdogLock);
+
+ tidToCycleCounterMap.erase(tid);
+
+ if (tidToCycleCounterMap.empty()) {
+ mPause = true;
+ }
+}
+
+void CameraServiceWatchdog::start(uint32_t tid)
+{
+ AutoMutex _l(mWatchdogLock);
+
+ tidToCycleCounterMap[tid] = 0;
+
+ if (mPause) {
+ mPause = false;
+ mWatchdogCondition.signal();
+ }
+}
+
+} // namespace android
diff --git a/services/camera/libcameraservice/CameraServiceWatchdog.h b/services/camera/libcameraservice/CameraServiceWatchdog.h
new file mode 100644
index 0000000..f4955e2
--- /dev/null
+++ b/services/camera/libcameraservice/CameraServiceWatchdog.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+/**
+ * The CameraService watchdog is used to help detect bad states in the
+ * Camera HAL. The threadloop uses cycle counters, assigned to each calling
+ * thread, to monitor the elapsing time and kills the process when the
+ * expected duration has exceeded.
+ * Notes on multi-threaded behaviors:
+ * - The threadloop is blocked/paused when there are no calls being
+ * monitored.
+ * - The start and stop functions handle simultaneous call monitoring
+ * and single call monitoring differently. See function documentation for
+ * more details.
+ */
+
+#include <chrono>
+#include <thread>
+#include <time.h>
+#include <utils/Thread.h>
+#include <utils/Log.h>
+#include <unordered_map>
+
+// Used to wrap the call of interest in start and stop calls
+#define WATCH(toMonitor) watchThread([&]() { return toMonitor;}, gettid())
+#define WATCH_CUSTOM_TIMER(toMonitor, cycles, cycleLength) \
+ watchThread([&]() { return toMonitor;}, gettid(), cycles, cycleLength);
+
+// Default cycles and cycle length values used to calculate permitted elapsed time
+const static size_t kMaxCycles = 100;
+const static uint32_t kCycleLengthMs = 100;
+
+namespace android {
+
+class CameraServiceWatchdog : public Thread {
+
+public:
+ explicit CameraServiceWatchdog() : mPause(true), mMaxCycles(kMaxCycles),
+ mCycleLengthMs(kCycleLengthMs) {};
+
+ explicit CameraServiceWatchdog (size_t maxCycles, uint32_t cycleLengthMs) :
+ mPause(true), mMaxCycles(maxCycles), mCycleLengthMs(cycleLengthMs) {};
+
+ virtual ~CameraServiceWatchdog() {};
+
+ virtual void requestExit();
+
+ /** Used to wrap monitored calls in start and stop functions using custom timer values */
+ template<typename T>
+ auto watchThread(T func, uint32_t tid, uint32_t cycles, uint32_t cycleLength) {
+ auto res = NULL;
+
+ if (cycles != mMaxCycles || cycleLength != mCycleLengthMs) {
+ // Create another instance of the watchdog to prevent disruption
+ // of timer for current monitored calls
+ sp<CameraServiceWatchdog> tempWatchdog =
+ new CameraServiceWatchdog(cycles, cycleLength);
+ tempWatchdog->run("CameraServiceWatchdog");
+ res = tempWatchdog->watchThread(func, tid);
+ tempWatchdog->requestExit();
+ tempWatchdog.clear();
+ } else {
+ // If custom timer values are equivalent to set class timer values, use
+ // current thread
+ res = watchThread(func, tid);
+ }
+
+ return res;
+ }
+
+ /** Used to wrap monitored calls in start and stop functions using class timer values */
+ template<typename T>
+ auto watchThread(T func, uint32_t tid) {
+ auto res = NULL;
+
+ start(tid);
+ res = func();
+ stop(tid);
+
+ return res;
+ }
+
+private:
+
+ /**
+ * Start adds a cycle counter for the calling thread. When threadloop is blocked/paused,
+ * start() unblocks and starts the watchdog
+ */
+ void start(uint32_t tid);
+
+ /**
+ * If there are no calls left to be monitored, stop blocks/pauses threadloop
+ * otherwise stop() erases the cycle counter to end watchdog for the calling thread
+ */
+ void stop(uint32_t tid);
+
+ virtual bool threadLoop();
+
+ Mutex mWatchdogLock; // Lock for condition variable
+ Condition mWatchdogCondition; // Condition variable for stop/start
+ bool mPause; // True if thread is currently paused
+ uint32_t mMaxCycles; // Max cycles
+ uint32_t mCycleLengthMs; // Length of time elapsed per cycle
+
+ std::unordered_map<uint32_t, uint32_t> tidToCycleCounterMap; // Thread Id to cycle counter map
+};
+
+} // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 55acec4..f5c6d6f 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -115,6 +115,10 @@
status_t Camera3Device::initializeCommonLocked() {
+ /** Start watchdog thread */
+ mCameraServiceWatchdog = new CameraServiceWatchdog();
+ mCameraServiceWatchdog->run("CameraServiceWatchdog");
+
/** Start up status tracker thread */
mStatusTracker = new StatusTracker(this);
status_t res = mStatusTracker->run(String8::format("C3Dev-%s-Status", mId.string()).string());
@@ -316,7 +320,7 @@
// Call close without internal mutex held, as the HAL close may need to
// wait on assorted callbacks,etc, to complete before it can return.
- interface->close();
+ mCameraServiceWatchdog->WATCH(interface->close());
flushInflightRequests();
@@ -339,6 +343,12 @@
}
}
ALOGI("%s: X", __FUNCTION__);
+
+ if (mCameraServiceWatchdog != NULL) {
+ mCameraServiceWatchdog->requestExit();
+ mCameraServiceWatchdog.clear();
+ }
+
return res;
}
@@ -1719,7 +1729,12 @@
mSessionStatsBuilder.stopCounter();
}
- return mRequestThread->flush();
+ // Calculate expected duration for flush with additional buffer time in ms for watchdog
+ uint64_t maxExpectedDuration = (getExpectedInFlightDuration() + kBaseGetBufferWait) / 1e6;
+ status_t res = mCameraServiceWatchdog->WATCH_CUSTOM_TIMER(mRequestThread->flush(),
+ maxExpectedDuration / kCycleLengthMs, kCycleLengthMs);
+
+ return res;
}
status_t Camera3Device::prepare(int streamId) {
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 1a240c3..0fd0a2d 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -32,6 +32,7 @@
#include <camera/CaptureResult.h>
#include "android/hardware/camera/metadata/3.8/types.h"
+#include "CameraServiceWatchdog.h"
#include "common/CameraDeviceBase.h"
#include "device3/BufferUtils.h"
#include "device3/StatusTracker.h"
@@ -98,6 +99,9 @@
metadata_vendor_id_t getVendorTagId() const override { return mVendorTagId; }
+ // Watchdog thread
+ sp<CameraServiceWatchdog> mCameraServiceWatchdog;
+
// Transitions to idle state on success.
virtual status_t initialize(sp<CameraProviderManager> /*manager*/,
const String8& /*monitorTags*/) = 0;
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp b/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
index 3c98a5e..1df730d 100644
--- a/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
@@ -65,6 +65,7 @@
fuzz_config: {
cc: [
"android-media-fuzzing-reports@google.com",
+ "android-camera-fwk-eng@google.com",
],
componentid: 155276,
libfuzzer_options: [
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp b/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
index 97d7bf4..b3502e2 100644
--- a/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
@@ -125,6 +125,7 @@
void invokeDump();
void invokeShellCommand();
void invokeNotifyCalls();
+ void invokeTorchAPIs(int32_t cameraId);
// CameraClient interface
void notifyCallback(int32_t msgType, int32_t, int32_t) override;
@@ -311,9 +312,23 @@
mCameraService->notifySystemEvent(eventId, args);
}
+void CameraFuzzer::invokeTorchAPIs(int32_t cameraId) {
+ String16 cameraIdStr = String16(String8::format("%d", cameraId));
+ sp<IBinder> binder = new BBinder;
+
+ mCameraService->setTorchMode(cameraIdStr, true, binder);
+ ALOGV("Turned torch on.");
+ int32_t torchStrength = rand() % 5 + 1;
+ ALOGV("Changing torch strength level to %d", torchStrength);
+ mCameraService->turnOnTorchWithStrengthLevel(cameraIdStr, torchStrength, binder);
+ mCameraService->setTorchMode(cameraIdStr, false, binder);
+ ALOGV("Turned torch off.");
+}
+
void CameraFuzzer::invokeCameraAPIs() {
for (int32_t cameraId = 0; cameraId < mNumCameras; ++cameraId) {
getCameraInformation(cameraId);
+ invokeTorchAPIs(cameraId);
::android::binder::Status rc;
sp<ICamera> cameraDevice;
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.cpp b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
index 3f18b95..bbfa0b7 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.cpp
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
@@ -228,9 +228,6 @@
if (mMmapStream != nullptr) {
// Needs to be explicitly cleared or CTS will fail but it is not clear why.
mMmapStream.clear();
- // Apparently the above close is asynchronous. An attempt to open a new device
- // right after a close can fail. Also some callbacks may still be in flight!
- // FIXME Make closing synchronous.
AudioClock::sleepForNanos(100 * AAUDIO_NANOS_PER_MILLISECOND);
}
}
@@ -362,12 +359,8 @@
asyncTask.detach();
}
-void AAudioServiceEndpointMMAP::onVolumeChanged(audio_channel_mask_t channels,
- android::Vector<float> values) {
- // TODO Do we really need a different volume for each channel?
- // We get called with an array filled with a single value!
- float volume = values[0];
- ALOGD("%s() volume[0] = %f", __func__, volume);
+void AAudioServiceEndpointMMAP::onVolumeChanged(float volume) {
+ ALOGD("%s() volume = %f", __func__, volume);
std::lock_guard<std::mutex> lock(mLockStreams);
for(const auto& stream : mRegisteredStreams) {
stream->onVolumeChanged(volume);
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.h b/services/oboeservice/AAudioServiceEndpointMMAP.h
index 3e7f2c7..3658c58 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.h
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.h
@@ -77,8 +77,7 @@
// -------------- Callback functions for MmapStreamCallback ---------------------
void onTearDown(audio_port_handle_t portHandle) override;
- void onVolumeChanged(audio_channel_mask_t channels,
- android::Vector<float> values) override;
+ void onVolumeChanged(float volume) override;
void onRoutingChanged(audio_port_handle_t portHandle) override;
// ------------------------------------------------------------------------------