AudioPolicyManager volume init on invalid min/max
Detect situations where min/max volumes are invalid
in AudioPolicyManager::checkAndSetVolume and return
an error. On error, call back into AudioService
to request the volume ranges to be reinitialized.
Bug: 206966260
Test: upcoming AudioService test
Change-Id: Ie63d9b9e3faad0a3e897f2807ece383632860adb
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 9a7b9c1..02e7114 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -70,6 +70,7 @@
dynamic_policy_callback AudioSystem::gDynPolicyCallback = NULL;
record_config_callback AudioSystem::gRecordConfigCallback = NULL;
routing_callback AudioSystem::gRoutingCallback = NULL;
+vol_range_init_req_callback AudioSystem::gVolRangeInitReqCallback = NULL;
// Required to be held while calling into gSoundTriggerCaptureStateListener.
class CaptureStateListenerImpl;
@@ -781,6 +782,11 @@
gRoutingCallback = cb;
}
+/*static*/ void AudioSystem::setVolInitReqCallback(vol_range_init_req_callback cb) {
+ Mutex::Autolock _l(gLock);
+ gVolRangeInitReqCallback = cb;
+}
+
// client singleton for AudioPolicyService binder interface
// protected by gLockAPS
sp<IAudioPolicyService> AudioSystem::gAudioPolicyService;
@@ -2574,6 +2580,19 @@
return Status::ok();
}
+Status AudioSystem::AudioPolicyServiceClient::onVolumeRangeInitRequest() {
+ vol_range_init_req_callback cb = NULL;
+ {
+ Mutex::Autolock _l(AudioSystem::gLock);
+ cb = gVolRangeInitReqCallback;
+ }
+
+ if (cb != NULL) {
+ cb();
+ }
+ return Status::ok();
+}
+
void AudioSystem::AudioPolicyServiceClient::binderDied(const wp<IBinder>& who __unused) {
{
Mutex::Autolock _l(mLock);
diff --git a/media/libaudioclient/aidl/android/media/IAudioPolicyServiceClient.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyServiceClient.aidl
index d93a59d..c0cdd96 100644
--- a/media/libaudioclient/aidl/android/media/IAudioPolicyServiceClient.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioPolicyServiceClient.aidl
@@ -46,4 +46,7 @@
AudioSource source);
/** Notifies a change of audio routing */
void onRoutingUpdated();
+ /** Notifies a request for volume index ranges to be reset after they were observed as invalid
+ */
+ void onVolumeRangeInitRequest();
}
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 1cc22a0..b5b9277 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -77,6 +77,7 @@
audio_patch_handle_t patchHandle,
audio_source_t source);
typedef void (*routing_callback)();
+typedef void (*vol_range_init_req_callback)();
class IAudioFlinger;
class String8;
@@ -154,6 +155,7 @@
static void setDynPolicyCallback(dynamic_policy_callback cb);
static void setRecordConfigCallback(record_config_callback);
static void setRoutingCallback(routing_callback cb);
+ static void setVolInitReqCallback(vol_range_init_req_callback cb);
// Sets the binder to use for accessing the AudioFlinger service. This enables the system server
// to grant specific isolated processes access to the audio system. Currently used only for the
@@ -736,6 +738,7 @@
int32_t patchHandle,
media::audio::common::AudioSource source) override;
binder::Status onRoutingUpdated();
+ binder::Status onVolumeRangeInitRequest();
private:
Mutex mLock;
@@ -763,6 +766,7 @@
static dynamic_policy_callback gDynPolicyCallback;
static record_config_callback gRecordConfigCallback;
static routing_callback gRoutingCallback;
+ static vol_range_init_req_callback gVolRangeInitReqCallback;
static size_t gInBuffSize;
// previous parameters for recording buffer size queries
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 20d0523..496591a 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -533,6 +533,10 @@
virtual void onRoutingUpdated() = 0;
+ // Used to notify AudioService that an error was encountering when reading
+ // the volume ranges, and that they should be re-initialized
+ virtual void onVolumeRangeInitRequest() = 0;
+
// Used to notify the sound trigger module that an audio capture is about to
// take place. This should typically result in any active recognition
// sessions to be preempted on modules that do not support sound trigger
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index f08d4ad..334f267 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -2115,11 +2115,15 @@
// apply volume rules for current stream and device if necessary
auto &curves = getVolumeCurves(client->attributes());
- checkAndSetVolume(curves, client->volumeSource(),
+ if (NO_ERROR != checkAndSetVolume(curves, client->volumeSource(),
curves.getVolumeIndex(outputDesc->devices().types()),
outputDesc,
outputDesc->devices().types(), 0 /*delay*/,
- outputDesc->useHwGain() /*force*/);
+ outputDesc->useHwGain() /*force*/)) {
+ // request AudioService to reinitialize the volume curves asynchronously
+ ALOGE("checkAndSetVolume failed, requesting volume range init");
+ mpClientInterface->onVolumeRangeInitRequest();
+ };
// update the outputs if starting an output with a stream that can affect notification
// routing
@@ -7244,6 +7248,11 @@
deviceTypes = outputDesc->devices().types();
}
+ if (curves.getVolumeIndexMin() < 0 || curves.getVolumeIndexMax() < 0) {
+ ALOGE("invalid volume index range");
+ return BAD_VALUE;
+ }
+
float volumeDb = computeVolume(curves, volumeSource, index, deviceTypes);
if (outputDesc->isFixedVolume(deviceTypes) ||
// Force VoIP volume to max for bluetooth SCO device except if muted
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index 63a1e71..c766a15 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -277,6 +277,11 @@
mAudioPolicyService->onRoutingUpdated();
}
+void AudioPolicyService::AudioPolicyClient::onVolumeRangeInitRequest()
+{
+ mAudioPolicyService->onVolumeRangeInitRequest();
+}
+
audio_unique_id_t AudioPolicyService::AudioPolicyClient::newAudioUniqueId(audio_unique_id_use_t use)
{
return AudioSystem::newAudioUniqueId(use);
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index da0a4a9..08ab4b6 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -488,6 +488,19 @@
}
}
+void AudioPolicyService::onVolumeRangeInitRequest()
+{
+ mOutputCommandThread->volRangeInitReqCommand();
+}
+
+void AudioPolicyService::doOnVolumeRangeInitRequest()
+{
+ Mutex::Autolock _l(mNotificationClientsLock);
+ for (size_t i = 0; i < mNotificationClients.size(); i++) {
+ mNotificationClients.valueAt(i)->onVolumeRangeInitRequest();
+ }
+}
+
void AudioPolicyService::onCheckSpatializer()
{
Mutex::Autolock _l(mLock);
@@ -721,6 +734,13 @@
}
}
+void AudioPolicyService::NotificationClient::onVolumeRangeInitRequest()
+{
+ if (mAudioPolicyServiceClient != 0 && isServiceUid(mUid)) {
+ mAudioPolicyServiceClient->onVolumeRangeInitRequest();
+ }
+}
+
void AudioPolicyService::binderDied(const wp<IBinder>& who) {
ALOGW("binderDied() %p, calling pid %d", who.unsafe_get(),
IPCThreadState::self()->getCallingPid());
@@ -2157,6 +2177,17 @@
mLock.lock();
} break;
+ case VOL_RANGE_INIT_REQUEST: {
+ ALOGV("AudioCommandThread() processing volume range init request");
+ svc = mService.promote();
+ if (svc == 0) {
+ break;
+ }
+ mLock.unlock();
+ svc->doOnVolumeRangeInitRequest();
+ mLock.lock();
+ } break;
+
default:
ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
}
@@ -2480,6 +2511,14 @@
sendCommand(command);
}
+void AudioPolicyService::AudioCommandThread::volRangeInitReqCommand()
+{
+ sp<AudioCommand>command = new AudioCommand();
+ command->mCommand = VOL_RANGE_INIT_REQUEST;
+ ALOGV("AudioCommandThread() adding volume range init request");
+ sendCommand(command);
+}
+
status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs)
{
{
@@ -2647,6 +2686,10 @@
} break;
+ case VOL_RANGE_INIT_REQUEST: {
+ // command may come from different requests, do not filter
+ } break;
+
default:
break;
}
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index d863ff1..3a08cf8 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -343,6 +343,9 @@
void onRoutingUpdated();
void doOnRoutingUpdated();
+ void onVolumeRangeInitRequest();
+ void doOnVolumeRangeInitRequest();
+
/**
* Spatializer SpatializerPolicyCallback implementation.
* onCheckSpatializer() sends an event on mOutputCommandThread which executes
@@ -530,7 +533,8 @@
ROUTING_UPDATED,
UPDATE_UID_STATES,
CHECK_SPATIALIZER_OUTPUT, // verify if spatializer effect should be created or moved
- UPDATE_ACTIVE_SPATIALIZER_TRACKS // Update active track counts on spalializer output
+ UPDATE_ACTIVE_SPATIALIZER_TRACKS, // Update active track counts on spalializer output
+ VOL_RANGE_INIT_REQUEST, // request to reset the volume range indices
};
AudioCommandThread (String8 name, const wp<AudioPolicyService>& service);
@@ -581,6 +585,7 @@
void updateUidStatesCommand();
void checkSpatializerCommand();
void updateActiveSpatializerTracksCommand();
+ void volRangeInitReqCommand();
void insertCommand_l(AudioCommand *command, int delayMs = 0);
private:
@@ -803,6 +808,8 @@
virtual void onRoutingUpdated();
+ virtual void onVolumeRangeInitRequest();
+
virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use);
void setSoundTriggerCaptureState(bool active) override;
@@ -842,6 +849,7 @@
audio_patch_handle_t patchHandle,
audio_source_t source);
void onRoutingUpdated();
+ void onVolumeRangeInitRequest();
void setAudioPortCallbacksEnabled(bool enabled);
void setAudioVolumeGroupCallbacksEnabled(bool enabled);
diff --git a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
index adef8f1..057fa58 100644
--- a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
@@ -138,7 +138,12 @@
}
size_t getRoutingUpdatedCounter() const {
- return mRoutingUpdatedUpdateCount; }
+ return mRoutingUpdatedUpdateCount;
+ }
+
+ void onVolumeRangeInitRequest() override {
+
+ }
status_t updateSecondaryOutputs(
const TrackSecondaryOutputsMap& trackSecondaryOutputs __unused) override {
diff --git a/services/audiopolicy/tests/AudioPolicyTestClient.h b/services/audiopolicy/tests/AudioPolicyTestClient.h
index da85658..8a85fee 100644
--- a/services/audiopolicy/tests/AudioPolicyTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyTestClient.h
@@ -85,6 +85,7 @@
audio_patch_handle_t patchHandle __unused,
audio_source_t source __unused) override { }
void onRoutingUpdated() override { }
+ void onVolumeRangeInitRequest() override { }
void setEffectSuspended(int effectId __unused,
audio_session_t sessionId __unused,
bool suspended __unused) {}