summaryrefslogtreecommitdiffstats
path: root/services/audiopolicy/enginedefault
diff options
context:
space:
mode:
authorFrançois Gaffie <francois.gaffie@intel.com>2015-03-24 08:41:51 +0100
committerJean-Michel Trivi <jmtrivi@google.com>2015-04-01 10:22:42 -0700
commit2110e04cdfbf9ad85ce154ce5f778ee5ccfc95eb (patch)
tree5051da296e1fbc067db7ac190334d7d98a4410eb /services/audiopolicy/enginedefault
parentdfd7409c1b708f6c429aa43722ca8493a91d8df0 (diff)
downloadframeworks_av-2110e04cdfbf9ad85ce154ce5f778ee5ccfc95eb.zip
frameworks_av-2110e04cdfbf9ad85ce154ce5f778ee5ccfc95eb.tar.gz
frameworks_av-2110e04cdfbf9ad85ce154ce5f778ee5ccfc95eb.tar.bz2
Split ManagerDefault into manager and engine
This patch defines an interface for a new component: policy engine. The APIs found under this interface are the one we may want to customize and to configure easily. This patch also split the current manager code into manager and engine to provide a default version of the policy engine. Change-Id: I97cf59760b53d248fe9efe466ae5e73bd7e5cc06 Signed-off-by: François Gaffie <francois.gaffie@intel.com>
Diffstat (limited to 'services/audiopolicy/enginedefault')
-rwxr-xr-xservices/audiopolicy/enginedefault/Android.mk48
-rwxr-xr-xservices/audiopolicy/enginedefault/include/AudioPolicyEngineInstance.h76
-rwxr-xr-xservices/audiopolicy/enginedefault/src/Engine.cpp707
-rwxr-xr-xservices/audiopolicy/enginedefault/src/Engine.h158
-rwxr-xr-xservices/audiopolicy/enginedefault/src/EngineInstance.cpp54
-rw-r--r--services/audiopolicy/enginedefault/src/Gains.cpp247
-rw-r--r--services/audiopolicy/enginedefault/src/Gains.h59
7 files changed, 1349 insertions, 0 deletions
diff --git a/services/audiopolicy/enginedefault/Android.mk b/services/audiopolicy/enginedefault/Android.mk
new file mode 100755
index 0000000..b0ae835
--- /dev/null
+++ b/services/audiopolicy/enginedefault/Android.mk
@@ -0,0 +1,48 @@
+LOCAL_PATH := $(call my-dir)
+
+# Component build
+#######################################################################
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ src/Engine.cpp \
+ src/EngineInstance.cpp \
+ src/Gains.cpp \
+
+
+audio_policy_engine_includes_common := \
+ $(LOCAL_PATH)/include \
+ $(TOPDIR)frameworks/av/services/audiopolicy/engine/interface
+
+LOCAL_CFLAGS += \
+ -Wall \
+ -Werror \
+ -Wextra \
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := \
+ $(audio_policy_engine_includes_common)
+
+LOCAL_C_INCLUDES := \
+ $(audio_policy_engine_includes_common) \
+ $(TARGET_OUT_HEADERS)/hw \
+ $(call include-path-for, frameworks-av) \
+ $(call include-path-for, audio-utils) \
+ $(call include-path-for, bionic) \
+ $(TOPDIR)frameworks/av/services/audiopolicy/common/include
+
+
+LOCAL_MODULE := libaudiopolicyenginedefault
+LOCAL_MODULE_TAGS := optional
+LOCAL_STATIC_LIBRARIES := \
+ libmedia_helper \
+ libaudiopolicycomponents
+
+LOCAL_SHARED_LIBRARIES += \
+ libcutils \
+ libutils \
+ libaudioutils \
+
+include external/stlport/libstlport.mk
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/services/audiopolicy/enginedefault/include/AudioPolicyEngineInstance.h b/services/audiopolicy/enginedefault/include/AudioPolicyEngineInstance.h
new file mode 100755
index 0000000..1e329f0
--- /dev/null
+++ b/services/audiopolicy/enginedefault/include/AudioPolicyEngineInstance.h
@@ -0,0 +1,76 @@
+/*
+ * 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
+
+class AudioPolicyManagerInterface;
+
+namespace android
+{
+namespace audio_policy
+{
+
+class Engine;
+
+class EngineInstance
+{
+protected:
+ EngineInstance();
+
+public:
+ virtual ~EngineInstance();
+
+ /**
+ * Get Audio Policy Engine instance.
+ *
+ * @return pointer to Route Manager Instance object.
+ */
+ static EngineInstance *getInstance();
+
+ /**
+ * Interface query.
+ * The first client of an interface of the policy engine will start the singleton.
+ *
+ * @tparam RequestedInterface: interface that the client is wishing to retrieve.
+ *
+ * @return interface handle.
+ */
+ template <class RequestedInterface>
+ RequestedInterface *queryInterface() const;
+
+protected:
+ /**
+ * Get Audio Policy Engine instance.
+ *
+ * @return Audio Policy Engine singleton.
+ */
+ Engine *getEngine() const;
+
+private:
+ /* Copy facilities are put private to disable copy. */
+ EngineInstance(const EngineInstance &object);
+ EngineInstance &operator=(const EngineInstance &object);
+};
+
+/**
+ * Limit template instantation to supported type interfaces.
+ * Compile time error will claim if invalid interface is requested.
+ */
+template <>
+AudioPolicyManagerInterface *EngineInstance::queryInterface() const;
+
+} // namespace audio_policy
+} // namespace android
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
new file mode 100755
index 0000000..b4d7246
--- /dev/null
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -0,0 +1,707 @@
+/*
+ * 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 "Gains.h"
+#include <AudioPolicyManagerObserver.h>
+#include <AudioPort.h>
+#include <IOProfile.h>
+#include <policy.h>
+#include <utils/String8.h>
+#include <utils/Log.h>
+
+namespace android
+{
+namespace audio_policy
+{
+
+Engine::Engine()
+ : mManagerInterface(this),
+ mPhoneState(AUDIO_MODE_NORMAL),
+ mApmObserver(NULL)
+{
+ for (int i = 0; i < AUDIO_POLICY_FORCE_USE_CNT; i++) {
+ mForceUse[i] = AUDIO_POLICY_FORCE_NONE;
+ }
+}
+
+Engine::~Engine()
+{
+}
+
+void Engine::setObserver(AudioPolicyManagerObserver *observer)
+{
+ ALOG_ASSERT(observer != NULL, "Invalid Audio Policy Manager observer");
+ mApmObserver = observer;
+}
+
+status_t Engine::initCheck()
+{
+ return (mApmObserver != NULL) ? NO_ERROR : NO_INIT;
+}
+
+float Engine::volIndexToAmpl(Volume::device_category category, audio_stream_type_t streamType,
+ int indexInUi)
+{
+ const StreamDescriptor &streamDesc = mApmObserver->getStreamDescriptors().valueAt(streamType);
+ return Gains::volIndexToAmpl(category, streamDesc, indexInUi);
+}
+
+status_t Engine::initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax)
+{
+ ALOGV("initStreamVolume() stream %d, min %d, max %d", stream , indexMin, indexMax);
+ if (indexMin < 0 || indexMin >= indexMax) {
+ ALOGW("initStreamVolume() invalid index limits for stream %d, min %d, max %d",
+ stream , indexMin, indexMax);
+ return BAD_VALUE;
+ }
+ mApmObserver->getStreamDescriptors().setVolumeIndexMin(stream, indexMin);
+ mApmObserver->getStreamDescriptors().setVolumeIndexMax(stream, indexMax);
+ return NO_ERROR;
+}
+
+void Engine::initializeVolumeCurves(bool isSpeakerDrcEnabled)
+{
+ StreamDescriptorCollection &streams = mApmObserver->getStreamDescriptors();
+
+ for (int i = 0; i < AUDIO_STREAM_CNT; i++) {
+ for (int j = 0; j < Volume::DEVICE_CATEGORY_CNT; j++) {
+ streams.setVolumeCurvePoint(static_cast<audio_stream_type_t>(i),
+ static_cast<Volume::device_category>(j),
+ Gains::sVolumeProfiles[i][j]);
+ }
+ }
+
+ // Check availability of DRC on speaker path: if available, override some of the speaker curves
+ if (isSpeakerDrcEnabled) {
+ streams.setVolumeCurvePoint(AUDIO_STREAM_SYSTEM, Volume::DEVICE_CATEGORY_SPEAKER,
+ Gains::sDefaultSystemVolumeCurveDrc);
+ streams.setVolumeCurvePoint(AUDIO_STREAM_RING, Volume::DEVICE_CATEGORY_SPEAKER,
+ Gains::sSpeakerSonificationVolumeCurveDrc);
+ streams.setVolumeCurvePoint(AUDIO_STREAM_ALARM, Volume::DEVICE_CATEGORY_SPEAKER,
+ Gains::sSpeakerSonificationVolumeCurveDrc);
+ streams.setVolumeCurvePoint(AUDIO_STREAM_NOTIFICATION, Volume::DEVICE_CATEGORY_SPEAKER,
+ Gains::sSpeakerSonificationVolumeCurveDrc);
+ streams.setVolumeCurvePoint(AUDIO_STREAM_MUSIC, Volume::DEVICE_CATEGORY_SPEAKER,
+ Gains::sSpeakerMediaVolumeCurveDrc);
+ streams.setVolumeCurvePoint(AUDIO_STREAM_ACCESSIBILITY, Volume::DEVICE_CATEGORY_SPEAKER,
+ Gains::sSpeakerMediaVolumeCurveDrc);
+ }
+}
+
+
+status_t Engine::setPhoneState(audio_mode_t state)
+{
+ ALOGV("setPhoneState() state %d", state);
+
+ if (state < 0 || state >= AUDIO_MODE_CNT) {
+ ALOGW("setPhoneState() invalid state %d", state);
+ return BAD_VALUE;
+ }
+
+ if (state == mPhoneState ) {
+ ALOGW("setPhoneState() setting same state %d", state);
+ return BAD_VALUE;
+ }
+
+ // store previous phone state for management of sonification strategy below
+ int oldState = mPhoneState;
+ mPhoneState = state;
+ StreamDescriptorCollection &streams = mApmObserver->getStreamDescriptors();
+ // are we entering or starting a call
+ if (!is_state_in_call(oldState) && is_state_in_call(state)) {
+ ALOGV(" Entering call in setPhoneState()");
+ for (int j = 0; j < Volume::DEVICE_CATEGORY_CNT; j++) {
+ streams.setVolumeCurvePoint(AUDIO_STREAM_DTMF, static_cast<Volume::device_category>(j),
+ Gains::sVolumeProfiles[AUDIO_STREAM_VOICE_CALL][j]);
+ }
+ } else if (is_state_in_call(oldState) && !is_state_in_call(state)) {
+ ALOGV(" Exiting call in setPhoneState()");
+ for (int j = 0; j < Volume::DEVICE_CATEGORY_CNT; j++) {
+ streams.setVolumeCurvePoint(AUDIO_STREAM_DTMF, static_cast<Volume::device_category>(j),
+ Gains::sVolumeProfiles[AUDIO_STREAM_DTMF][j]);
+ }
+ }
+ return NO_ERROR;
+}
+
+status_t Engine::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)
+{
+ switch(usage) {
+ case AUDIO_POLICY_FORCE_FOR_COMMUNICATION:
+ if (config != AUDIO_POLICY_FORCE_SPEAKER && config != AUDIO_POLICY_FORCE_BT_SCO &&
+ config != AUDIO_POLICY_FORCE_NONE) {
+ ALOGW("setForceUse() invalid config %d for FOR_COMMUNICATION", config);
+ return BAD_VALUE;
+ }
+ mForceUse[usage] = config;
+ break;
+ case AUDIO_POLICY_FORCE_FOR_MEDIA:
+ if (config != AUDIO_POLICY_FORCE_HEADPHONES && config != AUDIO_POLICY_FORCE_BT_A2DP &&
+ config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY &&
+ config != AUDIO_POLICY_FORCE_ANALOG_DOCK &&
+ config != AUDIO_POLICY_FORCE_DIGITAL_DOCK && config != AUDIO_POLICY_FORCE_NONE &&
+ config != AUDIO_POLICY_FORCE_NO_BT_A2DP && config != AUDIO_POLICY_FORCE_SPEAKER ) {
+ ALOGW("setForceUse() invalid config %d for FOR_MEDIA", config);
+ return BAD_VALUE;
+ }
+ mForceUse[usage] = config;
+ break;
+ case AUDIO_POLICY_FORCE_FOR_RECORD:
+ if (config != AUDIO_POLICY_FORCE_BT_SCO && config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY &&
+ config != AUDIO_POLICY_FORCE_NONE) {
+ ALOGW("setForceUse() invalid config %d for FOR_RECORD", config);
+ return BAD_VALUE;
+ }
+ mForceUse[usage] = config;
+ break;
+ case AUDIO_POLICY_FORCE_FOR_DOCK:
+ if (config != AUDIO_POLICY_FORCE_NONE && config != AUDIO_POLICY_FORCE_BT_CAR_DOCK &&
+ config != AUDIO_POLICY_FORCE_BT_DESK_DOCK &&
+ config != AUDIO_POLICY_FORCE_WIRED_ACCESSORY &&
+ config != AUDIO_POLICY_FORCE_ANALOG_DOCK &&
+ config != AUDIO_POLICY_FORCE_DIGITAL_DOCK) {
+ ALOGW("setForceUse() invalid config %d for FOR_DOCK", config);
+ }
+ mForceUse[usage] = config;
+ break;
+ case AUDIO_POLICY_FORCE_FOR_SYSTEM:
+ if (config != AUDIO_POLICY_FORCE_NONE &&
+ config != AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) {
+ ALOGW("setForceUse() invalid config %d for FOR_SYSTEM", config);
+ }
+ mForceUse[usage] = config;
+ break;
+ case AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO:
+ if (config != AUDIO_POLICY_FORCE_NONE &&
+ config != AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED) {
+ ALOGW("setForceUse() invalid config %d forHDMI_SYSTEM_AUDIO", config);
+ }
+ mForceUse[usage] = config;
+ break;
+ default:
+ ALOGW("setForceUse() invalid usage %d", usage);
+ break;
+ }
+ return NO_ERROR;
+}
+
+routing_strategy Engine::getStrategyForStream(audio_stream_type_t stream)
+{
+ // stream to strategy mapping
+ switch (stream) {
+ case AUDIO_STREAM_VOICE_CALL:
+ case AUDIO_STREAM_BLUETOOTH_SCO:
+ return STRATEGY_PHONE;
+ case AUDIO_STREAM_RING:
+ case AUDIO_STREAM_ALARM:
+ return STRATEGY_SONIFICATION;
+ case AUDIO_STREAM_NOTIFICATION:
+ return STRATEGY_SONIFICATION_RESPECTFUL;
+ case AUDIO_STREAM_DTMF:
+ return STRATEGY_DTMF;
+ default:
+ ALOGE("unknown stream type %d", stream);
+ case AUDIO_STREAM_SYSTEM:
+ // NOTE: SYSTEM stream uses MEDIA strategy because muting music and switching outputs
+ // while key clicks are played produces a poor result
+ case AUDIO_STREAM_MUSIC:
+ return STRATEGY_MEDIA;
+ case AUDIO_STREAM_ENFORCED_AUDIBLE:
+ return STRATEGY_ENFORCED_AUDIBLE;
+ case AUDIO_STREAM_TTS:
+ return STRATEGY_TRANSMITTED_THROUGH_SPEAKER;
+ case AUDIO_STREAM_ACCESSIBILITY:
+ return STRATEGY_ACCESSIBILITY;
+ case AUDIO_STREAM_REROUTING:
+ return STRATEGY_REROUTING;
+ }
+}
+
+routing_strategy Engine::getStrategyForUsage(audio_usage_t usage)
+{
+ const AudioOutputCollection &outputs = mApmObserver->getOutputs();
+
+ // usage to strategy mapping
+ switch (usage) {
+ case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
+ if (outputs.isStreamActive(AUDIO_STREAM_RING) ||
+ outputs.isStreamActive(AUDIO_STREAM_ALARM)) {
+ return STRATEGY_SONIFICATION;
+ }
+ if (isInCall()) {
+ return STRATEGY_PHONE;
+ }
+ return STRATEGY_ACCESSIBILITY;
+
+ case AUDIO_USAGE_MEDIA:
+ case AUDIO_USAGE_GAME:
+ case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
+ case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
+ return STRATEGY_MEDIA;
+
+ case AUDIO_USAGE_VOICE_COMMUNICATION:
+ return STRATEGY_PHONE;
+
+ case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
+ return STRATEGY_DTMF;
+
+ case AUDIO_USAGE_ALARM:
+ case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
+ return STRATEGY_SONIFICATION;
+
+ case AUDIO_USAGE_NOTIFICATION:
+ case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
+ case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
+ case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
+ case AUDIO_USAGE_NOTIFICATION_EVENT:
+ return STRATEGY_SONIFICATION_RESPECTFUL;
+
+ case AUDIO_USAGE_UNKNOWN:
+ default:
+ return STRATEGY_MEDIA;
+ }
+}
+
+audio_devices_t Engine::getDeviceForStrategy(routing_strategy strategy) const
+{
+ const DeviceVector &availableOutputDevices = mApmObserver->getAvailableOutputDevices();
+ const DeviceVector &availableInputDevices = mApmObserver->getAvailableInputDevices();
+
+ const AudioOutputCollection &outputs = mApmObserver->getOutputs();
+
+ uint32_t device = AUDIO_DEVICE_NONE;
+ uint32_t availableOutputDevicesType = availableOutputDevices.types();
+
+ switch (strategy) {
+
+ case STRATEGY_TRANSMITTED_THROUGH_SPEAKER:
+ device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
+ if (!device) {
+ ALOGE("getDeviceForStrategy() no device found for "\
+ "STRATEGY_TRANSMITTED_THROUGH_SPEAKER");
+ }
+ break;
+
+ case STRATEGY_SONIFICATION_RESPECTFUL:
+ if (isInCall()) {
+ device = getDeviceForStrategy(STRATEGY_SONIFICATION);
+ } else if (outputs.isStreamActiveRemotely(AUDIO_STREAM_MUSIC,
+ SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
+ // 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
+ device = getDeviceForStrategy(STRATEGY_SONIFICATION);
+ //user "safe" speaker if available instead of normal speaker to avoid triggering
+ //other acoustic safety mechanisms for notification
+ if (device == AUDIO_DEVICE_OUT_SPEAKER && (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE))
+ device = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
+ } else if (outputs.isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
+ // while media is playing (or has recently played), use the same device
+ device = getDeviceForStrategy(STRATEGY_MEDIA);
+ } else {
+ // when media is not playing anymore, fall back on the sonification behavior
+ device = getDeviceForStrategy(STRATEGY_SONIFICATION);
+ //user "safe" speaker if available instead of normal speaker to avoid triggering
+ //other acoustic safety mechanisms for notification
+ if (device == AUDIO_DEVICE_OUT_SPEAKER && (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE))
+ device = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
+ }
+ break;
+
+ case STRATEGY_DTMF:
+ if (!isInCall()) {
+ // when off call, DTMF strategy follows the same rules as MEDIA strategy
+ device = getDeviceForStrategy(STRATEGY_MEDIA);
+ break;
+ }
+ // when in call, DTMF and PHONE strategies follow the same rules
+ // FALL THROUGH
+
+ case STRATEGY_PHONE:
+ // Force use of only devices on primary output if:
+ // - in call AND
+ // - cannot route from voice call RX OR
+ // - audio HAL version is < 3.0 and TX device is on the primary HW module
+ if (getPhoneState() == AUDIO_MODE_IN_CALL) {
+ audio_devices_t txDevice = getDeviceForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION);
+ sp<AudioOutputDescriptor> primaryOutput = outputs.getPrimaryOutput();
+ audio_devices_t availPrimaryInputDevices =
+ availableInputDevices.getDevicesFromHwModule(primaryOutput->getModuleHandle());
+ audio_devices_t availPrimaryOutputDevices =
+ primaryOutput->supportedDevices() & availableOutputDevices.types();
+
+ if (((availableInputDevices.types() &
+ AUDIO_DEVICE_IN_TELEPHONY_RX & ~AUDIO_DEVICE_BIT_IN) == 0) ||
+ (((txDevice & availPrimaryInputDevices & ~AUDIO_DEVICE_BIT_IN) != 0) &&
+ (primaryOutput->getAudioPort()->mModule->mHalVersion <
+ AUDIO_DEVICE_API_VERSION_3_0))) {
+ availableOutputDevicesType = availPrimaryOutputDevices;
+ }
+ }
+ // for phone strategy, we first consider the forced use and then the available devices by order
+ // of priority
+ switch (mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]) {
+ case AUDIO_POLICY_FORCE_BT_SCO:
+ if (!isInCall() || strategy != STRATEGY_DTMF) {
+ device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
+ if (device) break;
+ }
+ device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
+ if (device) break;
+ device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_SCO;
+ if (device) break;
+ // if SCO device is requested but no SCO device is available, fall back to default case
+ // FALL THROUGH
+
+ default: // FORCE_NONE
+ // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
+ if (!isInCall() &&
+ (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
+ (outputs.getA2dpOutput() != 0)) {
+ device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
+ if (device) break;
+ device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
+ if (device) break;
+ }
+ device = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
+ if (device) break;
+ device = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET;
+ if (device) break;
+ device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE;
+ if (device) break;
+ if (!isInCall()) {
+ device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY;
+ if (device) break;
+ device = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
+ if (device) break;
+ device = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
+ if (device) break;
+ device = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
+ if (device) break;
+ }
+ device = availableOutputDevicesType & AUDIO_DEVICE_OUT_EARPIECE;
+ if (device) break;
+ device = mApmObserver->getDefaultOutputDevice()->type();
+ if (device == AUDIO_DEVICE_NONE) {
+ ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE");
+ }
+ break;
+
+ case AUDIO_POLICY_FORCE_SPEAKER:
+ // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to
+ // A2DP speaker when forcing to speaker output
+ if (!isInCall() &&
+ (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
+ (outputs.getA2dpOutput() != 0)) {
+ device = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
+ if (device) break;
+ }
+ if (!isInCall()) {
+ device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY;
+ if (device) break;
+ device = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE;
+ if (device) break;
+ device = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
+ if (device) break;
+ device = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
+ if (device) break;
+ device = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
+ if (device) break;
+ }
+ device = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE;
+ if (device) break;
+ device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
+ if (device) break;
+ device = mApmObserver->getDefaultOutputDevice()->type();
+ if (device == AUDIO_DEVICE_NONE) {
+ ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE, FORCE_SPEAKER");
+ }
+ break;
+ }
+ break;
+
+ case STRATEGY_SONIFICATION:
+
+ // If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by
+ // handleIncallSonification().
+ if (isInCall()) {
+ device = getDeviceForStrategy(STRATEGY_PHONE);
+ break;
+ }
+ // FALL THROUGH
+
+ case STRATEGY_ENFORCED_AUDIBLE:
+ // strategy STRATEGY_ENFORCED_AUDIBLE uses same routing policy as STRATEGY_SONIFICATION
+ // except:
+ // - when in call where it doesn't default to STRATEGY_PHONE behavior
+ // - in countries where not enforced in which case it follows STRATEGY_MEDIA
+
+ if ((strategy == STRATEGY_SONIFICATION) ||
+ (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)) {
+ device = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
+ if (device == AUDIO_DEVICE_NONE) {
+ ALOGE("getDeviceForStrategy() speaker device not found for STRATEGY_SONIFICATION");
+ }
+ }
+ // The second device used for sonification is the same as the device used by media strategy
+ // FALL THROUGH
+
+ // FIXME: STRATEGY_ACCESSIBILITY and STRATEGY_REROUTING follow STRATEGY_MEDIA for now
+ case STRATEGY_ACCESSIBILITY:
+ if (strategy == STRATEGY_ACCESSIBILITY) {
+ // do not route accessibility prompts to a digital output currently configured with a
+ // compressed format as they would likely not be mixed and dropped.
+ for (size_t i = 0; i < outputs.size(); i++) {
+ sp<AudioOutputDescriptor> desc = outputs.valueAt(i);
+ audio_devices_t devices = desc->device() &
+ (AUDIO_DEVICE_OUT_HDMI | AUDIO_DEVICE_OUT_SPDIF | AUDIO_DEVICE_OUT_HDMI_ARC);
+ if (desc->isActive() && !audio_is_linear_pcm(desc->mFormat) &&
+ devices != AUDIO_DEVICE_NONE) {
+ availableOutputDevicesType = availableOutputDevices.types() & ~devices;
+ }
+ }
+ }
+ // FALL THROUGH
+
+ case STRATEGY_REROUTING:
+ case STRATEGY_MEDIA: {
+ uint32_t device2 = AUDIO_DEVICE_NONE;
+ if (strategy != STRATEGY_SONIFICATION) {
+ // no sonification on remote submix (e.g. WFD)
+ if (availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, String8("0")) != 0) {
+ device2 = availableOutputDevices.types() & AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+ }
+ }
+ if ((device2 == AUDIO_DEVICE_NONE) &&
+ (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
+ (outputs.getA2dpOutput() != 0)) {
+ device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
+ if (device2 == AUDIO_DEVICE_NONE) {
+ device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
+ }
+ if (device2 == AUDIO_DEVICE_NONE) {
+ device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
+ }
+ }
+ if ((device2 == AUDIO_DEVICE_NONE) &&
+ (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] == AUDIO_POLICY_FORCE_SPEAKER)) {
+ device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
+ }
+ if (device2 == AUDIO_DEVICE_NONE) {
+ device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
+ }
+ if ((device2 == AUDIO_DEVICE_NONE)) {
+ device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE;
+ }
+ if (device2 == AUDIO_DEVICE_NONE) {
+ device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET;
+ }
+ if (device2 == AUDIO_DEVICE_NONE) {
+ device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY;
+ }
+ if (device2 == AUDIO_DEVICE_NONE) {
+ device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE;
+ }
+ if (device2 == AUDIO_DEVICE_NONE) {
+ device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
+ }
+ if ((device2 == AUDIO_DEVICE_NONE) && (strategy != STRATEGY_SONIFICATION)) {
+ // no sonification on aux digital (e.g. HDMI)
+ device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
+ }
+ if ((device2 == AUDIO_DEVICE_NONE) &&
+ (mForceUse[AUDIO_POLICY_FORCE_FOR_DOCK] == AUDIO_POLICY_FORCE_ANALOG_DOCK)) {
+ device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
+ }
+ if (device2 == AUDIO_DEVICE_NONE) {
+ device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
+ }
+ int device3 = AUDIO_DEVICE_NONE;
+ if (strategy == STRATEGY_MEDIA) {
+ // ARC, SPDIF and AUX_LINE can co-exist with others.
+ device3 = availableOutputDevicesType & AUDIO_DEVICE_OUT_HDMI_ARC;
+ device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPDIF);
+ device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_LINE);
+ }
+
+ device2 |= device3;
+ // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION or
+ // STRATEGY_ENFORCED_AUDIBLE, AUDIO_DEVICE_NONE otherwise
+ device |= device2;
+
+ // If hdmi system audio mode is on, remove speaker out of output list.
+ if ((strategy == STRATEGY_MEDIA) &&
+ (mForceUse[AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] ==
+ AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)) {
+ device &= ~AUDIO_DEVICE_OUT_SPEAKER;
+ }
+
+ if (device) break;
+ device = mApmObserver->getDefaultOutputDevice()->type();
+ if (device == AUDIO_DEVICE_NONE) {
+ ALOGE("getDeviceForStrategy() no device found for STRATEGY_MEDIA");
+ }
+ } break;
+
+ default:
+ ALOGW("getDeviceForStrategy() unknown strategy: %d", strategy);
+ break;
+ }
+
+ ALOGVV("getDeviceForStrategy() strategy %d, device %x", strategy, device);
+ return device;
+}
+
+
+audio_devices_t Engine::getDeviceForInputSource(audio_source_t inputSource) const
+{
+ const DeviceVector &availableOutputDevices = mApmObserver->getAvailableOutputDevices();
+ const DeviceVector &availableInputDevices = mApmObserver->getAvailableInputDevices();
+ const AudioOutputCollection &outputs = mApmObserver->getOutputs();
+ audio_devices_t availableDeviceTypes = availableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN;
+
+ uint32_t device = AUDIO_DEVICE_NONE;
+
+ switch (inputSource) {
+ case AUDIO_SOURCE_VOICE_UPLINK:
+ if (availableDeviceTypes & AUDIO_DEVICE_IN_VOICE_CALL) {
+ device = AUDIO_DEVICE_IN_VOICE_CALL;
+ break;
+ }
+ break;
+
+ case AUDIO_SOURCE_DEFAULT:
+ case AUDIO_SOURCE_MIC:
+ if (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) {
+ device = AUDIO_DEVICE_IN_BLUETOOTH_A2DP;
+ } else if ((mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] == AUDIO_POLICY_FORCE_BT_SCO) &&
+ (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET)) {
+ device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+ } else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+ device = AUDIO_DEVICE_IN_WIRED_HEADSET;
+ } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
+ device = AUDIO_DEVICE_IN_USB_DEVICE;
+ } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+ device = AUDIO_DEVICE_IN_BUILTIN_MIC;
+ }
+ break;
+
+ case AUDIO_SOURCE_VOICE_COMMUNICATION:
+ // Allow only use of devices on primary input if in call and HAL does not support routing
+ // to voice call path.
+ if ((getPhoneState() == AUDIO_MODE_IN_CALL) &&
+ (availableOutputDevices.types() & AUDIO_DEVICE_OUT_TELEPHONY_TX) == 0) {
+ sp<AudioOutputDescriptor> primaryOutput = outputs.getPrimaryOutput();
+ availableDeviceTypes =
+ availableInputDevices.getDevicesFromHwModule(primaryOutput->getModuleHandle())
+ & ~AUDIO_DEVICE_BIT_IN;
+ }
+
+ switch (mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]) {
+ case AUDIO_POLICY_FORCE_BT_SCO:
+ // if SCO device is requested but no SCO device is available, fall back to default case
+ if (availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
+ device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+ break;
+ }
+ // FALL THROUGH
+
+ default: // FORCE_NONE
+ if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+ device = AUDIO_DEVICE_IN_WIRED_HEADSET;
+ } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
+ device = AUDIO_DEVICE_IN_USB_DEVICE;
+ } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+ device = AUDIO_DEVICE_IN_BUILTIN_MIC;
+ }
+ break;
+
+ case AUDIO_POLICY_FORCE_SPEAKER:
+ if (availableDeviceTypes & AUDIO_DEVICE_IN_BACK_MIC) {
+ device = AUDIO_DEVICE_IN_BACK_MIC;
+ } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+ device = AUDIO_DEVICE_IN_BUILTIN_MIC;
+ }
+ break;
+ }
+ break;
+
+ case AUDIO_SOURCE_VOICE_RECOGNITION:
+ case AUDIO_SOURCE_HOTWORD:
+ if (mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] == AUDIO_POLICY_FORCE_BT_SCO &&
+ availableDeviceTypes & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
+ device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+ } else if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+ device = AUDIO_DEVICE_IN_WIRED_HEADSET;
+ } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
+ device = AUDIO_DEVICE_IN_USB_DEVICE;
+ } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+ device = AUDIO_DEVICE_IN_BUILTIN_MIC;
+ }
+ break;
+ case AUDIO_SOURCE_CAMCORDER:
+ if (availableDeviceTypes & AUDIO_DEVICE_IN_BACK_MIC) {
+ device = AUDIO_DEVICE_IN_BACK_MIC;
+ } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+ device = AUDIO_DEVICE_IN_BUILTIN_MIC;
+ }
+ break;
+ case AUDIO_SOURCE_VOICE_DOWNLINK:
+ case AUDIO_SOURCE_VOICE_CALL:
+ if (availableDeviceTypes & AUDIO_DEVICE_IN_VOICE_CALL) {
+ device = AUDIO_DEVICE_IN_VOICE_CALL;
+ }
+ break;
+ case AUDIO_SOURCE_REMOTE_SUBMIX:
+ if (availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
+ device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
+ }
+ break;
+ case AUDIO_SOURCE_FM_TUNER:
+ if (availableDeviceTypes & AUDIO_DEVICE_IN_FM_TUNER) {
+ device = AUDIO_DEVICE_IN_FM_TUNER;
+ }
+ break;
+ default:
+ ALOGW("getDeviceForInputSource() invalid input source %d", inputSource);
+ break;
+ }
+ ALOGV("getDeviceForInputSource()input source %d, device %08x", inputSource, device);
+ return device;
+}
+
+template <>
+AudioPolicyManagerInterface *Engine::queryInterface()
+{
+ return &mManagerInterface;
+}
+
+} // namespace audio_policy
+} // namespace android
+
+
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
new file mode 100755
index 0000000..f44556c
--- /dev/null
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -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.
+ */
+
+#pragma once
+
+
+#include "AudioPolicyManagerInterface.h"
+#include "Gains.h"
+#include <AudioGain.h>
+#include <policy.h>
+
+namespace android
+{
+
+class AudioPolicyManagerObserver;
+
+namespace audio_policy
+{
+
+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 void setObserver(AudioPolicyManagerObserver *observer)
+ {
+ mPolicyEngine->setObserver(observer);
+ }
+ virtual status_t initCheck()
+ {
+ return mPolicyEngine->initCheck();
+ }
+ virtual audio_devices_t getDeviceForInputSource(audio_source_t inputSource) const
+ {
+ return mPolicyEngine->getDeviceForInputSource(inputSource);
+ }
+ virtual audio_devices_t getDeviceForStrategy(routing_strategy strategy) const
+ {
+ return mPolicyEngine->getDeviceForStrategy(strategy);
+ }
+ virtual routing_strategy getStrategyForStream(audio_stream_type_t stream)
+ {
+ return mPolicyEngine->getStrategyForStream(stream);
+ }
+ virtual routing_strategy getStrategyForUsage(audio_usage_t usage)
+ {
+ return mPolicyEngine->getStrategyForUsage(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 status_t setDeviceConnectionState(const sp<DeviceDescriptor> /*devDesc*/,
+ audio_policy_dev_state_t /*state*/)
+ {
+ return NO_ERROR;
+ }
+ virtual status_t initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax)
+ {
+ return mPolicyEngine->initStreamVolume(stream, indexMin, indexMax);
+ }
+ virtual void initializeVolumeCurves(bool isSpeakerDrcEnabled)
+ {
+ return mPolicyEngine->initializeVolumeCurves(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;
+
+private:
+ /* Copy facilities are put private to disable copy. */
+ Engine(const Engine &object);
+ Engine &operator=(const Engine &object);
+
+ void setObserver(AudioPolicyManagerObserver *observer);
+
+ status_t initCheck();
+
+ inline bool isInCall() const
+ {
+ return is_state_in_call(mPhoneState);
+ }
+
+ status_t setPhoneState(audio_mode_t mode);
+ audio_mode_t getPhoneState() const
+ {
+ return mPhoneState;
+ }
+ 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
+ {
+ return mForceUse[usage];
+ }
+ status_t setDefaultDevice(audio_devices_t device);
+
+ routing_strategy getStrategyForStream(audio_stream_type_t stream);
+ routing_strategy getStrategyForUsage(audio_usage_t usage);
+ audio_devices_t getDeviceForStrategy(routing_strategy strategy) const;
+ audio_devices_t getDeviceForInputSource(audio_source_t inputSource) const;
+
+ 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);
+ void initializeVolumeCurves(bool isSpeakerDrcEnabled);
+
+ audio_mode_t mPhoneState; /**< current phone state. */
+
+ /** current forced use configuration. */
+ audio_policy_forced_cfg_t mForceUse[AUDIO_POLICY_FORCE_USE_CNT];
+
+ AudioPolicyManagerObserver *mApmObserver;
+};
+} // namespace audio_policy
+} // namespace android
+
diff --git a/services/audiopolicy/enginedefault/src/EngineInstance.cpp b/services/audiopolicy/enginedefault/src/EngineInstance.cpp
new file mode 100755
index 0000000..17e9832
--- /dev/null
+++ b/services/audiopolicy/enginedefault/src/EngineInstance.cpp
@@ -0,0 +1,54 @@
+/*
+ * 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 "AudioPolicyEngineInstance.h"
+#include "Engine.h"
+
+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>();
+}
+
+} // namespace audio_policy
+} // namespace android
+
diff --git a/services/audiopolicy/enginedefault/src/Gains.cpp b/services/audiopolicy/enginedefault/src/Gains.cpp
new file mode 100644
index 0000000..a684fdd
--- /dev/null
+++ b/services/audiopolicy/enginedefault/src/Gains.cpp
@@ -0,0 +1,247 @@
+/*
+ * 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::Gains"
+//#define LOG_NDEBUG 0
+
+//#define VERY_VERBOSE_LOGGING
+#ifdef VERY_VERBOSE_LOGGING
+#define ALOGVV ALOGV
+#else
+#define ALOGVV(a...) do { } while(0)
+#endif
+
+#include "Gains.h"
+#include <Volume.h>
+#include <math.h>
+#include <utils/String8.h>
+
+namespace android {
+
+// Enginedefault
+const VolumeCurvePoint
+Gains::sDefaultVolumeCurve[Volume::VOLCNT] = {
+ {1, -49.5f}, {33, -33.5f}, {66, -17.0f}, {100, 0.0f}
+};
+
+
+const VolumeCurvePoint
+Gains::sDefaultMediaVolumeCurve[Volume::VOLCNT] = {
+ {1, -58.0f}, {20, -40.0f}, {60, -17.0f}, {100, 0.0f}
+};
+
+const VolumeCurvePoint
+Gains::sExtMediaSystemVolumeCurve[Volume::VOLCNT] = {
+ {1, -58.0f}, {20, -40.0f}, {60, -21.0f}, {100, -10.0f}
+};
+
+const VolumeCurvePoint
+Gains::sSpeakerMediaVolumeCurve[Volume::VOLCNT] = {
+ {1, -56.0f}, {20, -34.0f}, {60, -11.0f}, {100, 0.0f}
+};
+
+const VolumeCurvePoint
+Gains::sSpeakerMediaVolumeCurveDrc[Volume::VOLCNT] = {
+ {1, -55.0f}, {20, -43.0f}, {86, -12.0f}, {100, 0.0f}
+};
+
+const VolumeCurvePoint
+Gains::sSpeakerSonificationVolumeCurve[Volume::VOLCNT] = {
+ {1, -29.7f}, {33, -20.1f}, {66, -10.2f}, {100, 0.0f}
+};
+
+const VolumeCurvePoint
+Gains::sSpeakerSonificationVolumeCurveDrc[Volume::VOLCNT] = {
+ {1, -35.7f}, {33, -26.1f}, {66, -13.2f}, {100, 0.0f}
+};
+
+// AUDIO_STREAM_SYSTEM, AUDIO_STREAM_ENFORCED_AUDIBLE and AUDIO_STREAM_DTMF volume tracks
+// AUDIO_STREAM_RING on phones and AUDIO_STREAM_MUSIC on tablets.
+// AUDIO_STREAM_DTMF tracks AUDIO_STREAM_VOICE_CALL while in call (See AudioService.java).
+// The range is constrained between -24dB and -6dB over speaker and -30dB and -18dB over headset.
+
+const VolumeCurvePoint
+Gains::sDefaultSystemVolumeCurve[Volume::VOLCNT] = {
+ {1, -24.0f}, {33, -18.0f}, {66, -12.0f}, {100, -6.0f}
+};
+
+const VolumeCurvePoint
+Gains::sDefaultSystemVolumeCurveDrc[Volume::VOLCNT] = {
+ {1, -34.0f}, {33, -24.0f}, {66, -15.0f}, {100, -6.0f}
+};
+
+const VolumeCurvePoint
+Gains::sHeadsetSystemVolumeCurve[Volume::VOLCNT] = {
+ {1, -30.0f}, {33, -26.0f}, {66, -22.0f}, {100, -18.0f}
+};
+
+const VolumeCurvePoint
+Gains::sDefaultVoiceVolumeCurve[Volume::VOLCNT] = {
+ {0, -42.0f}, {33, -28.0f}, {66, -14.0f}, {100, 0.0f}
+};
+
+const VolumeCurvePoint
+Gains::sSpeakerVoiceVolumeCurve[Volume::VOLCNT] = {
+ {0, -24.0f}, {33, -16.0f}, {66, -8.0f}, {100, 0.0f}
+};
+
+const VolumeCurvePoint
+Gains::sLinearVolumeCurve[Volume::VOLCNT] = {
+ {0, -96.0f}, {33, -68.0f}, {66, -34.0f}, {100, 0.0f}
+};
+
+const VolumeCurvePoint
+Gains::sSilentVolumeCurve[Volume::VOLCNT] = {
+ {0, -96.0f}, {1, -96.0f}, {2, -96.0f}, {100, -96.0f}
+};
+
+const VolumeCurvePoint
+Gains::sFullScaleVolumeCurve[Volume::VOLCNT] = {
+ {0, 0.0f}, {1, 0.0f}, {2, 0.0f}, {100, 0.0f}
+};
+
+const VolumeCurvePoint *Gains::sVolumeProfiles[AUDIO_STREAM_CNT]
+ [Volume::DEVICE_CATEGORY_CNT] = {
+ { // AUDIO_STREAM_VOICE_CALL
+ Gains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET
+ Gains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+ Gains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+ Gains::sDefaultMediaVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
+ },
+ { // AUDIO_STREAM_SYSTEM
+ Gains::sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET
+ Gains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+ Gains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+ Gains::sExtMediaSystemVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
+ },
+ { // AUDIO_STREAM_RING
+ Gains::sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
+ Gains::sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+ Gains::sDefaultVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+ Gains::sExtMediaSystemVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
+ },
+ { // AUDIO_STREAM_MUSIC
+ Gains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET
+ Gains::sSpeakerMediaVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+ Gains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+ Gains::sDefaultMediaVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
+ },
+ { // AUDIO_STREAM_ALARM
+ Gains::sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
+ Gains::sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+ Gains::sDefaultVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+ Gains::sExtMediaSystemVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
+ },
+ { // AUDIO_STREAM_NOTIFICATION
+ Gains::sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
+ Gains::sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+ Gains::sDefaultVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+ Gains::sExtMediaSystemVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
+ },
+ { // AUDIO_STREAM_BLUETOOTH_SCO
+ Gains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET
+ Gains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+ Gains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+ Gains::sDefaultMediaVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
+ },
+ { // AUDIO_STREAM_ENFORCED_AUDIBLE
+ Gains::sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET
+ Gains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+ Gains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+ Gains::sExtMediaSystemVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
+ },
+ { // AUDIO_STREAM_DTMF
+ Gains::sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET
+ Gains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+ Gains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+ Gains::sExtMediaSystemVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
+ },
+ { // AUDIO_STREAM_TTS
+ // "Transmitted Through Speaker": always silent except on DEVICE_CATEGORY_SPEAKER
+ Gains::sSilentVolumeCurve, // DEVICE_CATEGORY_HEADSET
+ Gains::sLinearVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+ Gains::sSilentVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+ Gains::sSilentVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
+ },
+ { // AUDIO_STREAM_ACCESSIBILITY
+ Gains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET
+ Gains::sSpeakerMediaVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+ Gains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+ Gains::sDefaultMediaVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
+ },
+ { // AUDIO_STREAM_REROUTING
+ Gains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_HEADSET
+ Gains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+ Gains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+ Gains::sFullScaleVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
+ },
+ { // AUDIO_STREAM_PATCH
+ Gains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_HEADSET
+ Gains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+ Gains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+ Gains::sFullScaleVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
+ },
+};
+
+//static
+float Gains::volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc,
+ int indexInUi)
+{
+ Volume::device_category deviceCategory = Volume::getDeviceCategory(device);
+ const VolumeCurvePoint *curve = streamDesc.getVolumeCurvePoint(deviceCategory);
+
+ // 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;
+ int volIdx = (nbSteps * (indexInUi - streamDesc.getVolumeIndexMin())) /
+ (streamDesc.getVolumeIndexMax() - streamDesc.getVolumeIndexMin());
+
+ // 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 )
+
+ ALOGVV("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 android
diff --git a/services/audiopolicy/enginedefault/src/Gains.h b/services/audiopolicy/enginedefault/src/Gains.h
new file mode 100644
index 0000000..b5601ca
--- /dev/null
+++ b/services/audiopolicy/enginedefault/src/Gains.h
@@ -0,0 +1,59 @@
+/*
+ * 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 <StreamDescriptor.h>
+#include <utils/KeyedVector.h>
+#include <system/audio.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class StreamDescriptor;
+
+class Gains
+{
+public :
+ static float volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc,
+ int indexInUi);
+
+ // default volume curve
+ static const VolumeCurvePoint sDefaultVolumeCurve[Volume::VOLCNT];
+ // default volume curve for media strategy
+ static const VolumeCurvePoint sDefaultMediaVolumeCurve[Volume::VOLCNT];
+ // volume curve for non-media audio on ext media outputs (HDMI, Line, etc)
+ static const VolumeCurvePoint sExtMediaSystemVolumeCurve[Volume::VOLCNT];
+ // volume curve for media strategy on speakers
+ static const VolumeCurvePoint sSpeakerMediaVolumeCurve[Volume::VOLCNT];
+ static const VolumeCurvePoint sSpeakerMediaVolumeCurveDrc[Volume::VOLCNT];
+ // volume curve for sonification strategy on speakers
+ static const VolumeCurvePoint sSpeakerSonificationVolumeCurve[Volume::VOLCNT];
+ static const VolumeCurvePoint sSpeakerSonificationVolumeCurveDrc[Volume::VOLCNT];
+ static const VolumeCurvePoint sDefaultSystemVolumeCurve[Volume::VOLCNT];
+ static const VolumeCurvePoint sDefaultSystemVolumeCurveDrc[Volume::VOLCNT];
+ static const VolumeCurvePoint sHeadsetSystemVolumeCurve[Volume::VOLCNT];
+ static const VolumeCurvePoint sDefaultVoiceVolumeCurve[Volume::VOLCNT];
+ static const VolumeCurvePoint sSpeakerVoiceVolumeCurve[Volume::VOLCNT];
+ static const VolumeCurvePoint sLinearVolumeCurve[Volume::VOLCNT];
+ static const VolumeCurvePoint sSilentVolumeCurve[Volume::VOLCNT];
+ static const VolumeCurvePoint sFullScaleVolumeCurve[Volume::VOLCNT];
+ // default volume curves per stream and device category. See initializeVolumeCurves()
+ static const VolumeCurvePoint *sVolumeProfiles[AUDIO_STREAM_CNT][Volume::DEVICE_CATEGORY_CNT];
+};
+
+}; // namespace android