diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp index 35adb725fd..0ce251344f 100644 --- a/media/libaudioclient/AudioSystem.cpp +++ b/media/libaudioclient/AudioSystem.cpp @@ -792,6 +792,7 @@ const sp AudioSystem::get_audio_policy_service() int64_t token = IPCThreadState::self()->clearCallingIdentity(); ap->registerClient(apc); ap->setAudioPortCallbacksEnabled(apc->isAudioPortCbEnabled()); + ap->setAudioVolumeGroupCallbacksEnabled(apc->isAudioVolumeGroupCbEnabled()); IPCThreadState::self()->restoreCallingIdentity(token); } @@ -987,6 +988,38 @@ status_t AudioSystem::getStreamVolumeIndex(audio_stream_type_t stream, return aps->getStreamVolumeIndex(stream, index, device); } +status_t AudioSystem::setVolumeIndexForAttributes(const audio_attributes_t &attr, + int index, + audio_devices_t device) +{ + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + return aps->setVolumeIndexForAttributes(attr, index, device); +} + +status_t AudioSystem::getVolumeIndexForAttributes(const audio_attributes_t &attr, + int &index, + audio_devices_t device) +{ + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + return aps->getVolumeIndexForAttributes(attr, index, device); +} + +status_t AudioSystem::getMaxVolumeIndexForAttributes(const audio_attributes_t &attr, int &index) +{ + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + return aps->getMaxVolumeIndexForAttributes(attr, index); +} + +status_t AudioSystem::getMinVolumeIndexForAttributes(const audio_attributes_t &attr, int &index) +{ + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + return aps->getMinVolumeIndexForAttributes(attr, index); +} + uint32_t AudioSystem::getStrategyForStream(audio_stream_type_t stream) { const sp& aps = AudioSystem::get_audio_policy_service(); @@ -1190,6 +1223,38 @@ status_t AudioSystem::removeAudioPortCallback(const sp& callb return (ret < 0) ? INVALID_OPERATION : NO_ERROR; } +status_t AudioSystem::addAudioVolumeGroupCallback(const sp& callback) +{ + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + + Mutex::Autolock _l(gLockAPS); + if (gAudioPolicyServiceClient == 0) { + return NO_INIT; + } + int ret = gAudioPolicyServiceClient->addAudioVolumeGroupCallback(callback); + if (ret == 1) { + aps->setAudioVolumeGroupCallbacksEnabled(true); + } + return (ret < 0) ? INVALID_OPERATION : NO_ERROR; +} + +status_t AudioSystem::removeAudioVolumeGroupCallback(const sp& callback) +{ + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + + Mutex::Autolock _l(gLockAPS); + if (gAudioPolicyServiceClient == 0) { + return NO_INIT; + } + int ret = gAudioPolicyServiceClient->removeAudioVolumeGroupCallback(callback); + if (ret == 0) { + aps->setAudioVolumeGroupCallbacksEnabled(false); + } + return (ret < 0) ? INVALID_OPERATION : NO_ERROR; +} + status_t AudioSystem::addAudioDeviceCallback( const wp& callback, audio_io_handle_t audioIo) { @@ -1498,6 +1563,47 @@ void AudioSystem::AudioPolicyServiceClient::onAudioPatchListUpdate() } } +// ---------------------------------------------------------------------------- +int AudioSystem::AudioPolicyServiceClient::addAudioVolumeGroupCallback( + const sp& callback) +{ + Mutex::Autolock _l(mLock); + for (size_t i = 0; i < mAudioVolumeGroupCallback.size(); i++) { + if (mAudioVolumeGroupCallback[i] == callback) { + return -1; + } + } + mAudioVolumeGroupCallback.add(callback); + return mAudioVolumeGroupCallback.size(); +} + +int AudioSystem::AudioPolicyServiceClient::removeAudioVolumeGroupCallback( + const sp& callback) +{ + Mutex::Autolock _l(mLock); + size_t i; + for (i = 0; i < mAudioVolumeGroupCallback.size(); i++) { + if (mAudioVolumeGroupCallback[i] == callback) { + break; + } + } + if (i == mAudioVolumeGroupCallback.size()) { + return -1; + } + mAudioVolumeGroupCallback.removeAt(i); + return mAudioVolumeGroupCallback.size(); +} + +void AudioSystem::AudioPolicyServiceClient::onAudioVolumeGroupChanged(volume_group_t group, + int flags) +{ + Mutex::Autolock _l(mLock); + for (size_t i = 0; i < mAudioVolumeGroupCallback.size(); i++) { + mAudioVolumeGroupCallback[i]->onAudioVolumeGroupChanged(group, flags); + } +} +// ---------------------------------------------------------------------------- + void AudioSystem::AudioPolicyServiceClient::onDynamicPolicyMixStateUpdate( String8 regId, int32_t state) { @@ -1541,6 +1647,9 @@ void AudioSystem::AudioPolicyServiceClient::binderDied(const wp& who __ for (size_t i = 0; i < mAudioPortCallbacks.size(); i++) { mAudioPortCallbacks[i]->onServiceDied(); } + for (size_t i = 0; i < mAudioVolumeGroupCallback.size(); i++) { + mAudioVolumeGroupCallback[i]->onServiceDied(); + } } { Mutex::Autolock _l(gLockAPS); diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp index feb131764e..3bac44f2eb 100644 --- a/media/libaudioclient/IAudioPolicyService.cpp +++ b/media/libaudioclient/IAudioPolicyService.cpp @@ -51,6 +51,10 @@ enum { INIT_STREAM_VOLUME, SET_STREAM_VOLUME, GET_STREAM_VOLUME, + SET_VOLUME_ATTRIBUTES, + GET_VOLUME_ATTRIBUTES, + GET_MIN_VOLUME_FOR_ATTRIBUTES, + GET_MAX_VOLUME_FOR_ATTRIBUTES, GET_STRATEGY_FOR_STREAM, GET_OUTPUT_FOR_EFFECT, REGISTER_EFFECT, @@ -78,6 +82,7 @@ enum { START_AUDIO_SOURCE, STOP_AUDIO_SOURCE, SET_AUDIO_PORT_CALLBACK_ENABLED, + SET_AUDIO_VOLUME_GROUP_CALLBACK_ENABLED, SET_MASTER_MONO, GET_MASTER_MONO, GET_STREAM_VOLUME_DB, @@ -417,6 +422,70 @@ public: return static_cast (reply.readInt32()); } + virtual status_t setVolumeIndexForAttributes(const audio_attributes_t &attr, int index, + audio_devices_t device) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + data.write(&attr, sizeof(audio_attributes_t)); + data.writeInt32(index); + data.writeInt32(static_cast (device)); + status_t status = remote()->transact(SET_VOLUME_ATTRIBUTES, data, &reply); + if (status != NO_ERROR) { + return status; + } + return static_cast (reply.readInt32()); + } + virtual status_t getVolumeIndexForAttributes(const audio_attributes_t &attr, int &index, + audio_devices_t device) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + data.write(&attr, sizeof(audio_attributes_t)); + data.writeInt32(static_cast (device)); + status_t status = remote()->transact(GET_VOLUME_ATTRIBUTES, data, &reply); + if (status != NO_ERROR) { + return status; + } + status = static_cast (reply.readInt32()); + if (status != NO_ERROR) { + return status; + } + index = reply.readInt32(); + return NO_ERROR; + } + virtual status_t getMinVolumeIndexForAttributes(const audio_attributes_t &attr, int &index) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + data.write(&attr, sizeof(audio_attributes_t)); + status_t status = remote()->transact(GET_MIN_VOLUME_FOR_ATTRIBUTES, data, &reply); + if (status != NO_ERROR) { + return status; + } + status = static_cast (reply.readInt32()); + if (status != NO_ERROR) { + return status; + } + index = reply.readInt32(); + return NO_ERROR; + } + virtual status_t getMaxVolumeIndexForAttributes(const audio_attributes_t &attr, int &index) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + data.write(&attr, sizeof(audio_attributes_t)); + status_t status = remote()->transact(GET_MAX_VOLUME_FOR_ATTRIBUTES, data, &reply); + if (status != NO_ERROR) { + return status; + } + status = static_cast (reply.readInt32()); + if (status != NO_ERROR) { + return status; + } + index = reply.readInt32(); + return NO_ERROR; + } virtual uint32_t getStrategyForStream(audio_stream_type_t stream) { Parcel data, reply; @@ -694,6 +763,14 @@ public: remote()->transact(SET_AUDIO_PORT_CALLBACK_ENABLED, data, &reply); } + virtual void setAudioVolumeGroupCallbacksEnabled(bool enabled) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + data.writeInt32(enabled ? 1 : 0); + remote()->transact(SET_AUDIO_VOLUME_GROUP_CALLBACK_ENABLED, data, &reply); + } + virtual status_t acquireSoundTriggerSession(audio_session_t *session, audio_io_handle_t *ioHandle, audio_devices_t *device) @@ -1492,6 +1569,73 @@ status_t BnAudioPolicyService::onTransact( return NO_ERROR; } break; + case SET_VOLUME_ATTRIBUTES: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + audio_attributes_t attributes = {}; + status_t status = data.read(&attributes, sizeof(audio_attributes_t)); + if (status != NO_ERROR) { + return status; + } + int index = data.readInt32(); + audio_devices_t device = static_cast (data.readInt32()); + + reply->writeInt32(static_cast (setVolumeIndexForAttributes(attributes, + index, device))); + return NO_ERROR; + } break; + + case GET_VOLUME_ATTRIBUTES: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + audio_attributes_t attributes = {}; + status_t status = data.read(&attributes, sizeof(audio_attributes_t)); + if (status != NO_ERROR) { + return status; + } + audio_devices_t device = static_cast (data.readInt32()); + + int index = 0; + status = getVolumeIndexForAttributes(attributes, index, device); + reply->writeInt32(static_cast (status)); + if (status == NO_ERROR) { + reply->writeInt32(index); + } + return NO_ERROR; + } break; + + case GET_MIN_VOLUME_FOR_ATTRIBUTES: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + audio_attributes_t attributes = {}; + status_t status = data.read(&attributes, sizeof(audio_attributes_t)); + if (status != NO_ERROR) { + return status; + } + + int index = 0; + status = getMinVolumeIndexForAttributes(attributes, index); + reply->writeInt32(static_cast (status)); + if (status == NO_ERROR) { + reply->writeInt32(index); + } + return NO_ERROR; + } break; + + case GET_MAX_VOLUME_FOR_ATTRIBUTES: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + audio_attributes_t attributes = {}; + status_t status = data.read(&attributes, sizeof(audio_attributes_t)); + if (status != NO_ERROR) { + return status; + } + + int index = 0; + status = getMaxVolumeIndexForAttributes(attributes, index); + reply->writeInt32(static_cast (status)); + if (status == NO_ERROR) { + reply->writeInt32(index); + } + return NO_ERROR; + } break; + case GET_DEVICES_FOR_STREAM: { CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_stream_type_t stream = @@ -1740,6 +1884,12 @@ status_t BnAudioPolicyService::onTransact( return NO_ERROR; } break; + case SET_AUDIO_VOLUME_GROUP_CALLBACK_ENABLED: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + setAudioVolumeGroupCallbacksEnabled(data.readInt32() == 1); + return NO_ERROR; + } break; + case ACQUIRE_SOUNDTRIGGER_SESSION: { CHECK_INTERFACE(IAudioPolicyService, data, reply); sp client = interface_cast( diff --git a/media/libaudioclient/IAudioPolicyServiceClient.cpp b/media/libaudioclient/IAudioPolicyServiceClient.cpp index 1f9eab7fa8..52d8ccd175 100644 --- a/media/libaudioclient/IAudioPolicyServiceClient.cpp +++ b/media/libaudioclient/IAudioPolicyServiceClient.cpp @@ -31,7 +31,8 @@ enum { PORT_LIST_UPDATE = IBinder::FIRST_CALL_TRANSACTION, PATCH_LIST_UPDATE, MIX_STATE_UPDATE, - RECORDING_CONFIGURATION_UPDATE + RECORDING_CONFIGURATION_UPDATE, + VOLUME_GROUP_CHANGED, }; // ---------------------------------------------------------------------- @@ -108,6 +109,15 @@ public: remote()->transact(PATCH_LIST_UPDATE, data, &reply, IBinder::FLAG_ONEWAY); } + void onAudioVolumeGroupChanged(volume_group_t group, int flags) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor()); + data.writeUint32(group); + data.writeInt32(flags); + remote()->transact(VOLUME_GROUP_CHANGED, data, &reply, IBinder::FLAG_ONEWAY); + } + void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state) { Parcel data, reply; @@ -157,6 +167,13 @@ status_t BnAudioPolicyServiceClient::onTransact( onAudioPatchListUpdate(); return NO_ERROR; } break; + case VOLUME_GROUP_CHANGED: { + CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply); + volume_group_t group = static_cast(data.readUint32()); + int flags = data.readInt32(); + onAudioVolumeGroupChanged(group, flags); + return NO_ERROR; + } break; case MIX_STATE_UPDATE: { CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply); String8 regId = data.readString8(); diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h index 142d2bbab7..e64f285b09 100644 --- a/media/libaudioclient/include/media/AudioSystem.h +++ b/media/libaudioclient/include/media/AudioSystem.h @@ -264,6 +264,17 @@ public: int *index, audio_devices_t device); + static status_t setVolumeIndexForAttributes(const audio_attributes_t &attr, + int index, + audio_devices_t device); + static status_t getVolumeIndexForAttributes(const audio_attributes_t &attr, + int &index, + audio_devices_t device); + + static status_t getMaxVolumeIndexForAttributes(const audio_attributes_t &attr, int &index); + + static status_t getMinVolumeIndexForAttributes(const audio_attributes_t &attr, int &index); + static uint32_t getStrategyForStream(audio_stream_type_t stream); static audio_devices_t getDevicesForStream(audio_stream_type_t stream); @@ -381,6 +392,21 @@ public: // ---------------------------------------------------------------------------- + class AudioVolumeGroupCallback : public RefBase + { + public: + + AudioVolumeGroupCallback() {} + virtual ~AudioVolumeGroupCallback() {} + + virtual void onAudioVolumeGroupChanged(volume_group_t group, int flags) = 0; + virtual void onServiceDied() = 0; + + }; + + static status_t addAudioVolumeGroupCallback(const sp& callback); + static status_t removeAudioVolumeGroupCallback(const sp& callback); + class AudioPortCallback : public RefBase { public: @@ -513,12 +539,17 @@ private: int removeAudioPortCallback(const sp& callback); bool isAudioPortCbEnabled() const { return (mAudioPortCallbacks.size() != 0); } + int addAudioVolumeGroupCallback(const sp& callback); + int removeAudioVolumeGroupCallback(const sp& callback); + bool isAudioVolumeGroupCbEnabled() const { return (mAudioVolumeGroupCallback.size() != 0); } + // DeathRecipient virtual void binderDied(const wp& who); // IAudioPolicyServiceClient virtual void onAudioPortListUpdate(); virtual void onAudioPatchListUpdate(); + virtual void onAudioVolumeGroupChanged(volume_group_t group, int flags); virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state); virtual void onRecordingConfigurationUpdate(int event, const record_client_info_t *clientInfo, @@ -532,6 +563,7 @@ private: private: Mutex mLock; Vector > mAudioPortCallbacks; + Vector > mAudioVolumeGroupCallback; }; static audio_io_handle_t getOutput(audio_stream_type_t stream); diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h index 800344d8eb..35540f096a 100644 --- a/media/libaudioclient/include/media/IAudioPolicyService.h +++ b/media/libaudioclient/include/media/IAudioPolicyService.h @@ -93,6 +93,17 @@ public: virtual status_t getStreamVolumeIndex(audio_stream_type_t stream, int *index, audio_devices_t device) = 0; + + virtual status_t setVolumeIndexForAttributes(const audio_attributes_t &attr, + int index, + audio_devices_t device) = 0; + virtual status_t getVolumeIndexForAttributes(const audio_attributes_t &attr, + int &index, + audio_devices_t device) = 0; + virtual status_t getMaxVolumeIndexForAttributes(const audio_attributes_t &attr, int &index) = 0; + + virtual status_t getMinVolumeIndexForAttributes(const audio_attributes_t &attr, int &index) = 0; + virtual uint32_t getStrategyForStream(audio_stream_type_t stream) = 0; virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream) = 0; virtual audio_io_handle_t getOutputForEffect(const effect_descriptor_t *desc) = 0; @@ -160,6 +171,8 @@ public: virtual void setAudioPortCallbacksEnabled(bool enabled) = 0; + virtual void setAudioVolumeGroupCallbacksEnabled(bool enabled) = 0; + virtual status_t acquireSoundTriggerSession(audio_session_t *session, audio_io_handle_t *ioHandle, audio_devices_t *device) = 0; diff --git a/media/libaudioclient/include/media/IAudioPolicyServiceClient.h b/media/libaudioclient/include/media/IAudioPolicyServiceClient.h index b3c0381db1..79008c3ccd 100644 --- a/media/libaudioclient/include/media/IAudioPolicyServiceClient.h +++ b/media/libaudioclient/include/media/IAudioPolicyServiceClient.h @@ -23,6 +23,8 @@ #include #include #include +#include +#include namespace android { @@ -45,6 +47,8 @@ class IAudioPolicyServiceClient : public IInterface public: DECLARE_META_INTERFACE(AudioPolicyServiceClient); + // Notifies a change of volume group + virtual void onAudioVolumeGroupChanged(volume_group_t group, int flags) = 0; // Notifies a change of audio port configuration. virtual void onAudioPortListUpdate() = 0; // Notifies a change of audio patch configuration. diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h index 9b00a4d696..d61188f08c 100644 --- a/services/audiopolicy/AudioPolicyInterface.h +++ b/services/audiopolicy/AudioPolicyInterface.h @@ -159,6 +159,19 @@ public: int *index, audio_devices_t device) = 0; + virtual status_t setVolumeIndexForAttributes(const audio_attributes_t &attr, + int index, + audio_devices_t device) = 0; + virtual status_t getVolumeIndexForAttributes(const audio_attributes_t &attr, + int &index, + audio_devices_t device) = 0; + + virtual status_t getMaxVolumeIndexForAttributes(const audio_attributes_t &attr, + int &index) = 0; + + virtual status_t getMinVolumeIndexForAttributes(const audio_attributes_t &attr, + int &index) = 0; + // return the strategy corresponding to a given stream type virtual uint32_t getStrategyForStream(audio_stream_type_t stream) = 0; @@ -347,6 +360,8 @@ public: virtual void onAudioPatchListUpdate() = 0; + virtual void onAudioVolumeGroupChanged(volume_group_t group, int flags) = 0; + virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use) = 0; virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state) = 0; diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index 4540c4d99a..92aa189296 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -2498,6 +2498,107 @@ status_t AudioPolicyManager::getStreamVolumeIndex(audio_stream_type_t stream, return NO_ERROR; } +status_t AudioPolicyManager::setVolumeIndexForAttributes(const audio_attributes_t &attr, + int index, + audio_devices_t device) +{ + // Get Volume group matching the Audio Attributes + auto volumeGroup = mEngine->getVolumeGroupForAttributes(attr); + if (volumeGroup == VOLUME_GROUP_NONE) { + ALOGD("%s: could not find group matching with %s", __FUNCTION__, toString(attr).c_str()); + return BAD_VALUE; + } + ALOGD("%s: FOUND group %d matching with %s", __FUNCTION__, volumeGroup, toString(attr).c_str()); + return setVolumeGroupIndex(getVolumeCurves(attr), volumeGroup, index, device, attr); +} + +status_t AudioPolicyManager::setVolumeGroupIndex(IVolumeCurves &curves, volume_group_t group, + int index, + audio_devices_t device, + const audio_attributes_t /*attributes*/) +{ + ALOGVV("%s: group=%d", __func__, group); + status_t status = NO_ERROR; + setVolumeCurveIndex(group, index, device, curves); + // update volume on all outputs and streams matching the following: + // - The requested stream (or a stream matching for volume control) is active on the output + // - The device (or devices) selected by the engine for this stream includes + // the requested device + // - For non default requested device, currently selected device on the output is either the + // requested device or one of the devices selected by the engine for this stream + // - For default requested device (AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME), apply volume only if + // no specific device volume value exists for currently selected device. + // @TODO + mpClientInterface->onAudioVolumeGroupChanged(group, 0 /*flags*/); + return status; +} + +status_t AudioPolicyManager::setVolumeCurveIndex(volume_group_t volumeGroup, + int index, + audio_devices_t device, + IVolumeCurves &volumeCurves) +{ + // VOICE_CALL stream has minVolumeIndex > 0 but can be muted directly by an + // app that has MODIFY_PHONE_STATE permission. + // If voice is member of the volume group, it will contaminate all the member of this group + auto streams = mEngine->getStreamTypesForVolumeGroup(volumeGroup); + if (((index < volumeCurves.getVolumeIndexMin()) && !(hasVoiceStream(streams) && index == 0)) || + (index > volumeCurves.getVolumeIndexMax())) { + ALOGD("%s: wrong index %d min=%d max=%d", __FUNCTION__, index, + volumeCurves.getVolumeIndexMin(), volumeCurves.getVolumeIndexMax()); + return BAD_VALUE; + } + if (!audio_is_output_device(device)) { + return BAD_VALUE; + } + + // Force max volume if stream cannot be muted + if (!volumeCurves.canBeMuted()) index = volumeCurves.getVolumeIndexMax(); + + ALOGD("%s device %08x, index %d", __FUNCTION__ , device, index); + volumeCurves.addCurrentVolumeIndex(device, index); + return NO_ERROR; +} + +status_t AudioPolicyManager::getVolumeIndexForAttributes(const audio_attributes_t &attr, + int &index, + audio_devices_t device) +{ + // if device is AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME, return volume for device selected for this + // stream by the engine. + if (device == AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) { + device = mEngine->getOutputDevicesForAttributes(attr, nullptr, true /*fromCache*/).types(); + } + return getVolumeIndex(getVolumeCurves(attr), index, device); +} + +status_t AudioPolicyManager::getVolumeIndex(const IVolumeCurves &curves, + int &index, + audio_devices_t device) const +{ + if (!audio_is_output_device(device)) { + return BAD_VALUE; + } + device = Volume::getDeviceForVolume(device); + index = curves.getVolumeIndex(device); + ALOGV("%s: device %08x index %d", __FUNCTION__, device, index); + return NO_ERROR; +} + +status_t AudioPolicyManager::getMinVolumeIndexForAttributes(const audio_attributes_t &attr, + int &index) +{ + index = getVolumeCurves(attr).getVolumeIndexMin(); + return NO_ERROR; +} + +status_t AudioPolicyManager::getMaxVolumeIndexForAttributes(const audio_attributes_t &attr, + int &index) +{ + index = getVolumeCurves(attr).getVolumeIndexMax(); + return NO_ERROR; +} + audio_io_handle_t AudioPolicyManager::selectOutputForMusicEffects() { // select one output among several suitable for global effects. diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h index 9fe8d1daa5..641a03ad88 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.h +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h @@ -161,6 +161,27 @@ public: int *index, audio_devices_t device); + virtual status_t setVolumeIndexForAttributes(const audio_attributes_t &attr, + int index, + audio_devices_t device); + virtual status_t getVolumeIndexForAttributes(const audio_attributes_t &attr, + int &index, + audio_devices_t device); + virtual status_t getMaxVolumeIndexForAttributes(const audio_attributes_t &attr, int &index); + + virtual status_t getMinVolumeIndexForAttributes(const audio_attributes_t &attr, int &index); + + status_t setVolumeGroupIndex(IVolumeCurves &volumeCurves, volume_group_t group, int index, + audio_devices_t device, const audio_attributes_t attributes); + + status_t setVolumeCurveIndex(volume_group_t volumeGroup, + int index, + audio_devices_t device, + IVolumeCurves &volumeCurves); + + status_t getVolumeIndex(const IVolumeCurves &curves, int &index, + audio_devices_t device) const; + // return the strategy corresponding to a given stream type virtual uint32_t getStrategyForStream(audio_stream_type_t stream) { diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp index d826192d9f..5748334e0e 100644 --- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp +++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp @@ -222,6 +222,12 @@ void AudioPolicyService::AudioPolicyClient::onRecordingConfigurationUpdate( clientConfig, clientEffects, deviceConfig, effects, patchHandle, source); } +void AudioPolicyService::AudioPolicyClient::onAudioVolumeGroupChanged(volume_group_t group, + int flags) +{ + mAudioPolicyService->onAudioVolumeGroupChanged(group, flags); +} + audio_unique_id_t AudioPolicyService::AudioPolicyClient::newAudioUniqueId(audio_unique_id_use_t use) { return AudioSystem::newAudioUniqueId(use); diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp index c19016f612..a1b6b0fb06 100644 --- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp +++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp @@ -689,6 +689,53 @@ status_t AudioPolicyService::getStreamVolumeIndex(audio_stream_type_t stream, device); } +status_t AudioPolicyService::setVolumeIndexForAttributes(const audio_attributes_t &attributes, + int index, audio_devices_t device) +{ + if (mAudioPolicyManager == NULL) { + return NO_INIT; + } + if (!settingsAllowed()) { + return PERMISSION_DENIED; + } + Mutex::Autolock _l(mLock); + AutoCallerClear acc; + return mAudioPolicyManager->setVolumeIndexForAttributes(attributes, index, device); +} + +status_t AudioPolicyService::getVolumeIndexForAttributes(const audio_attributes_t &attributes, + int &index, audio_devices_t device) +{ + if (mAudioPolicyManager == NULL) { + return NO_INIT; + } + Mutex::Autolock _l(mLock); + AutoCallerClear acc; + return mAudioPolicyManager->getVolumeIndexForAttributes(attributes, index, device); +} + +status_t AudioPolicyService::getMinVolumeIndexForAttributes(const audio_attributes_t &attributes, + int &index) +{ + if (mAudioPolicyManager == NULL) { + return NO_INIT; + } + Mutex::Autolock _l(mLock); + AutoCallerClear acc; + return mAudioPolicyManager->getMinVolumeIndexForAttributes(attributes, index); +} + +status_t AudioPolicyService::getMaxVolumeIndexForAttributes(const audio_attributes_t &attributes, + int &index) +{ + if (mAudioPolicyManager == NULL) { + return NO_INIT; + } + Mutex::Autolock _l(mLock); + AutoCallerClear acc; + return mAudioPolicyManager->getMaxVolumeIndexForAttributes(attributes, index); +} + uint32_t AudioPolicyService::getStrategyForStream(audio_stream_type_t stream) { if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) { diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp index 76ac191503..cf9cf71b0e 100644 --- a/services/audiopolicy/service/AudioPolicyService.cpp +++ b/services/audiopolicy/service/AudioPolicyService.cpp @@ -150,6 +150,20 @@ void AudioPolicyService::setAudioPortCallbacksEnabled(bool enabled) mNotificationClients.valueFor(token)->setAudioPortCallbacksEnabled(enabled); } +void AudioPolicyService::setAudioVolumeGroupCallbacksEnabled(bool enabled) +{ + Mutex::Autolock _l(mNotificationClientsLock); + + uid_t uid = IPCThreadState::self()->getCallingUid(); + pid_t pid = IPCThreadState::self()->getCallingPid(); + int64_t token = ((int64_t)uid<<32) | pid; + + if (mNotificationClients.indexOfKey(token) < 0) { + return; + } + mNotificationClients.valueFor(token)->setAudioVolumeGroupCallbacksEnabled(enabled); +} + // removeNotificationClient() is called when the client process dies. void AudioPolicyService::removeNotificationClient(uid_t uid, pid_t pid) { @@ -200,6 +214,19 @@ void AudioPolicyService::doOnAudioPatchListUpdate() } } +void AudioPolicyService::onAudioVolumeGroupChanged(volume_group_t group, int flags) +{ + mOutputCommandThread->changeAudioVolumeGroupCommand(group, flags); +} + +void AudioPolicyService::doOnAudioVolumeGroupChanged(volume_group_t group, int flags) +{ + Mutex::Autolock _l(mNotificationClientsLock); + for (size_t i = 0; i < mNotificationClients.size(); i++) { + mNotificationClients.valueAt(i)->onAudioVolumeGroupChanged(group, flags); + } +} + void AudioPolicyService::onDynamicPolicyMixStateUpdate(const String8& regId, int32_t state) { ALOGV("AudioPolicyService::onDynamicPolicyMixStateUpdate(%s, %d)", @@ -270,7 +297,7 @@ AudioPolicyService::NotificationClient::NotificationClient(const sponAudioVolumeGroupChanged(group, flags); + } +} + + void AudioPolicyService::NotificationClient::onDynamicPolicyMixStateUpdate( const String8& regId, int32_t state) { @@ -330,6 +366,10 @@ void AudioPolicyService::NotificationClient::setAudioPortCallbacksEnabled(bool e mAudioPortCallbacksEnabled = enabled; } +void AudioPolicyService::NotificationClient::setAudioVolumeGroupCallbacksEnabled(bool enabled) +{ + mAudioVolumeGroupCallbacksEnabled = enabled; +} void AudioPolicyService::binderDied(const wp& who) { ALOGW("binderDied() %p, calling pid %d", who.unsafe_get(), @@ -1058,6 +1098,18 @@ bool AudioPolicyService::AudioCommandThread::threadLoop() svc->doOnAudioPatchListUpdate(); mLock.lock(); }break; + case CHANGED_AUDIOVOLUMEGROUP: { + AudioVolumeGroupData *data = + static_cast(command->mParam.get()); + ALOGV("AudioCommandThread() processing update audio volume group"); + svc = mService.promote(); + if (svc == 0) { + break; + } + mLock.unlock(); + svc->doOnAudioVolumeGroupChanged(data->mGroup, data->mFlags); + mLock.lock(); + }break; case SET_AUDIOPORT_CONFIG: { SetAudioPortConfigData *data = (SetAudioPortConfigData *)command->mParam.get(); ALOGV("AudioCommandThread() processing set port config"); @@ -1302,6 +1354,19 @@ void AudioPolicyService::AudioCommandThread::updateAudioPatchListCommand() sendCommand(command); } +void AudioPolicyService::AudioCommandThread::changeAudioVolumeGroupCommand(volume_group_t group, + int flags) +{ + spcommand = new AudioCommand(); + command->mCommand = CHANGED_AUDIOVOLUMEGROUP; + AudioVolumeGroupData *data= new AudioVolumeGroupData(); + data->mGroup = group; + data->mFlags = flags; + command->mParam = data; + ALOGV("AudioCommandThread() adding audio volume group changed"); + sendCommand(command); +} + status_t AudioPolicyService::AudioCommandThread::setAudioPortConfigCommand( const struct audio_port_config *config, int delayMs) { diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h index e19b4e5c22..5888841707 100644 --- a/services/audiopolicy/service/AudioPolicyService.h +++ b/services/audiopolicy/service/AudioPolicyService.h @@ -111,6 +111,17 @@ public: int *index, audio_devices_t device); + virtual status_t setVolumeIndexForAttributes(const audio_attributes_t &attr, + int index, + audio_devices_t device); + virtual status_t getVolumeIndexForAttributes(const audio_attributes_t &attr, + int &index, + audio_devices_t device); + virtual status_t getMinVolumeIndexForAttributes(const audio_attributes_t &attr, + int &index); + virtual status_t getMaxVolumeIndexForAttributes(const audio_attributes_t &attr, + int &index); + virtual uint32_t getStrategyForStream(audio_stream_type_t stream); virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream); @@ -192,6 +203,8 @@ public: virtual void setAudioPortCallbacksEnabled(bool enabled); + virtual void setAudioVolumeGroupCallbacksEnabled(bool enabled); + virtual status_t acquireSoundTriggerSession(audio_session_t *session, audio_io_handle_t *ioHandle, audio_devices_t *device); @@ -275,6 +288,9 @@ public: audio_patch_handle_t patchHandle, audio_source_t source); + void onAudioVolumeGroupChanged(volume_group_t group, int flags); + void doOnAudioVolumeGroupChanged(volume_group_t group, int flags); + private: AudioPolicyService() ANDROID_API; virtual ~AudioPolicyService(); @@ -404,6 +420,7 @@ private: RELEASE_AUDIO_PATCH, UPDATE_AUDIOPORT_LIST, UPDATE_AUDIOPATCH_LIST, + CHANGED_AUDIOVOLUMEGROUP, SET_AUDIOPORT_CONFIG, DYN_POLICY_MIX_STATE_UPDATE, RECORDING_CONFIGURATION_UPDATE @@ -435,6 +452,7 @@ private: int delayMs); void updateAudioPortListCommand(); void updateAudioPatchListCommand(); + void changeAudioVolumeGroupCommand(volume_group_t group, int flags); status_t setAudioPortConfigCommand(const struct audio_port_config *config, int delayMs); void dynamicPolicyMixStateUpdateCommand(const String8& regId, @@ -516,6 +534,12 @@ private: audio_patch_handle_t mHandle; }; + class AudioVolumeGroupData : public AudioCommandData { + public: + volume_group_t mGroup; + int mFlags; + }; + class SetAudioPortConfigData : public AudioCommandData { public: struct audio_port_config mConfig; @@ -648,6 +672,8 @@ private: audio_patch_handle_t patchHandle, audio_source_t source); + virtual void onAudioVolumeGroupChanged(volume_group_t group, int flags); + virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use); private: @@ -666,6 +692,7 @@ private: void onAudioPatchListUpdate(); void onDynamicPolicyMixStateUpdate(const String8& regId, int32_t state); + void onAudioVolumeGroupChanged(volume_group_t group, int flags); void onRecordingConfigurationUpdate( int event, const record_client_info_t *clientInfo, @@ -676,6 +703,7 @@ private: audio_patch_handle_t patchHandle, audio_source_t source); void setAudioPortCallbacksEnabled(bool enabled); + void setAudioVolumeGroupCallbacksEnabled(bool enabled); uid_t uid() { return mUid; @@ -693,6 +721,7 @@ private: const pid_t mPid; const sp mAudioPolicyServiceClient; bool mAudioPortCallbacksEnabled; + bool mAudioVolumeGroupCallbacksEnabled; }; class AudioClient : public virtual RefBase { diff --git a/services/audiopolicy/tests/AudioPolicyTestClient.h b/services/audiopolicy/tests/AudioPolicyTestClient.h index 6ae354bdba..8854eb2e6d 100644 --- a/services/audiopolicy/tests/AudioPolicyTestClient.h +++ b/services/audiopolicy/tests/AudioPolicyTestClient.h @@ -73,6 +73,7 @@ public: int /*delayMs*/) override { return NO_INIT; } void onAudioPortListUpdate() override { } void onAudioPatchListUpdate() override { } + void onAudioVolumeGroupChanged(volume_group_t /*group*/, int /*flags*/) override { } audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t /*use*/) override { return 0; } void onDynamicPolicyMixStateUpdate(String8 /*regId*/, int32_t /*state*/) override { } void onRecordingConfigurationUpdate(int event __unused,