diff options
Diffstat (limited to 'services/audiopolicy/engineconfigurable/src')
13 files changed, 1563 insertions, 0 deletions
diff --git a/services/audiopolicy/engineconfigurable/src/Collection.h b/services/audiopolicy/engineconfigurable/src/Collection.h new file mode 100755 index 0000000..8f17b15 --- /dev/null +++ b/services/audiopolicy/engineconfigurable/src/Collection.h @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2015 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 "Element.h" +#include "Stream.h" +#include "Strategy.h" +#include "Usage.h" +#include "InputSource.h" +#include <utils/Errors.h> +#include <system/audio.h> +#include <utils/Log.h> +#include <map> +#include <stdint.h> +#include <string> + +namespace android +{ +namespace audio_policy +{ + +/** + * Collection of policy element as a map indexed with a their UID type. + * + * @tparam Key type of the policy element indexing the collection. + * Policy Element supported are: + * - Strategy + * - Stream + * - InputSource + * - Usage. + */ +template <typename Key> +class Collection : public std::map<Key, Element<Key> *> +{ +private: + typedef Element<Key> T; + typedef typename std::map<Key, T *>::iterator CollectionIterator; + typedef typename std::map<Key, T *>::const_iterator CollectionConstIterator; + +public: + Collection() + { + collectionSupported(); + } + + /** + * Add a policy element to the collection. Policy elements are streams, strategies, input + * sources, ... Compile time error generated if called with not supported collection. + * It also set the key as the unique identifier of the policy element. + * + * @tparam Key indexing the collection of policy element. + * @param[in] name of the policy element to find. + * @param[in] key to be used to index this new policy element. + * + * @return NO_ERROR if the policy element has been successfully added to the collection. + */ + status_t add(const std::string &name, Key key) + { + if ((*this).find(key) != (*this).end()) { + ALOGW("%s: element %s already added", __FUNCTION__, name.c_str()); + return BAD_VALUE; + } + (*this)[key] = new T(name); + ALOGD("%s: adding element %s to collection", __FUNCTION__, name.c_str()); + return (*this)[key]->setIdentifier(key); + } + + /** + * Get a policy element from the collection by its key. Policy elements are streams, strategies, + * input sources, ... Compile time error generated if called with not supported collection. + * + * @tparam Key indexing the collection of policy element. + * @param[in] key of the policy element to find. + * + * @return valid pointer on policy element if found, NULL otherwise. + */ + T *get(Key key) const + { + CollectionConstIterator it = (*this).find(key); + return (it == (*this).end()) ? NULL : it->second; + } + + /** + * Find a policy element from the collection by its name. Policy elements are streams, + * strategies, input sources, ... + * Compile time error generated if called with not supported collection. + * + * @tparam Key indexing the collection of policy element. + * @param[in] name of the policy element to find. + * @param[in] elementsMap maps of policy elements to search into. + * + * @return valid pointer on element if found, NULL otherwise. + */ + T *findByName(const std::string &name) const + { + + CollectionConstIterator it; + for (it = (*this).begin(); it != (*this).end(); ++it) { + T *element = it->second; + if (element->getName() == name) { + return element; + } + } + return NULL; + } + + /** + * Removes all the elements from the list and destroy them. + */ + void clear() + { + CollectionIterator it; + for (it = (*this).begin(); it != (*this).end(); ++it) { + delete it->second; + } + (*this).clear(); + } + +private: + /** + * provide a compile time error if no specialization is provided for a given type. + * + * @tparam T: type of the policyElement. Policy Element supported are: + * - Strategy + * - Stream + * - InputSource + * - Usage. + */ + struct collectionSupported; +}; + +template <> +struct Collection<audio_stream_type_t>::collectionSupported {}; +template <> +struct Collection<std::string>::collectionSupported {}; +template <> +struct Collection<audio_usage_t>::collectionSupported {}; +template <> +struct Collection<audio_source_t>::collectionSupported {}; +template <> +struct Collection<routing_strategy>::collectionSupported {}; + +typedef Collection<routing_strategy> StrategyCollection; +typedef Collection<audio_stream_type_t> StreamCollection; +typedef Collection<audio_usage_t> UsageCollection; +typedef Collection<audio_source_t> InputSourceCollection; + +} // namespace audio_policy +} // namespace android diff --git a/services/audiopolicy/engineconfigurable/src/Element.h b/services/audiopolicy/engineconfigurable/src/Element.h new file mode 100755 index 0000000..52e77e5 --- /dev/null +++ b/services/audiopolicy/engineconfigurable/src/Element.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2015 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 <stdint.h> +#include <string> +#include <utils/Errors.h> +#include <system/audio.h> +#include <utils/Log.h> + +namespace android +{ +namespace audio_policy +{ + +template <typename Key> +class Element +{ +public: + Element(const std::string &name) + : mName(name) + {} + ~Element() {} + + /** + * Returns identifier of this policy element + * + * @returns string representing the name of this policy element + */ + const std::string &getName() const { return mName; } + + /** + * Set the unique identifier for this policy element. + * + * @tparam Key type of the unique identifier. + * @param[in] identifier to be set. + * + * @return NO_ERROR if the identifier is valid and set correctly, error code otherwise. + */ + status_t setIdentifier(Key identifier) + { + mIdentifier = identifier; + return NO_ERROR; + } + + /** + * @return the unique identifier of this policy element. + */ + const Key &getIdentifier() const { return mIdentifier; } + + /** + * A Policy element may implement getter/setter function for a given property. + * Property may be routing_strategy, audio_stream_type_t, audio_usage_t, audio_source_t + * or a string. + * + * @tparam Property for which this policy element has setter / getter. + * @return the property kept track by this policy base element. + */ + template <typename Property> + Property get() const; + + /** + * A Policy element may implement getter/setter function for a given property. + * Property may be routing_strategy, audio_stream_type_t, audio_usage_t, audio_source_t + * or a string. + * + * @tparam Property for which this policy element has setter / getter. + * + * @param[in] property value to be assigned for this policy base element. + * + * @return the property kept track by this policy base element. + */ + template <typename Property> + status_t set(Property property); + +private: + /* Copy facilities are put private to disable copy. */ + Element(const Element &object); + Element &operator=(const Element &object); + + std::string mName; /**< Unique literal Identifier of a policy base element*/ + Key mIdentifier; /**< Unique numerical Identifier of a policy base element*/ +}; +} // namespace audio_policy +} // namespace android diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp new file mode 100755 index 0000000..c5cccfd --- /dev/null +++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2015 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 "APM::AudioPolicyEngine" +//#define LOG_NDEBUG 0 + +//#define VERY_VERBOSE_LOGGING +#ifdef VERY_VERBOSE_LOGGING +#define ALOGVV ALOGV +#else +#define ALOGVV(a...) do { } while(0) +#endif + +#include "Engine.h" +#include "Strategy.h" +#include "Stream.h" +#include "InputSource.h" +#include "Usage.h" +#include <policy.h> +#include <ParameterManagerWrapper.h> + +using std::string; +using std::map; + +namespace android +{ +namespace audio_policy +{ +template <> +StrategyCollection &Engine::getCollection<routing_strategy>() +{ + return mStrategyCollection; +} +template <> +StreamCollection &Engine::getCollection<audio_stream_type_t>() +{ + return mStreamCollection; +} +template <> +UsageCollection &Engine::getCollection<audio_usage_t>() +{ + return mUsageCollection; +} +template <> +InputSourceCollection &Engine::getCollection<audio_source_t>() +{ + return mInputSourceCollection; +} + +template <> +const StrategyCollection &Engine::getCollection<routing_strategy>() const +{ + return mStrategyCollection; +} +template <> +const StreamCollection &Engine::getCollection<audio_stream_type_t>() const +{ + return mStreamCollection; +} +template <> +const UsageCollection &Engine::getCollection<audio_usage_t>() const +{ + return mUsageCollection; +} +template <> +const InputSourceCollection &Engine::getCollection<audio_source_t>() const +{ + return mInputSourceCollection; +} + +Engine::Engine() + : mManagerInterface(this), + mPluginInterface(this), + mPolicyParameterMgr(new ParameterManagerWrapper()), + mApmObserver(NULL) +{ + if (mPolicyParameterMgr->start() != NO_ERROR) { + ALOGE("%s: could not start Policy PFW", __FUNCTION__); + delete mPolicyParameterMgr; + mPolicyParameterMgr = NULL; + } +} + +Engine::~Engine() +{ + mStrategyCollection.clear(); + mStreamCollection.clear(); + mInputSourceCollection.clear(); + mUsageCollection.clear(); +} + + +void Engine::setObserver(AudioPolicyManagerObserver *observer) +{ + ALOG_ASSERT(observer != NULL, "Invalid Audio Policy Manager observer"); + mApmObserver = observer; +} + +status_t Engine::initCheck() +{ + return (mPolicyParameterMgr != NULL) && + mPolicyParameterMgr->isStarted() && + (mApmObserver != NULL)? + NO_ERROR : NO_INIT; +} + +bool Engine::setVolumeProfileForStream(const audio_stream_type_t &streamType, + Volume::device_category deviceCategory, + const VolumeCurvePoints &points) +{ + Stream *stream = getFromCollection<audio_stream_type_t>(streamType); + if (stream == NULL) { + ALOGE("%s: stream %d not found", __FUNCTION__, streamType); + return false; + } + return stream->setVolumeProfile(deviceCategory, points) == NO_ERROR; +} + +template <typename Key> +Element<Key> *Engine::getFromCollection(const Key &key) const +{ + const Collection<Key> collection = getCollection<Key>(); + return collection.get(key); +} + +template <typename Key> +status_t Engine::add(const std::string &name, const Key &key) +{ + Collection<Key> &collection = getCollection<Key>(); + return collection.add(name, key); +} + +template <> +routing_strategy Engine::getPropertyForKey<routing_strategy, audio_usage_t>(audio_usage_t usage) const +{ + const AudioOutputCollection &outputs = mApmObserver->getOutputs(); + + if (usage == AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY && + (outputs.isStreamActive(AUDIO_STREAM_RING) || + outputs.isStreamActive(AUDIO_STREAM_ALARM))) { + return STRATEGY_SONIFICATION; + } + return getPropertyForKey<routing_strategy, audio_usage_t>(usage); +} + +template <typename Property, typename Key> +Property Engine::getPropertyForKey(Key key) const +{ + Element<Key> *element = getFromCollection<Key>(key); + if (element == NULL) { + ALOGE("%s: Element not found within collection", __FUNCTION__); + return static_cast<Property>(0); + } + return element->template get<Property>(); +} + +template <> +audio_devices_t Engine::getPropertyForKey<audio_devices_t, routing_strategy>(routing_strategy strategy) const +{ + const AudioOutputCollection &outputs = mApmObserver->getOutputs(); + + /** This is the only case handled programmatically because the PFW is unable to know the + * activity of streams. + * + * -While media is playing on a remote device, use the the sonification behavior. + * Note that we test this usecase before testing if media is playing because + * the isStreamActive() method only informs about the activity of a stream, not + * if it's for local playback. Note also that we use the same delay between both tests + * + * -When media is not playing anymore, fall back on the sonification behavior + */ + if (strategy == STRATEGY_SONIFICATION_RESPECTFUL && + !is_state_in_call(getPhoneState()) && + !outputs.isStreamActiveRemotely(AUDIO_STREAM_MUSIC, + SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY) && + outputs.isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) { + return getPropertyForKey<audio_devices_t, routing_strategy>(STRATEGY_MEDIA); + } + return getPropertyForKey<audio_devices_t, routing_strategy>(strategy); +} + +routing_strategy Engine::ManagerInterfaceImpl::getStrategyForUsage(audio_usage_t usage) +{ + return mPolicyEngine->getPropertyForKey<routing_strategy, audio_usage_t>(usage); +} + +audio_devices_t Engine::ManagerInterfaceImpl::getDeviceForStrategy(routing_strategy stategy) const +{ + return mPolicyEngine->getPropertyForKey<audio_devices_t, routing_strategy>(stategy); +} + +template <typename Property, typename Key> +bool Engine::setPropertyForKey(const Property &property, const Key &key) +{ + Element<Key> *element = getFromCollection<Key>(key); + if (element == NULL) { + ALOGE("%s: Element not found within collection", __FUNCTION__); + return BAD_VALUE; + } + return element->template set<Property>(property) == NO_ERROR; +} + +float Engine::volIndexToAmpl(Volume::device_category category, + audio_stream_type_t streamType, + int indexInUi) +{ + Stream *stream = getFromCollection<audio_stream_type_t>(streamType); + if (stream == NULL) { + ALOGE("%s: Element indexed by key=%d not found", __FUNCTION__, streamType); + return 1.0f; + } + return stream->volIndexToAmpl(category, indexInUi); +} + +status_t Engine::initStreamVolume(audio_stream_type_t streamType, + int indexMin, int indexMax) +{ + Stream *stream = getFromCollection<audio_stream_type_t>(streamType); + if (stream == NULL) { + ALOGE("%s: Stream Type %d not found", __FUNCTION__, streamType); + return BAD_TYPE; + } + return stream->initVolume(indexMin, indexMax); +} + +status_t Engine::setPhoneState(audio_mode_t mode) +{ + return mPolicyParameterMgr->setPhoneState(mode); +} + +audio_mode_t Engine::getPhoneState() const +{ + return mPolicyParameterMgr->getPhoneState(); +} + +status_t Engine::setForceUse(audio_policy_force_use_t usage, + audio_policy_forced_cfg_t config) +{ + return mPolicyParameterMgr->setForceUse(usage, config); +} + +audio_policy_forced_cfg_t Engine::getForceUse(audio_policy_force_use_t usage) const +{ + return mPolicyParameterMgr->getForceUse(usage); +} + +status_t Engine::setDeviceConnectionState(audio_devices_t devices, audio_policy_dev_state_t state, + const char *deviceAddress) +{ + return mPolicyParameterMgr->setDeviceConnectionState(devices, state, deviceAddress); +} + +template <> +AudioPolicyManagerInterface *Engine::queryInterface() +{ + return &mManagerInterface; +} + +template <> +AudioPolicyPluginInterface *Engine::queryInterface() +{ + return &mPluginInterface; +} + +} // namespace audio_policy +} // namespace android + + diff --git a/services/audiopolicy/engineconfigurable/src/Engine.h b/services/audiopolicy/engineconfigurable/src/Engine.h new file mode 100755 index 0000000..23ca7d0 --- /dev/null +++ b/services/audiopolicy/engineconfigurable/src/Engine.h @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2015 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 <AudioPolicyManagerInterface.h> +#include <AudioPolicyPluginInterface.h> +#include "Collection.h" + +namespace android +{ +class AudioPolicyManagerObserver; + +namespace audio_policy +{ + +class ParameterManagerWrapper; +class VolumeProfile; + +class Engine +{ +public: + Engine(); + virtual ~Engine(); + + template <class RequestedInterface> + RequestedInterface *queryInterface(); + +private: + /// Interface members + class ManagerInterfaceImpl : public AudioPolicyManagerInterface + { + public: + ManagerInterfaceImpl(Engine *policyEngine) + : mPolicyEngine(policyEngine) {} + + virtual android::status_t initCheck() + { + return mPolicyEngine->initCheck(); + } + virtual void setObserver(AudioPolicyManagerObserver *observer) + { + mPolicyEngine->setObserver(observer); + } + virtual audio_devices_t getDeviceForInputSource(audio_source_t inputSource) const + { + return mPolicyEngine->getPropertyForKey<audio_devices_t, audio_source_t>(inputSource); + } + virtual audio_devices_t getDeviceForStrategy(routing_strategy stategy) const; + virtual routing_strategy getStrategyForStream(audio_stream_type_t stream) + { + return mPolicyEngine->getPropertyForKey<routing_strategy, audio_stream_type_t>(stream); + } + virtual routing_strategy getStrategyForUsage(audio_usage_t usage); + virtual status_t setPhoneState(audio_mode_t mode) + { + return mPolicyEngine->setPhoneState(mode); + } + virtual audio_mode_t getPhoneState() const + { + return mPolicyEngine->getPhoneState(); + } + virtual status_t setForceUse(audio_policy_force_use_t usage, + audio_policy_forced_cfg_t config) + { + return mPolicyEngine->setForceUse(usage, config); + } + virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) const + { + return mPolicyEngine->getForceUse(usage); + } + virtual android::status_t setDeviceConnectionState(const sp<DeviceDescriptor> devDesc, + audio_policy_dev_state_t state) + { + return mPolicyEngine->setDeviceConnectionState(devDesc->type(), state, + devDesc->mAddress); + } + virtual status_t initStreamVolume(audio_stream_type_t stream, + int indexMin, int indexMax) + { + return mPolicyEngine->initStreamVolume(stream, indexMin, indexMax); + } + + virtual void initializeVolumeCurves(bool /*isSpeakerDrcEnabled*/) {} + + virtual float volIndexToAmpl(Volume::device_category deviceCategory, + audio_stream_type_t stream, + int indexInUi) + { + return mPolicyEngine->volIndexToAmpl(deviceCategory, stream, indexInUi); + } + + private: + Engine *mPolicyEngine; + } mManagerInterface; + + class PluginInterfaceImpl : public AudioPolicyPluginInterface + { + public: + PluginInterfaceImpl(Engine *policyEngine) + : mPolicyEngine(policyEngine) {} + + virtual status_t addStrategy(const std::string &name, routing_strategy strategy) + { + return mPolicyEngine->add<routing_strategy>(name, strategy); + } + virtual status_t addStream(const std::string &name, audio_stream_type_t stream) + { + return mPolicyEngine->add<audio_stream_type_t>(name, stream); + } + virtual status_t addUsage(const std::string &name, audio_usage_t usage) + { + return mPolicyEngine->add<audio_usage_t>(name, usage); + } + virtual status_t addInputSource(const std::string &name, audio_source_t source) + { + return mPolicyEngine->add<audio_source_t>(name, source); + } + virtual bool setDeviceForStrategy(const routing_strategy &strategy, audio_devices_t devices) + { + return mPolicyEngine->setPropertyForKey<audio_devices_t, routing_strategy>(devices, + strategy); + } + virtual bool setStrategyForStream(const audio_stream_type_t &stream, + routing_strategy strategy) + { + return mPolicyEngine->setPropertyForKey<routing_strategy, audio_stream_type_t>(strategy, + stream); + } + virtual bool setVolumeProfileForStream(const audio_stream_type_t &stream, + Volume::device_category deviceCategory, + const VolumeCurvePoints &points) + { + return mPolicyEngine->setVolumeProfileForStream(stream, deviceCategory, points); + } + + virtual bool setStrategyForUsage(const audio_usage_t &usage, routing_strategy strategy) + { + return mPolicyEngine->setPropertyForKey<routing_strategy, audio_usage_t>(strategy, + usage); + } + virtual bool setDeviceForInputSource(const audio_source_t &inputSource, + audio_devices_t device) + { + return mPolicyEngine->setPropertyForKey<audio_devices_t, audio_source_t>(device, + inputSource); + } + + private: + Engine *mPolicyEngine; + } mPluginInterface; + +private: + /* Copy facilities are put private to disable copy. */ + Engine(const Engine &object); + Engine &operator=(const Engine &object); + + void setObserver(AudioPolicyManagerObserver *observer); + + bool setVolumeProfileForStream(const audio_stream_type_t &stream, + Volume::device_category deviceCategory, + const VolumeCurvePoints &points); + + status_t initCheck(); + status_t setPhoneState(audio_mode_t mode); + audio_mode_t getPhoneState() const; + status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config); + audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) const; + status_t setDeviceConnectionState(audio_devices_t devices, audio_policy_dev_state_t state, + const char *deviceAddress); + + float volIndexToAmpl(Volume::device_category category, + audio_stream_type_t stream, + int indexInUi); + status_t initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax); + + StrategyCollection mStrategyCollection; /**< Strategies indexed by their enum id. */ + StreamCollection mStreamCollection; /**< Streams indexed by their enum id. */ + UsageCollection mUsageCollection; /**< Usages indexed by their enum id. */ + InputSourceCollection mInputSourceCollection; /**< Input sources indexed by their enum id. */ + + template <typename Key> + status_t add(const std::string &name, const Key &key); + + template <typename Key> + Element<Key> *getFromCollection(const Key &key) const; + + template <typename Key> + const Collection<Key> &getCollection() const; + + template <typename Key> + Collection<Key> &getCollection(); + + template <typename Property, typename Key> + Property getPropertyForKey(Key key) const; + + template <typename Property, typename Key> + bool setPropertyForKey(const Property &property, const Key &key); + + /** + * Policy Parameter Manager hidden through a wrapper. + */ + ParameterManagerWrapper *mPolicyParameterMgr; + + AudioPolicyManagerObserver *mApmObserver; +}; + +}; // namespace audio_policy + +}; // namespace android + diff --git a/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp b/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp new file mode 100755 index 0000000..9aa89b2 --- /dev/null +++ b/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2015 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. + */ + +#include <AudioPolicyManagerInterface.h> +#include <AudioPolicyPluginInterface.h> +#include "AudioPolicyEngineInstance.h" +#include "Engine.h" + +using std::string; + +namespace android +{ +namespace audio_policy +{ + +EngineInstance::EngineInstance() +{ +} + +EngineInstance *EngineInstance::getInstance() +{ + static EngineInstance instance; + return &instance; +} + +EngineInstance::~EngineInstance() +{ +} + +Engine *EngineInstance::getEngine() const +{ + static Engine engine; + return &engine; +} + +template <> +AudioPolicyManagerInterface *EngineInstance::queryInterface() const +{ + return getEngine()->queryInterface<AudioPolicyManagerInterface>(); +} + +template <> +AudioPolicyPluginInterface *EngineInstance::queryInterface() const +{ + return getEngine()->queryInterface<AudioPolicyPluginInterface>(); +} + +} // namespace audio_policy +} // namespace android + diff --git a/services/audiopolicy/engineconfigurable/src/InputSource.cpp b/services/audiopolicy/engineconfigurable/src/InputSource.cpp new file mode 100755 index 0000000..9ff1538 --- /dev/null +++ b/services/audiopolicy/engineconfigurable/src/InputSource.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2015 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 "APM::AudioPolicyEngine/InputSource" + +#include "InputSource.h" + +using std::string; + +namespace android +{ +namespace audio_policy +{ +status_t Element<audio_source_t>::setIdentifier(audio_source_t identifier) +{ + if (identifier > AUDIO_SOURCE_MAX && identifier != AUDIO_SOURCE_HOTWORD) { + return BAD_VALUE; + } + mIdentifier = identifier; + ALOGD("%s: InputSource %s identifier 0x%X", __FUNCTION__, getName().c_str(), identifier); + return NO_ERROR; +} + +/** +* Set the device associated to this source. +* It checks if the input device is valid but allows to set a NONE device +* (i.e. only the IN BIT is set). +* +* @param[in] devices selected for the given input source. +* @tparam audio_devices_t: Applicable input device for this input source. +* +* @return NO_ERROR if the device is either valid or none, error code otherwise. +*/ +template <> +status_t Element<audio_source_t>::set(audio_devices_t devices) +{ + if (!audio_is_input_device(devices) && devices != AUDIO_DEVICE_BIT_IN) { + ALOGE("%s: trying to set an invalid device 0x%X for input source %s", + __FUNCTION__, devices, getName().c_str()); + return BAD_VALUE; + } + ALOGD("%s: 0x%X for input source %s", __FUNCTION__, devices, getName().c_str()); + mApplicableDevices = devices; + return NO_ERROR; +} + +template <> +audio_devices_t Element<audio_source_t>::get<audio_devices_t>() const +{ + ALOGV("%s: 0x%X for inputSource %s", __FUNCTION__, mApplicableDevices, getName().c_str()); + return mApplicableDevices; +} +} // namespace audio_policy +} // namespace android + + diff --git a/services/audiopolicy/engineconfigurable/src/InputSource.h b/services/audiopolicy/engineconfigurable/src/InputSource.h new file mode 100755 index 0000000..6c498dc --- /dev/null +++ b/services/audiopolicy/engineconfigurable/src/InputSource.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2015 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 "Element.h" + +namespace android +{ +namespace audio_policy +{ + +/** + * Specialization of policy base class element for audio_source_t + * @tparam audio_source_t Policy Base Element identified by the audio_source_t definition. + */ +template <> +class Element<audio_source_t> +{ +public: + Element(const std::string &name) + : mName(name), + mApplicableDevices(AUDIO_DEVICE_NONE) + {} + ~Element() {} + + /** + * Returns identifier of this policy element + * + * @returns string representing the name of this policy element + */ + const std::string &getName() const { return mName; } + + /** + * Set the unique identifier for this policy element. + * + * @tparam Key type of the unique identifier. + * @param[in] identifier to be set. + * + * @return NO_ERROR if the identifier is valid and set correctly, error code otherwise. + */ + status_t setIdentifier(audio_source_t identifier); + + /** + * @return the unique identifier of this policy element. + */ + audio_source_t getIdentifier() const { return mIdentifier; } + + /** + * A Policy element may implement getter/setter function for a given property. + * Property may be routing_strategy, audio_stream_type_t, audio_usage_t, audio_source_t + * or a string. + */ + template <typename Property> + Property get() const; + + template <typename Property> + status_t set(Property property); + +private: + /* Copy facilities are put private to disable copy. */ + Element(const Element &object); + Element &operator=(const Element &object); + + std::string mName; /**< Unique literal Identifier of a policy base element*/ + audio_source_t mIdentifier; /**< Unique numerical Identifier of a policy base element*/ + + audio_devices_t mApplicableDevices; /**< Applicable input device for this input source. */ +}; + +typedef Element<audio_source_t> InputSource; + +} // namespace audio_policy +} // namespace android + diff --git a/services/audiopolicy/engineconfigurable/src/Strategy.cpp b/services/audiopolicy/engineconfigurable/src/Strategy.cpp new file mode 100755 index 0000000..847443a --- /dev/null +++ b/services/audiopolicy/engineconfigurable/src/Strategy.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2015 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 "APM::AudioPolicyEngine/Strategy" + +#include "Strategy.h" + +using std::string; + +namespace android +{ +namespace audio_policy +{ + +status_t Element<routing_strategy>::setIdentifier(routing_strategy identifier) +{ + if (identifier >= NUM_STRATEGIES) { + return BAD_VALUE; + } + mIdentifier = identifier; + ALOGD("%s: Strategy %s identifier 0x%X", __FUNCTION__, getName().c_str(), identifier); + return NO_ERROR; +} + +/** + * Set the device associated to this strategy. + * It checks if the output device is valid but allows to set a NONE device + * + * @param[in] devices selected for the given strategy. + * + * @return NO_ERROR if the device is either valid or none, error code otherwise. + */ +template <> +status_t Element<routing_strategy>::set<audio_devices_t>(audio_devices_t devices) +{ + if (!audio_is_output_devices(devices) && devices != AUDIO_DEVICE_NONE) { + ALOGE("%s: trying to set an invalid device 0x%X for strategy %s", + __FUNCTION__, devices, getName().c_str()); + return BAD_VALUE; + } + ALOGD("%s: 0x%X for strategy %s", __FUNCTION__, devices, getName().c_str()); + mApplicableDevices = devices; + return NO_ERROR; +} + +template <> +audio_devices_t Element<routing_strategy>::get<audio_devices_t>() const +{ + ALOGV("%s: 0x%X for strategy %s", __FUNCTION__, mApplicableDevices, getName().c_str()); + return mApplicableDevices; +} + +} // namespace audio_policy +} // namespace android + diff --git a/services/audiopolicy/engineconfigurable/src/Strategy.h b/services/audiopolicy/engineconfigurable/src/Strategy.h new file mode 100755 index 0000000..1157d55 --- /dev/null +++ b/services/audiopolicy/engineconfigurable/src/Strategy.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2015 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 "Element.h" +#include <RoutingStrategy.h> + +namespace android +{ +namespace audio_policy +{ + +/** + * @tparam audio_devices_t: Applicable output device(s) for this strategy. + */ +template <> +class Element<routing_strategy> +{ +public: + Element(const std::string &name) + : mName(name), + mApplicableDevices(AUDIO_DEVICE_NONE) + {} + ~Element() {} + + /** + * Returns identifier of this policy element + * + * @returns string representing the name of this policy element + */ + const std::string &getName() const { return mName; } + + /** + * Set the unique identifier for this policy element. + * + * @tparam Key type of the unique identifier. + * @param[in] identifier to be set. + * + * @return NO_ERROR if the identifier is valid and set correctly, error code otherwise. + */ + status_t setIdentifier(routing_strategy identifier); + + /** + * @return the unique identifier of this policy element. + */ + routing_strategy getIdentifier() const { return mIdentifier; } + + /** + * A Policy element may implement getter/setter function for a given property. + * Property may be routing_strategy, audio_stream_type_t, audio_usage_t, audio_source_t + * or a string. + */ + template <typename Property> + Property get() const; + + template <typename Property> + status_t set(Property property); + +private: + /* Copy facilities are put private to disable copy. */ + Element(const Element &object); + Element &operator=(const Element &object); + + std::string mName; /**< Unique literal Identifier of a policy base element*/ + routing_strategy mIdentifier; /**< Unique numerical Identifier of a policy base element*/ + + audio_devices_t mApplicableDevices; /**< Applicable output device(s) for this strategy. */ +}; + +typedef Element<routing_strategy> Strategy; + +} // namespace audio_policy +} // namespace android + + diff --git a/services/audiopolicy/engineconfigurable/src/Stream.cpp b/services/audiopolicy/engineconfigurable/src/Stream.cpp new file mode 100755 index 0000000..7126c27 --- /dev/null +++ b/services/audiopolicy/engineconfigurable/src/Stream.cpp @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2015 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 "APM::AudioPolicyEngine/Stream" + +#include "Stream.h" +#include <system/audio.h> + +using std::string; + +namespace android +{ +namespace audio_policy +{ + +status_t Element<audio_stream_type_t>::setIdentifier(audio_stream_type_t identifier) +{ + if (identifier > AUDIO_STREAM_CNT) { + return BAD_VALUE; + } + mIdentifier = identifier; + ALOGD("%s: Stream %s identifier 0x%X", __FUNCTION__, getName().c_str(), identifier); + return NO_ERROR; +} + +/** +* Set the strategy to follow for this stream. +* It checks if the strategy is valid. +* +* @param[in] strategy to be followed. +* +* @return NO_ERROR if the strategy is set correctly, error code otherwise. +*/ +template <> +status_t Element<audio_stream_type_t>::set<routing_strategy>(routing_strategy strategy) +{ + if (strategy >= NUM_STRATEGIES) { + return BAD_VALUE; + } + mApplicableStrategy = strategy; + ALOGD("%s: 0x%X for Stream %s", __FUNCTION__, strategy, getName().c_str()); + return NO_ERROR; +} + +template <> +routing_strategy Element<audio_stream_type_t>::get<routing_strategy>() const +{ + ALOGV("%s: 0x%X for Stream %s", __FUNCTION__, mApplicableStrategy, getName().c_str()); + return mApplicableStrategy; +} + +status_t Element<audio_stream_type_t>::setVolumeProfile(Volume::device_category category, + const VolumeCurvePoints &points) +{ + ALOGD("%s: adding volume profile for %s for device category %d, points nb =%d", __FUNCTION__, + getName().c_str(), category, points.size()); + mVolumeProfiles[category] = points; + + for (size_t i = 0; i < points.size(); i++) { + ALOGV("%s: %s cat=%d curve index =%d Index=%d dBAttenuation=%f", + __FUNCTION__, getName().c_str(), category, i, points[i].mIndex, + points[i].mDBAttenuation); + } + return NO_ERROR; +} + +status_t Element<audio_stream_type_t>::initVolume(int indexMin, int indexMax) +{ + ALOGV("initStreamVolume() stream %s, min %d, max %d", getName().c_str(), indexMin, indexMax); + if (indexMin < 0 || indexMin >= indexMax) { + ALOGW("initStreamVolume() invalid index limits for stream %s, min %d, max %d", + getName().c_str(), indexMin, indexMax); + return BAD_VALUE; + } + mIndexMin = indexMin; + mIndexMax = indexMax; + + return NO_ERROR; +} + +float Element<audio_stream_type_t>::volIndexToAmpl(Volume::device_category deviceCategory, + int indexInUi) +{ + VolumeProfileConstIterator it = mVolumeProfiles.find(deviceCategory); + if (it == mVolumeProfiles.end()) { + ALOGE("%s: device category %d not found for stream %s", __FUNCTION__, deviceCategory, + getName().c_str()); + return 1.0f; + } + const VolumeCurvePoints curve = mVolumeProfiles[deviceCategory]; + if (curve.size() != Volume::VOLCNT) { + ALOGE("%s: invalid profile for category %d and for stream %s", __FUNCTION__, deviceCategory, + getName().c_str()); + return 1.0f; + } + + // the volume index in the UI is relative to the min and max volume indices for this stream type + int nbSteps = 1 + curve[Volume::VOLMAX].mIndex - + curve[Volume::VOLMIN].mIndex; + + if (mIndexMax - mIndexMin == 0) { + ALOGE("%s: Invalid volume indexes Min=Max=%d", __FUNCTION__, mIndexMin); + return 1.0f; + } + int volIdx = (nbSteps * (indexInUi - mIndexMin)) / + (mIndexMax - mIndexMin); + + // find what part of the curve this index volume belongs to, or if it's out of bounds + int segment = 0; + if (volIdx < curve[Volume::VOLMIN].mIndex) { // out of bounds + return 0.0f; + } else if (volIdx < curve[Volume::VOLKNEE1].mIndex) { + segment = 0; + } else if (volIdx < curve[Volume::VOLKNEE2].mIndex) { + segment = 1; + } else if (volIdx <= curve[Volume::VOLMAX].mIndex) { + segment = 2; + } else { // out of bounds + return 1.0f; + } + + // linear interpolation in the attenuation table in dB + float decibels = curve[segment].mDBAttenuation + + ((float)(volIdx - curve[segment].mIndex)) * + ( (curve[segment+1].mDBAttenuation - + curve[segment].mDBAttenuation) / + ((float)(curve[segment+1].mIndex - + curve[segment].mIndex)) ); + + float amplification = exp(decibels * 0.115129f); /** exp( dB * ln(10) / 20 ) */ + + ALOGV("VOLUME vol index=[%d %d %d], dB=[%.1f %.1f %.1f] ampl=%.5f", + curve[segment].mIndex, volIdx, + curve[segment+1].mIndex, + curve[segment].mDBAttenuation, + decibels, + curve[segment+1].mDBAttenuation, + amplification); + + return amplification; +} + +} // namespace audio_policy +} // namespace android + diff --git a/services/audiopolicy/engineconfigurable/src/Stream.h b/services/audiopolicy/engineconfigurable/src/Stream.h new file mode 100755 index 0000000..03a9b3e9 --- /dev/null +++ b/services/audiopolicy/engineconfigurable/src/Stream.h @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2015 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 "Element.h" +#include "EngineDefinition.h" +#include <Volume.h> +#include <RoutingStrategy.h> +#include <map> + +namespace android +{ +namespace audio_policy +{ +/** + * @tparam routing_strategy: Applicable strategy for this stream. + */ +template <> +class Element<audio_stream_type_t> +{ +private: + typedef std::map<Volume::device_category, VolumeCurvePoints> VolumeProfiles; + typedef VolumeProfiles::iterator VolumeProfileIterator; + typedef VolumeProfiles::const_iterator VolumeProfileConstIterator; + +public: + Element(const std::string &name) + : mName(name), + mApplicableStrategy(STRATEGY_MEDIA), + mIndexMin(0), + mIndexMax(1) + {} + ~Element() {} + + /** + * Returns identifier of this policy element + * + * @returns string representing the name of this policy element + */ + const std::string &getName() const { return mName; } + + /** + * Set the unique identifier for this policy element. + * + * @tparam Key type of the unique identifier. + * @param[in] identifier to be set. + * + * @return NO_ERROR if the identifier is valid and set correctly, error code otherwise. + */ + status_t setIdentifier(audio_stream_type_t identifier); + + /** + * @return the unique identifier of this policy element. + */ + audio_stream_type_t getIdentifier() const { return mIdentifier; } + + /** + * A Policy element may implement getter/setter function for a given property. + * Property may be routing_strategy, audio_stream_type_t, audio_usage_t, audio_source_t + * or a string. + */ + template <typename Property> + Property get() const; + + template <typename Property> + status_t set(Property property); + + status_t setVolumeProfile(Volume::device_category category, const VolumeCurvePoints &points); + + float volIndexToAmpl(Volume::device_category deviceCategory, int indexInUi); + + status_t initVolume(int indexMin, int indexMax); + +private: + /* Copy facilities are put private to disable copy. */ + Element(const Element &object); + Element &operator=(const Element &object); + + std::string mName; /**< Unique literal Identifier of a policy base element*/ + audio_stream_type_t mIdentifier; /**< Unique numerical Identifier of a policy base element*/ + + routing_strategy mApplicableStrategy; /**< Applicable strategy for this stream. */ + + /** + * Collection of volume profiles indexed by the stream type. + * Volume is the only reason why the stream profile was not removed from policy when introducing + * attributes. + */ + VolumeProfiles mVolumeProfiles; + + int mIndexMin; + + int mIndexMax; +}; + +typedef Element<audio_stream_type_t> Stream; + +} // namespace audio_policy +} // namespace android + + diff --git a/services/audiopolicy/engineconfigurable/src/Usage.cpp b/services/audiopolicy/engineconfigurable/src/Usage.cpp new file mode 100755 index 0000000..5d20828 --- /dev/null +++ b/services/audiopolicy/engineconfigurable/src/Usage.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2015 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 "APM::AudioPolicyEngine/Usage" + +#include "Usage.h" + +namespace android +{ +namespace audio_policy +{ + +status_t Element<audio_usage_t>::setIdentifier(audio_usage_t identifier) +{ + if (identifier > AUDIO_USAGE_MAX) { + return BAD_VALUE; + } + mIdentifier = identifier; + ALOGD("%s: Usage %s has identifier 0x%X", __FUNCTION__, getName().c_str(), identifier); + return NO_ERROR; +} + +template <> +status_t Element<audio_usage_t>::set<routing_strategy>(routing_strategy strategy) +{ + if (strategy >= NUM_STRATEGIES) { + return BAD_VALUE; + } + ALOGD("%s: %d for Usage %s", __FUNCTION__, strategy, getName().c_str()); + mApplicableStrategy = strategy; + return NO_ERROR; +} + +template <> +routing_strategy Element<audio_usage_t>::get<routing_strategy>() const +{ + ALOGD("%s: %d for Usage %s", __FUNCTION__, mApplicableStrategy, getName().c_str()); + return mApplicableStrategy; +} + +} // namespace audio_policy +} // namespace android + + diff --git a/services/audiopolicy/engineconfigurable/src/Usage.h b/services/audiopolicy/engineconfigurable/src/Usage.h new file mode 100755 index 0000000..d69e0e0 --- /dev/null +++ b/services/audiopolicy/engineconfigurable/src/Usage.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2015 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 "Element.h" +#include <RoutingStrategy.h> + +namespace android +{ +namespace audio_policy +{ + +/** + * @tparam routing_strategy: Applicable strategy for this usage. + */ +template <> +class Element<audio_usage_t> +{ +public: + Element(const std::string &name) + : mName(name), + mApplicableStrategy(STRATEGY_MEDIA) + {} + ~Element() {} + + /** + * Returns identifier of this policy element + * + * @returns string representing the name of this policy element + */ + const std::string &getName() const { return mName; } + + /** + * Set the unique identifier for this policy element. + * + * @tparam Key type of the unique identifier. + * @param[in] identifier to be set. + * + * @return NO_ERROR if the identifier is valid and set correctly, error code otherwise. + */ + status_t setIdentifier(audio_usage_t identifier); + + /** + * @return the unique identifier of this policy element. + */ + audio_usage_t getIdentifier() const { return mIdentifier; } + + /** + * A Policy element may implement getter/setter function for a given property. + * Property may be routing_strategy, audio_stream_type_t, audio_usage_t, audio_source_t + * or a string. + */ + template <typename Property> + Property get() const; + + template <typename Property> + status_t set(Property property); + +private: + /* Copy facilities are put private to disable copy. */ + Element(const Element &object); + Element &operator=(const Element &object); + + std::string mName; /**< Unique literal Identifier of a policy base element*/ + audio_usage_t mIdentifier; /**< Unique numerical Identifier of a policy base element*/ + routing_strategy mApplicableStrategy; /**< Applicable strategy for this usage. */ +}; + +typedef Element<audio_usage_t> Usage; + +} // namespace audio_policy +} // namespace android + + |