summaryrefslogtreecommitdiffstats
path: root/services/audiopolicy
diff options
context:
space:
mode:
Diffstat (limited to 'services/audiopolicy')
-rw-r--r--services/audiopolicy/Android.mk36
-rw-r--r--services/audiopolicy/common/Android.mk9
-rw-r--r--services/audiopolicy/common/include/RoutingStrategy.h (renamed from services/audiopolicy/managerdefault/ApmImplDefinitions.h)6
-rwxr-xr-xservices/audiopolicy/common/include/Volume.h137
-rwxr-xr-xservices/audiopolicy/common/include/policy.h84
-rw-r--r--services/audiopolicy/common/managerdefinitions/Android.mk34
-rw-r--r--services/audiopolicy/common/managerdefinitions/include/AudioGain.h40
-rw-r--r--services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h (renamed from services/audiopolicy/managerdefault/AudioInputDescriptor.h)37
-rw-r--r--services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h (renamed from services/audiopolicy/managerdefault/AudioOutputDescriptor.h)52
-rw-r--r--services/audiopolicy/common/managerdefinitions/include/AudioPatch.h55
-rw-r--r--services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h81
-rw-r--r--services/audiopolicy/common/managerdefinitions/include/AudioPort.h (renamed from services/audiopolicy/managerdefault/Ports.h)37
-rw-r--r--services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h (renamed from services/audiopolicy/managerdefault/ConfigParsingUtils.h)39
-rw-r--r--services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h (renamed from services/audiopolicy/managerdefault/Devices.h)38
-rw-r--r--services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h71
-rw-r--r--services/audiopolicy/common/managerdefinitions/include/HwModule.h (renamed from services/audiopolicy/managerdefault/HwModule.h)28
-rw-r--r--services/audiopolicy/common/managerdefinitions/include/IOProfile.h (renamed from services/audiopolicy/managerdefault/IOProfile.h)7
-rw-r--r--services/audiopolicy/common/managerdefinitions/include/SoundTriggerSession.h33
-rw-r--r--services/audiopolicy/common/managerdefinitions/include/StreamDescriptor.h85
-rw-r--r--services/audiopolicy/common/managerdefinitions/include/audio_policy_conf.h (renamed from services/audiopolicy/managerdefault/audio_policy_conf.h)14
-rw-r--r--services/audiopolicy/common/managerdefinitions/src/AudioGain.cpp130
-rw-r--r--services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp (renamed from services/audiopolicy/managerdefault/AudioInputDescriptor.cpp)99
-rw-r--r--services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp (renamed from services/audiopolicy/managerdefault/AudioOutputDescriptor.cpp)144
-rw-r--r--services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp154
-rw-r--r--services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp193
-rw-r--r--services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp (renamed from services/audiopolicy/managerdefault/Ports.cpp)84
-rw-r--r--services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp288
-rw-r--r--services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp (renamed from services/audiopolicy/managerdefault/Devices.cpp)68
-rw-r--r--services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp192
-rw-r--r--services/audiopolicy/common/managerdefinitions/src/HwModule.cpp (renamed from services/audiopolicy/managerdefault/HwModule.cpp)98
-rw-r--r--services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp (renamed from services/audiopolicy/managerdefault/IOProfile.cpp)28
-rw-r--r--services/audiopolicy/common/managerdefinitions/src/SoundTriggerSession.cpp45
-rw-r--r--services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp162
-rwxr-xr-xservices/audiopolicy/engine/interface/AudioPolicyManagerInterface.h171
-rwxr-xr-xservices/audiopolicy/engine/interface/AudioPolicyManagerObserver.h62
-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
-rw-r--r--services/audiopolicy/managerdefault/AudioPolicyManager.cpp1857
-rw-r--r--services/audiopolicy/managerdefault/AudioPolicyManager.h238
-rw-r--r--services/audiopolicy/managerdefault/ConfigParsingUtils.cpp121
-rw-r--r--services/audiopolicy/managerdefault/Gains.cpp446
-rw-r--r--services/audiopolicy/managerdefault/Gains.h112
-rw-r--r--services/audiopolicy/service/AudioPolicyService.cpp2
48 files changed, 4482 insertions, 2484 deletions
diff --git a/services/audiopolicy/Android.mk b/services/audiopolicy/Android.mk
index 351ed79..d4ce86a 100644
--- a/services/audiopolicy/Android.mk
+++ b/services/audiopolicy/Android.mk
@@ -21,7 +21,9 @@ endif
LOCAL_C_INCLUDES := \
$(TOPDIR)frameworks/av/services/audioflinger \
$(call include-path-for, audio-effects) \
- $(call include-path-for, audio-utils)
+ $(call include-path-for, audio-utils) \
+ $(TOPDIR)frameworks/av/services/audiopolicy/common/include \
+ $(TOPDIR)frameworks/av/services/audiopolicy/engine/interface \
LOCAL_SHARED_LIBRARIES := \
libcutils \
@@ -39,7 +41,8 @@ LOCAL_SHARED_LIBRARIES += \
endif
LOCAL_STATIC_LIBRARIES := \
- libmedia_helper
+ libmedia_helper \
+ libaudiopolicycomponents
LOCAL_MODULE:= libaudiopolicyservice
@@ -54,14 +57,6 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
managerdefault/AudioPolicyManager.cpp \
- managerdefault/ConfigParsingUtils.cpp \
- managerdefault/Devices.cpp \
- managerdefault/Gains.cpp \
- managerdefault/HwModule.cpp \
- managerdefault/IOProfile.cpp \
- managerdefault/Ports.cpp \
- managerdefault/AudioInputDescriptor.cpp \
- managerdefault/AudioOutputDescriptor.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
@@ -69,8 +64,15 @@ LOCAL_SHARED_LIBRARIES := \
liblog \
libsoundtrigger
+LOCAL_SHARED_LIBRARIES += libaudiopolicyenginedefault
+
+LOCAL_C_INCLUDES += \
+ $(TOPDIR)frameworks/av/services/audiopolicy/common/include \
+ $(TOPDIR)frameworks/av/services/audiopolicy/engine/interface \
+
LOCAL_STATIC_LIBRARIES := \
- libmedia_helper
+ libmedia_helper \
+ libaudiopolicycomponents
LOCAL_MODULE:= libaudiopolicymanagerdefault
@@ -86,9 +88,21 @@ LOCAL_SRC_FILES:= \
LOCAL_SHARED_LIBRARIES := \
libaudiopolicymanagerdefault
+LOCAL_STATIC_LIBRARIES := \
+ libaudiopolicycomponents
+
+LOCAL_C_INCLUDES += \
+ $(TOPDIR)frameworks/av/services/audiopolicy/common/include \
+ $(TOPDIR)frameworks/av/services/audiopolicy/engine/interface \
+
LOCAL_MODULE:= libaudiopolicymanager
include $(BUILD_SHARED_LIBRARY)
endif
endif
+
+#######################################################################
+# Recursive call sub-folder Android.mk
+#
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/services/audiopolicy/common/Android.mk b/services/audiopolicy/common/Android.mk
new file mode 100644
index 0000000..dcce8e3
--- /dev/null
+++ b/services/audiopolicy/common/Android.mk
@@ -0,0 +1,9 @@
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+#######################################################################
+# Recursive call sub-folder Android.mk
+#
+include $(call all-makefiles-under,$(LOCAL_PATH))
+
diff --git a/services/audiopolicy/managerdefault/ApmImplDefinitions.h b/services/audiopolicy/common/include/RoutingStrategy.h
index 620979b..d38967e 100644
--- a/services/audiopolicy/managerdefault/ApmImplDefinitions.h
+++ b/services/audiopolicy/common/include/RoutingStrategy.h
@@ -14,8 +14,14 @@
* limitations under the License.
*/
+#pragma once
+
namespace android {
+// Time in milliseconds after media stopped playing during which we consider that the
+// sonification should be as unobtrusive as during the time media was playing.
+#define SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY 5000
+
enum routing_strategy {
STRATEGY_MEDIA,
STRATEGY_PHONE,
diff --git a/services/audiopolicy/common/include/Volume.h b/services/audiopolicy/common/include/Volume.h
new file mode 100755
index 0000000..a4cc759
--- /dev/null
+++ b/services/audiopolicy/common/include/Volume.h
@@ -0,0 +1,137 @@
+/*
+ * 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 <system/audio.h>
+#include <utils/Log.h>
+
+class VolumeCurvePoint
+{
+public:
+ int mIndex;
+ float mDBAttenuation;
+};
+
+class Volume
+{
+public:
+ /**
+ * 4 points to define the volume attenuation curve, each characterized by the volume
+ * index (from 0 to 100) at which they apply, and the attenuation in dB at that index.
+ * we use 100 steps to avoid rounding errors when computing the volume in volIndexToAmpl()
+ *
+ * @todo shall become configurable
+ */
+ enum {
+ VOLMIN = 0,
+ VOLKNEE1 = 1,
+ VOLKNEE2 = 2,
+ VOLMAX = 3,
+
+ VOLCNT = 4
+ };
+
+ /**
+ * device categories used for volume curve management.
+ */
+ enum device_category {
+ DEVICE_CATEGORY_HEADSET,
+ DEVICE_CATEGORY_SPEAKER,
+ DEVICE_CATEGORY_EARPIECE,
+ DEVICE_CATEGORY_EXT_MEDIA,
+ DEVICE_CATEGORY_CNT
+ };
+
+ /**
+ * extract one device relevant for volume control from multiple device selection
+ *
+ * @param[in] device for which the volume category is associated
+ *
+ * @return subset of device required to limit the number of volume category per device
+ */
+ static audio_devices_t getDeviceForVolume(audio_devices_t device)
+ {
+ if (device == AUDIO_DEVICE_NONE) {
+ // this happens when forcing a route update and no track is active on an output.
+ // In this case the returned category is not important.
+ device = AUDIO_DEVICE_OUT_SPEAKER;
+ } else if (popcount(device) > 1) {
+ // Multiple device selection is either:
+ // - speaker + one other device: give priority to speaker in this case.
+ // - one A2DP device + another device: happens with duplicated output. In this case
+ // retain the device on the A2DP output as the other must not correspond to an active
+ // selection if not the speaker.
+ // - HDMI-CEC system audio mode only output: give priority to available item in order.
+ if (device & AUDIO_DEVICE_OUT_SPEAKER) {
+ device = AUDIO_DEVICE_OUT_SPEAKER;
+ } else if (device & AUDIO_DEVICE_OUT_HDMI_ARC) {
+ device = AUDIO_DEVICE_OUT_HDMI_ARC;
+ } else if (device & AUDIO_DEVICE_OUT_AUX_LINE) {
+ device = AUDIO_DEVICE_OUT_AUX_LINE;
+ } else if (device & AUDIO_DEVICE_OUT_SPDIF) {
+ device = AUDIO_DEVICE_OUT_SPDIF;
+ } else {
+ device = (audio_devices_t)(device & AUDIO_DEVICE_OUT_ALL_A2DP);
+ }
+ }
+
+ /*SPEAKER_SAFE is an alias of SPEAKER for purposes of volume control*/
+ if (device == AUDIO_DEVICE_OUT_SPEAKER_SAFE)
+ device = AUDIO_DEVICE_OUT_SPEAKER;
+
+ ALOGW_IF(popcount(device) != 1,
+ "getDeviceForVolume() invalid device combination: %08x",
+ device);
+
+ return device;
+ }
+
+ /**
+ * returns the category the device belongs to with regard to volume curve management
+ *
+ * @param[in] device to check upon the category to whom it belongs to.
+ *
+ * @return device category.
+ */
+ static device_category getDeviceCategory(audio_devices_t device)
+ {
+ switch(getDeviceForVolume(device)) {
+ case AUDIO_DEVICE_OUT_EARPIECE:
+ return DEVICE_CATEGORY_EARPIECE;
+ case AUDIO_DEVICE_OUT_WIRED_HEADSET:
+ case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
+ case AUDIO_DEVICE_OUT_BLUETOOTH_SCO:
+ case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
+ case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
+ case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
+ return DEVICE_CATEGORY_HEADSET;
+ case AUDIO_DEVICE_OUT_LINE:
+ case AUDIO_DEVICE_OUT_AUX_DIGITAL:
+ /*USB? Remote submix?*/
+ return DEVICE_CATEGORY_EXT_MEDIA;
+ case AUDIO_DEVICE_OUT_SPEAKER:
+ case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
+ case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
+ case AUDIO_DEVICE_OUT_USB_ACCESSORY:
+ case AUDIO_DEVICE_OUT_USB_DEVICE:
+ case AUDIO_DEVICE_OUT_REMOTE_SUBMIX:
+ default:
+ return DEVICE_CATEGORY_SPEAKER;
+ }
+ }
+
+};
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
new file mode 100755
index 0000000..a2327ee
--- /dev/null
+++ b/services/audiopolicy/common/include/policy.h
@@ -0,0 +1,84 @@
+/*
+ * 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 <system/audio.h>
+
+// For mixed output and inputs, the policy will use max mixer sampling rates.
+// Do not limit sampling rate otherwise
+#define MAX_MIXER_SAMPLING_RATE 48000
+
+// For mixed output and inputs, the policy will use max mixer channel count.
+// Do not limit channel count otherwise
+#define MAX_MIXER_CHANNEL_COUNT 8
+
+/**
+ * A device mask for all audio input devices that are considered "virtual" when evaluating
+ * active inputs in getActiveInput()
+ */
+#define APM_AUDIO_IN_DEVICE_VIRTUAL_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX|AUDIO_DEVICE_IN_FM_TUNER)
+
+
+/**
+ * A device mask for all audio input and output devices where matching inputs/outputs on device
+ * type alone is not enough: the address must match too
+ */
+#define APM_AUDIO_DEVICE_MATCH_ADDRESS_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX | \
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX)
+
+/**
+ * Check if the state given correspond to an in call state.
+ * @TODO find a better name for widely call state
+ *
+ * @param[in] state to consider
+ *
+ * @return true if given state represents a device in a telephony or VoIP call
+ */
+static inline bool is_state_in_call(int state)
+{
+ return (state == AUDIO_MODE_IN_CALL) || (state == AUDIO_MODE_IN_COMMUNICATION);
+}
+
+/**
+ * Check if the input device given is considered as a virtual device.
+ *
+ * @param[in] device to consider
+ *
+ * @return true if the device is a virtual one, false otherwise.
+ */
+static bool is_virtual_input_device(audio_devices_t device)
+{
+ if ((device & AUDIO_DEVICE_BIT_IN) != 0) {
+ device &= ~AUDIO_DEVICE_BIT_IN;
+ if ((popcount(device) == 1) && ((device & ~APM_AUDIO_IN_DEVICE_VIRTUAL_ALL) == 0))
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Check whether the device type is one
+ * where addresses are used to distinguish between one connected device and another
+ *
+ * @param[in] device to consider
+ *
+ * @return true if the device needs distinguish on address, false otherwise..
+ */
+static bool device_distinguishes_on_address(audio_devices_t device)
+{
+ return ((device & APM_AUDIO_DEVICE_MATCH_ADDRESS_ALL & ~AUDIO_DEVICE_BIT_IN) != 0);
+}
diff --git a/services/audiopolicy/common/managerdefinitions/Android.mk b/services/audiopolicy/common/managerdefinitions/Android.mk
new file mode 100644
index 0000000..71ba1cb
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/Android.mk
@@ -0,0 +1,34 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ src/DeviceDescriptor.cpp \
+ src/AudioGain.cpp \
+ src/StreamDescriptor.cpp \
+ src/HwModule.cpp \
+ src/IOProfile.cpp \
+ src/AudioPort.cpp \
+ src/AudioPolicyMix.cpp \
+ src/AudioPatch.cpp \
+ src/AudioInputDescriptor.cpp \
+ src/AudioOutputDescriptor.cpp \
+ src/EffectDescriptor.cpp \
+ src/ConfigParsingUtils.cpp \
+ src/SoundTriggerSession.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libutils \
+ liblog \
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/include \
+ $(TOPDIR)frameworks/av/services/audiopolicy/common/include \
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := \
+ $(LOCAL_PATH)/include
+
+LOCAL_MODULE := libaudiopolicycomponents
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioGain.h b/services/audiopolicy/common/managerdefinitions/include/AudioGain.h
new file mode 100644
index 0000000..21fbf9b
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioGain.h
@@ -0,0 +1,40 @@
+/*
+ * 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 <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <system/audio.h>
+
+namespace android {
+
+class AudioGain: public RefBase
+{
+public:
+ AudioGain(int index, bool useInChannelMask);
+ virtual ~AudioGain() {}
+
+ void dump(int fd, int spaces, int index) const;
+
+ void getDefaultConfig(struct audio_gain_config *config);
+ status_t checkConfig(const struct audio_gain_config *config);
+ int mIndex;
+ struct audio_gain mGain;
+ bool mUseInChannelMask;
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/managerdefault/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index 02579e6..7536a37 100644
--- a/services/audiopolicy/managerdefault/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -14,14 +14,28 @@
* limitations under the License.
*/
+#pragma once
+
+#include "AudioPort.h"
+#include <utils/Errors.h>
+#include <system/audio.h>
+#include <utils/SortedVector.h>
+#include <utils/KeyedVector.h>
+
namespace android {
+class IOProfile;
+class AudioMix;
+
// descriptor for audio inputs. Used to maintain current configuration of each opened audio input
// and keep track of the usage of this input.
class AudioInputDescriptor: public AudioPortConfig
{
public:
AudioInputDescriptor(const sp<IOProfile>& profile);
+ void setIoHandle(audio_io_handle_t ioHandle);
+
+ audio_module_handle_t getModuleHandle() const;
status_t dump(int fd);
@@ -45,4 +59,27 @@ public:
void toAudioPort(struct audio_port *port) const;
};
+class AudioInputCollection :
+ public DefaultKeyedVector< audio_io_handle_t, sp<AudioInputDescriptor> >
+{
+public:
+ bool isSourceActive(audio_source_t source) const;
+
+ sp<AudioInputDescriptor> getInputFromId(audio_port_handle_t id) const;
+
+ uint32_t activeInputsCount() const;
+
+ /**
+ * return io handle of active input or 0 if no input is active
+ * Only considers inputs from physical devices (e.g. main mic, headset mic) when
+ * ignoreVirtualInputs is true.
+ */
+ audio_io_handle_t getActiveInput(bool ignoreVirtualInputs = true);
+
+ audio_devices_t getSupportedDevices(audio_io_handle_t handle) const;
+
+ status_t dump(int fd) const;
+};
+
+
}; // namespace android
diff --git a/services/audiopolicy/managerdefault/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index 32f46e4..43ee691 100644
--- a/services/audiopolicy/managerdefault/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -14,10 +14,20 @@
* limitations under the License.
*/
-#include "ApmImplDefinitions.h"
+#pragma once
+
+#include "AudioPort.h"
+#include <RoutingStrategy.h>
+#include <utils/Errors.h>
+#include <utils/Timers.h>
+#include <utils/KeyedVector.h>
+#include <system/audio.h>
namespace android {
+class IOProfile;
+class AudioMix;
+
// descriptor for audio outputs. Used to maintain current configuration of each opened audio output
// and keep track of the usage of this output by each audio stream type.
class AudioOutputDescriptor: public AudioPortConfig
@@ -30,6 +40,7 @@ public:
audio_devices_t device() const;
void changeRefCount(audio_stream_type_t stream, int delta);
+ void setIoHandle(audio_io_handle_t ioHandle);
bool isDuplicated() const { return (mOutput1 != NULL && mOutput2 != NULL); }
audio_devices_t supportedDevices();
uint32_t latency();
@@ -38,15 +49,14 @@ public:
bool isStreamActive(audio_stream_type_t stream,
uint32_t inPastMs = 0,
nsecs_t sysTime = 0) const;
- bool isStrategyActive(routing_strategy strategy,
- uint32_t inPastMs = 0,
- nsecs_t sysTime = 0) const;
virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig = NULL) const;
virtual sp<AudioPort> getAudioPort() const { return mProfile; }
void toAudioPort(struct audio_port *port) const;
+ audio_module_handle_t getModuleHandle() const;
+
audio_port_handle_t mId;
audio_io_handle_t mIoHandle; // output handle
uint32_t mLatency; //
@@ -66,4 +76,38 @@ public:
uint32_t mDirectOpenCount; // number of clients using this output (direct outputs only)
};
+class AudioOutputCollection :
+ public DefaultKeyedVector< audio_io_handle_t, sp<AudioOutputDescriptor> >
+{
+public:
+ bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
+
+ /**
+ * return whether a stream is playing remotely, override to change the definition of
+ * local/remote playback, used for instance by notification manager to not make
+ * media players lose audio focus when not playing locally
+ * For the base implementation, "remotely" means playing during screen mirroring which
+ * uses an output for playback with a non-empty, non "0" address.
+ */
+ bool isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
+
+ /**
+ * returns the A2DP output handle if it is open or 0 otherwise
+ */
+ audio_io_handle_t getA2dpOutput() const;
+
+ sp<AudioOutputDescriptor> getOutputFromId(audio_port_handle_t id) const;
+
+ sp<AudioOutputDescriptor> getPrimaryOutput() const;
+
+ /**
+ * return true if any output is playing anything besides the stream to ignore
+ */
+ bool isAnyOutputActive(audio_stream_type_t streamToIgnore) const;
+
+ audio_devices_t getSupportedDevices(audio_io_handle_t handle) const;
+
+ status_t dump(int fd) const;
+};
+
}; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPatch.h b/services/audiopolicy/common/managerdefinitions/include/AudioPatch.h
new file mode 100644
index 0000000..385f257
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPatch.h
@@ -0,0 +1,55 @@
+/*
+ * 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 <system/audio.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+
+namespace android {
+
+class AudioPatch : public RefBase
+{
+public:
+ AudioPatch(const struct audio_patch *patch, uid_t uid);
+
+ status_t dump(int fd, int spaces, int index) const;
+
+ audio_patch_handle_t mHandle;
+ struct audio_patch mPatch;
+ uid_t mUid;
+ audio_patch_handle_t mAfPatchHandle;
+
+private:
+ static volatile int32_t mNextUniqueId;
+};
+
+class AudioPatchCollection : public DefaultKeyedVector<audio_patch_handle_t, sp<AudioPatch> >
+{
+public:
+ status_t addAudioPatch(audio_patch_handle_t handle, const sp<AudioPatch>& patch);
+
+ status_t removeAudioPatch(audio_patch_handle_t handle);
+
+ status_t listAudioPatches(unsigned int *num_patches, struct audio_patch *patches) const;
+
+ status_t dump(int fd) const;
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
new file mode 100644
index 0000000..988aed6
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -0,0 +1,81 @@
+/*
+ * 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 <utils/RefBase.h>
+#include <media/AudioPolicy.h>
+#include <utils/KeyedVector.h>
+#include <hardware/audio.h>
+#include <utils/String8.h>
+
+namespace android {
+
+class AudioOutputDescriptor;
+
+/**
+ * custom mix entry in mPolicyMixes
+ */
+class AudioPolicyMix : public RefBase {
+public:
+ AudioPolicyMix() {}
+
+ const sp<AudioOutputDescriptor> &getOutput() const;
+
+ void setOutput(sp<AudioOutputDescriptor> &output);
+
+ void clearOutput();
+
+ android::AudioMix &getMix();
+
+ void setMix(AudioMix &mix);
+
+private:
+ AudioMix mMix; // Audio policy mix descriptor
+ sp<AudioOutputDescriptor> mOutput; // Corresponding output stream
+};
+
+
+class AudioPolicyMixCollection : public DefaultKeyedVector<String8, sp<AudioPolicyMix> >
+{
+public:
+ status_t getAudioPolicyMix(String8 address, sp<AudioPolicyMix> &policyMix) const;
+
+ status_t registerMix(String8 address, AudioMix mix);
+
+ status_t unregisterMix(String8 address);
+
+ void closeOutput(sp<AudioOutputDescriptor> &desc);
+
+ /**
+ * Try to find an output descriptor for the given attributes.
+ *
+ * @param[in] attributes to consider for the research of output descriptor.
+ * @param[out] desc to return if an output could be found.
+ *
+ * @return NO_ERROR if an output was found for the given attribute (in this case, the
+ * descriptor output param is initialized), error code otherwise.
+ */
+ status_t getOutputForAttr(audio_attributes_t attributes, sp<AudioOutputDescriptor> &desc);
+
+ audio_devices_t getDeviceAndMixForInputSource(audio_source_t inputSource,
+ audio_devices_t availableDeviceTypes,
+ AudioMix **policyMix);
+
+ status_t getInputMixForAttr(audio_attributes_t attr, AudioMix *&policyMix);
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/managerdefault/Ports.h b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
index f6e0e93..4f7f2bc 100644
--- a/services/audiopolicy/managerdefault/Ports.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
@@ -14,15 +14,25 @@
* limitations under the License.
*/
+#pragma once
+
+#include <utils/String8.h>
+#include <utils/Vector.h>
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <system/audio.h>
+#include <cutils/config_utils.h>
+
namespace android {
class HwModule;
+class AudioGain;
-class AudioPort: public virtual RefBase
+class AudioPort : public virtual RefBase
{
public:
AudioPort(const String8& name, audio_port_type_t type,
- audio_port_role_t role, const sp<HwModule>& module);
+ audio_port_role_t role, const sp<HwModule>& module);
virtual ~AudioPort() {}
audio_port_handle_t getHandle() { return mId; }
@@ -30,6 +40,8 @@ public:
void attach(const sp<HwModule>& module);
bool isAttached() { return mId != 0; }
+ static audio_port_handle_t getNextUniqueId();
+
virtual void toAudioPort(struct audio_port *port) const;
void importAudioPort(const sp<AudioPort> port);
@@ -63,6 +75,8 @@ public:
static const audio_format_t sPcmFormatCompareTable[];
static int compareFormats(audio_format_t format1, audio_format_t format2);
+ audio_module_handle_t getModuleHandle() const;
+
void dump(int fd, int spaces) const;
String8 mName;
@@ -86,9 +100,12 @@ protected:
// and a unique ID for identifying a port to the (upcoming) selection API,
// and its relationship to the mId in AudioOutputDescriptor and AudioInputDescriptor.
audio_port_handle_t mId;
+
+private:
+ static volatile int32_t mNextUniqueId;
};
-class AudioPortConfig: public virtual RefBase
+class AudioPortConfig : public virtual RefBase
{
public:
AudioPortConfig();
@@ -105,18 +122,4 @@ public:
struct audio_gain_config mGain;
};
-
-class AudioPatch: public RefBase
-{
-public:
- AudioPatch(audio_patch_handle_t handle, const struct audio_patch *patch, uid_t uid);
-
- status_t dump(int fd, int spaces, int index) const;
-
- audio_patch_handle_t mHandle;
- struct audio_patch mPatch;
- uid_t mUid;
- audio_patch_handle_t mAfPatchHandle;
-};
-
}; // namespace android
diff --git a/services/audiopolicy/managerdefault/ConfigParsingUtils.h b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
index b2d9763..53cb4a3 100644
--- a/services/audiopolicy/managerdefault/ConfigParsingUtils.h
+++ b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
@@ -14,6 +14,19 @@
* limitations under the License.
*/
+#pragma once
+
+#include "DeviceDescriptor.h"
+#include "HwModule.h"
+#include "audio_policy_conf.h"
+#include <system/audio.h>
+#include <utils/Log.h>
+#include <utils/Vector.h>
+#include <utils/SortedVector.h>
+#include <cutils/config_utils.h>
+#include <utils/RefBase.h>
+#include <system/audio_policy.h>
+
namespace android {
// ----------------------------------------------------------------------------
@@ -156,6 +169,32 @@ public:
static uint32_t parseOutputFlagNames(char *name);
static uint32_t parseInputFlagNames(char *name);
static audio_devices_t parseDeviceNames(char *name);
+
+ static void loadHwModules(cnode *root, HwModuleCollection &hwModules,
+ DeviceVector &availableInputDevices,
+ DeviceVector &availableOutputDevices,
+ sp<DeviceDescriptor> &defaultOutputDevices,
+ bool &isSpeakerDrcEnabled);
+
+ static void loadGlobalConfig(cnode *root, const sp<HwModule>& module,
+ DeviceVector &availableInputDevices,
+ DeviceVector &availableOutputDevices,
+ sp<DeviceDescriptor> &defaultOutputDevices,
+ bool &isSpeakerDrcEnabled);
+
+ static status_t loadAudioPolicyConfig(const char *path,
+ HwModuleCollection &hwModules,
+ DeviceVector &availableInputDevices,
+ DeviceVector &availableOutputDevices,
+ sp<DeviceDescriptor> &defaultOutputDevices,
+ bool &isSpeakerDrcEnabled);
+
+private:
+ static void loadHwModule(cnode *root, HwModuleCollection &hwModules,
+ DeviceVector &availableInputDevices,
+ DeviceVector &availableOutputDevices,
+ sp<DeviceDescriptor> &defaultOutputDevices,
+ bool &isSpeakerDrcEnabled);
};
}; // namespace android
diff --git a/services/audiopolicy/managerdefault/Devices.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index af2fbda..d15f6b4 100644
--- a/services/audiopolicy/managerdefault/Devices.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -14,12 +14,19 @@
* limitations under the License.
*/
-namespace android {
+#pragma once
+
+#include "AudioPort.h"
+#include <utils/Errors.h>
+#include <utils/String8.h>
+#include <utils/SortedVector.h>
+#include <cutils/config_utils.h>
+#include <system/audio.h>
+#include <system/audio_policy.h>
-class AudioPort;
-class AudioPortConfig;
+namespace android {
-class DeviceDescriptor: public AudioPort, public AudioPortConfig
+class DeviceDescriptor : public AudioPort, public AudioPortConfig
{
public:
DeviceDescriptor(const String8& name, audio_devices_t type);
@@ -37,12 +44,18 @@ public:
virtual void loadGains(cnode *root);
virtual void toAudioPort(struct audio_port *port) const;
+ audio_devices_t type() const { return mDeviceType; }
status_t dump(int fd, int spaces, int index) const;
- audio_devices_t mDeviceType;
String8 mAddress;
+ audio_port_handle_t mId;
static String8 emptyNameStr;
+
+private:
+ audio_devices_t mDeviceType;
+
+friend class DeviceVector;
};
class DeviceVector : public SortedVector< sp<DeviceDescriptor> >
@@ -50,9 +63,9 @@ class DeviceVector : public SortedVector< sp<DeviceDescriptor> >
public:
DeviceVector() : SortedVector(), mDeviceTypes(AUDIO_DEVICE_NONE) {}
- ssize_t add(const sp<DeviceDescriptor>& item);
- ssize_t remove(const sp<DeviceDescriptor>& item);
- ssize_t indexOf(const sp<DeviceDescriptor>& item) const;
+ ssize_t add(const sp<DeviceDescriptor>& item);
+ ssize_t remove(const sp<DeviceDescriptor>& item);
+ ssize_t indexOf(const sp<DeviceDescriptor>& item) const;
audio_devices_t types() const { return mDeviceTypes; }
@@ -63,8 +76,13 @@ public:
DeviceVector getDevicesFromType(audio_devices_t types) const;
sp<DeviceDescriptor> getDeviceFromId(audio_port_handle_t id) const;
sp<DeviceDescriptor> getDeviceFromName(const String8& name) const;
- DeviceVector getDevicesFromTypeAddr(audio_devices_t type, String8 address)
- const;
+ DeviceVector getDevicesFromTypeAddr(audio_devices_t type, String8 address) const;
+
+ audio_devices_t getDevicesFromHwModule(audio_module_handle_t moduleHandle) const;
+
+ audio_policy_dev_state_t getDeviceConnectionState(const sp<DeviceDescriptor> &devDesc) const;
+
+ status_t dump(int fd, const String8 &direction) const;
private:
void refreshTypes();
diff --git a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
new file mode 100644
index 0000000..c9783a1
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
@@ -0,0 +1,71 @@
+/*
+ * 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 <RoutingStrategy.h>
+#include <hardware/audio_effect.h>
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+
+class EffectDescriptor : public RefBase
+{
+public:
+ status_t dump(int fd);
+
+ int mIo; // io the effect is attached to
+ routing_strategy mStrategy; // routing strategy the effect is associated to
+ int mSession; // audio session the effect is on
+ effect_descriptor_t mDesc; // effect descriptor
+ bool mEnabled; // enabled state: CPU load being used or not
+};
+
+class EffectDescriptorCollection : public KeyedVector<int, sp<EffectDescriptor> >
+{
+public:
+ EffectDescriptorCollection();
+
+ status_t registerEffect(const effect_descriptor_t *desc, audio_io_handle_t io,
+ uint32_t strategy, int session, int id);
+ status_t unregisterEffect(int id);
+ status_t setEffectEnabled(int id, bool enabled);
+ uint32_t getMaxEffectsCpuLoad() const;
+ uint32_t getMaxEffectsMemory() const;
+ bool isNonOffloadableEffectEnabled();
+
+ status_t dump(int fd);
+
+private:
+ status_t setEffectEnabled(const sp<EffectDescriptor> &effectDesc, bool enabled);
+
+ uint32_t mTotalEffectsCpuLoad; // current CPU load used by effects
+ uint32_t mTotalEffectsMemory; // current memory used by effects
+
+ /**
+ * Maximum CPU load allocated to audio effects in 0.1 MIPS (ARMv5TE, 0 WS memory) units
+ */
+ static const uint32_t MAX_EFFECTS_CPU_LOAD = 1000;
+ /**
+ * Maximum memory allocated to audio effects in KB
+ */
+ static const uint32_t MAX_EFFECTS_MEMORY = 512;
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/managerdefault/HwModule.h b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
index f814dd9..92c3ea2 100644
--- a/services/audiopolicy/managerdefault/HwModule.h
+++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
@@ -14,8 +14,20 @@
* limitations under the License.
*/
+#pragma once
+
+#include "DeviceDescriptor.h"
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/Errors.h>
+#include <utils/Vector.h>
+#include <system/audio.h>
+#include <cutils/config_utils.h>
+
namespace android {
+class IOProfile;
+
class HwModule : public RefBase
{
public:
@@ -33,6 +45,8 @@ public:
audio_devices_t device, String8 address);
status_t removeInputProfile(String8 name);
+ audio_module_handle_t getHandle() const { return mHandle; }
+
void dump(int fd);
const char *const mName; // base name of the audio HW module (primary, a2dp ...)
@@ -43,4 +57,18 @@ public:
DeviceVector mDeclaredDevices; // devices declared in audio_policy.conf
};
+class HwModuleCollection : public Vector< sp<HwModule> >
+{
+public:
+ sp<HwModule> getModuleFromName(const char *name) const;
+
+ sp <HwModule> getModuleForDevice(audio_devices_t device) const;
+
+ sp<DeviceDescriptor> getDeviceDescriptor(const audio_devices_t device,
+ const char *device_address,
+ const char *device_name) const;
+
+ status_t dump(int fd) const;
+};
+
}; // namespace android
diff --git a/services/audiopolicy/managerdefault/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
index 3317969..095e759 100644
--- a/services/audiopolicy/managerdefault/IOProfile.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
@@ -14,6 +14,13 @@
* limitations under the License.
*/
+#pragma once
+
+#include "AudioPort.h"
+#include "DeviceDescriptor.h"
+#include <utils/String8.h>
+#include <system/audio.h>
+
namespace android {
class HwModule;
diff --git a/services/audiopolicy/common/managerdefinitions/include/SoundTriggerSession.h b/services/audiopolicy/common/managerdefinitions/include/SoundTriggerSession.h
new file mode 100644
index 0000000..420e6d7
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/include/SoundTriggerSession.h
@@ -0,0 +1,33 @@
+/*
+ * 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 <system/audio.h>
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+
+namespace android {
+
+class SoundTriggerSessionCollection : public DefaultKeyedVector<audio_session_t, audio_io_handle_t>
+{
+public:
+ status_t releaseSession(audio_session_t session);
+
+ status_t acquireSession(audio_session_t session, audio_io_handle_t ioHandle);
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/StreamDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/StreamDescriptor.h
new file mode 100644
index 0000000..84db5ab
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/include/StreamDescriptor.h
@@ -0,0 +1,85 @@
+/*
+ * 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 <Volume.h>
+#include <utils/KeyedVector.h>
+#include <utils/StrongPointer.h>
+#include <utils/SortedVector.h>
+#include <hardware/audio.h>
+
+namespace android {
+
+// stream descriptor used for volume control
+class StreamDescriptor
+{
+public:
+ StreamDescriptor();
+
+ int getVolumeIndex(audio_devices_t device) const;
+ bool canBeMuted() const { return mCanBeMuted; }
+ void clearCurrentVolumeIndex();
+ void addCurrentVolumeIndex(audio_devices_t device, int index);
+ int getVolumeIndexMin() const { return mIndexMin; }
+ int getVolumeIndexMax() const { return mIndexMax; }
+ void setVolumeIndexMin(int volIndexMin);
+ void setVolumeIndexMax(int volIndexMax);
+
+ void dump(int fd) const;
+
+ void setVolumeCurvePoint(Volume::device_category deviceCategory, const VolumeCurvePoint *point);
+ const VolumeCurvePoint *getVolumeCurvePoint(Volume::device_category deviceCategory) const
+ {
+ return mVolumeCurve[deviceCategory];
+ }
+
+private:
+ const VolumeCurvePoint *mVolumeCurve[Volume::DEVICE_CATEGORY_CNT];
+ KeyedVector<audio_devices_t, int> mIndexCur; /**< current volume index per device. */
+ int mIndexMin; /**< min volume index. */
+ int mIndexMax; /**< max volume index. */
+ bool mCanBeMuted; /**< true is the stream can be muted. */
+};
+
+/**
+ * stream descriptors collection for volume control
+ */
+class StreamDescriptorCollection : public DefaultKeyedVector<audio_stream_type_t, StreamDescriptor>
+{
+public:
+ StreamDescriptorCollection();
+
+ void clearCurrentVolumeIndex(audio_stream_type_t stream);
+ void addCurrentVolumeIndex(audio_stream_type_t stream, audio_devices_t device, int index);
+
+ bool canBeMuted(audio_stream_type_t stream);
+
+ status_t dump(int fd) const;
+
+ void setVolumeCurvePoint(audio_stream_type_t stream,
+ Volume::device_category deviceCategory,
+ const VolumeCurvePoint *point);
+
+ const VolumeCurvePoint *getVolumeCurvePoint(audio_stream_type_t stream,
+ Volume::device_category deviceCategory) const;
+
+ void setVolumeIndexMin(audio_stream_type_t stream,int volIndexMin);
+ void setVolumeIndexMax(audio_stream_type_t stream,int volIndexMax);
+
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/managerdefault/audio_policy_conf.h b/services/audiopolicy/common/managerdefinitions/include/audio_policy_conf.h
index 2535a67..a393e3b 100644
--- a/services/audiopolicy/managerdefault/audio_policy_conf.h
+++ b/services/audiopolicy/common/managerdefinitions/include/audio_policy_conf.h
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-
-#ifndef ANDROID_AUDIO_POLICY_CONF_H
-#define ANDROID_AUDIO_POLICY_CONF_H
+#pragma once
/////////////////////////////////////////////////
@@ -53,9 +51,9 @@
// "formats" in outputs descriptors indicating that supported
// values should be queried after opening the output.
-#define DEVICES_TAG "devices"
-#define DEVICE_TYPE "type"
-#define DEVICE_ADDRESS "address"
+#define APM_DEVICES_TAG "devices"
+#define APM_DEVICE_TYPE "type"
+#define APM_DEVICE_ADDRESS "address"
#define MIXERS_TAG "mixers"
#define MIXER_TYPE "type"
@@ -71,7 +69,3 @@
#define GAIN_STEP_VALUE "step_value_mB"
#define GAIN_MIN_RAMP_MS "min_ramp_ms"
#define GAIN_MAX_RAMP_MS "max_ramp_ms"
-
-
-
-#endif // ANDROID_AUDIO_POLICY_CONF_H
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioGain.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioGain.cpp
new file mode 100644
index 0000000..fc7b0cc
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioGain.cpp
@@ -0,0 +1,130 @@
+/*
+ * 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::AudioGain"
+//#define LOG_NDEBUG 0
+
+//#define VERY_VERBOSE_LOGGING
+#ifdef VERY_VERBOSE_LOGGING
+#define ALOGVV ALOGV
+#else
+#define ALOGVV(a...) do { } while(0)
+#endif
+
+#include "AudioGain.h"
+#include "StreamDescriptor.h"
+#include <utils/Log.h>
+#include <utils/String8.h>
+
+#include <math.h>
+
+namespace android {
+
+AudioGain::AudioGain(int index, bool useInChannelMask)
+{
+ mIndex = index;
+ mUseInChannelMask = useInChannelMask;
+ memset(&mGain, 0, sizeof(struct audio_gain));
+}
+
+void AudioGain::getDefaultConfig(struct audio_gain_config *config)
+{
+ config->index = mIndex;
+ config->mode = mGain.mode;
+ config->channel_mask = mGain.channel_mask;
+ if ((mGain.mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) {
+ config->values[0] = mGain.default_value;
+ } else {
+ uint32_t numValues;
+ if (mUseInChannelMask) {
+ numValues = audio_channel_count_from_in_mask(mGain.channel_mask);
+ } else {
+ numValues = audio_channel_count_from_out_mask(mGain.channel_mask);
+ }
+ for (size_t i = 0; i < numValues; i++) {
+ config->values[i] = mGain.default_value;
+ }
+ }
+ if ((mGain.mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) {
+ config->ramp_duration_ms = mGain.min_ramp_ms;
+ }
+}
+
+status_t AudioGain::checkConfig(const struct audio_gain_config *config)
+{
+ if ((config->mode & ~mGain.mode) != 0) {
+ return BAD_VALUE;
+ }
+ if ((config->mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) {
+ if ((config->values[0] < mGain.min_value) ||
+ (config->values[0] > mGain.max_value)) {
+ return BAD_VALUE;
+ }
+ } else {
+ if ((config->channel_mask & ~mGain.channel_mask) != 0) {
+ return BAD_VALUE;
+ }
+ uint32_t numValues;
+ if (mUseInChannelMask) {
+ numValues = audio_channel_count_from_in_mask(config->channel_mask);
+ } else {
+ numValues = audio_channel_count_from_out_mask(config->channel_mask);
+ }
+ for (size_t i = 0; i < numValues; i++) {
+ if ((config->values[i] < mGain.min_value) ||
+ (config->values[i] > mGain.max_value)) {
+ return BAD_VALUE;
+ }
+ }
+ }
+ if ((config->mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) {
+ if ((config->ramp_duration_ms < mGain.min_ramp_ms) ||
+ (config->ramp_duration_ms > mGain.max_ramp_ms)) {
+ return BAD_VALUE;
+ }
+ }
+ return NO_ERROR;
+}
+
+void AudioGain::dump(int fd, int spaces, int index) const
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ snprintf(buffer, SIZE, "%*sGain %d:\n", spaces, "", index+1);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "%*s- mode: %08x\n", spaces, "", mGain.mode);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "%*s- channel_mask: %08x\n", spaces, "", mGain.channel_mask);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "%*s- min_value: %d mB\n", spaces, "", mGain.min_value);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "%*s- max_value: %d mB\n", spaces, "", mGain.max_value);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "%*s- default_value: %d mB\n", spaces, "", mGain.default_value);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "%*s- step_value: %d mB\n", spaces, "", mGain.step_value);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "%*s- min_ramp_ms: %d ms\n", spaces, "", mGain.min_ramp_ms);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "%*s- max_ramp_ms: %d ms\n", spaces, "", mGain.max_ramp_ms);
+ result.append(buffer);
+
+ write(fd, result.string(), result.size());
+}
+
+}; // namespace android
diff --git a/services/audiopolicy/managerdefault/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index f4054c8..fa66728 100644
--- a/services/audiopolicy/managerdefault/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -17,7 +17,12 @@
#define LOG_TAG "APM::AudioInputDescriptor"
//#define LOG_NDEBUG 0
-#include "AudioPolicyManager.h"
+#include "AudioInputDescriptor.h"
+#include "IOProfile.h"
+#include "AudioGain.h"
+#include "HwModule.h"
+#include <media/AudioPolicy.h>
+#include <policy.h>
namespace android {
@@ -36,9 +41,19 @@ AudioInputDescriptor::AudioInputDescriptor(const sp<IOProfile>& profile)
}
}
-void AudioInputDescriptor::toAudioPortConfig(
- struct audio_port_config *dstConfig,
- const struct audio_port_config *srcConfig) const
+void AudioInputDescriptor::setIoHandle(audio_io_handle_t ioHandle)
+{
+ mId = AudioPort::getNextUniqueId();
+ mIoHandle = ioHandle;
+}
+
+audio_module_handle_t AudioInputDescriptor::getModuleHandle() const
+{
+ return mProfile->getModuleHandle();
+}
+
+void AudioInputDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
+ const struct audio_port_config *srcConfig) const
{
ALOG_ASSERT(mProfile != 0,
"toAudioPortConfig() called on input with null profile %d", mIoHandle);
@@ -58,8 +73,7 @@ void AudioInputDescriptor::toAudioPortConfig(
dstConfig->ext.mix.usecase.source = mInputSource;
}
-void AudioInputDescriptor::toAudioPort(
- struct audio_port *port) const
+void AudioInputDescriptor::toAudioPort(struct audio_port *port) const
{
ALOG_ASSERT(mProfile != 0, "toAudioPort() called on input with null profile %d", mIoHandle);
@@ -97,4 +111,77 @@ status_t AudioInputDescriptor::dump(int fd)
return NO_ERROR;
}
+bool AudioInputCollection::isSourceActive(audio_source_t source) const
+{
+ for (size_t i = 0; i < size(); i++) {
+ const sp<AudioInputDescriptor> inputDescriptor = valueAt(i);
+ if (inputDescriptor->mRefCount == 0) {
+ continue;
+ }
+ if (inputDescriptor->mInputSource == (int)source) {
+ return true;
+ }
+ }
+ return false;
+}
+
+sp<AudioInputDescriptor> AudioInputCollection::getInputFromId(audio_port_handle_t id) const
+{
+ sp<AudioInputDescriptor> inputDesc = NULL;
+ for (size_t i = 0; i < size(); i++) {
+ inputDesc = valueAt(i);
+ if (inputDesc->mId == id) {
+ break;
+ }
+ }
+ return inputDesc;
+}
+
+uint32_t AudioInputCollection::activeInputsCount() const
+{
+ uint32_t count = 0;
+ for (size_t i = 0; i < size(); i++) {
+ const sp<AudioInputDescriptor> desc = valueAt(i);
+ if (desc->mRefCount > 0) {
+ count++;
+ }
+ }
+ return count;
+}
+
+audio_io_handle_t AudioInputCollection::getActiveInput(bool ignoreVirtualInputs)
+{
+ for (size_t i = 0; i < size(); i++) {
+ const sp<AudioInputDescriptor> input_descriptor = valueAt(i);
+ if ((input_descriptor->mRefCount > 0)
+ && (!ignoreVirtualInputs || !is_virtual_input_device(input_descriptor->mDevice))) {
+ return keyAt(i);
+ }
+ }
+ return 0;
+}
+
+audio_devices_t AudioInputCollection::getSupportedDevices(audio_io_handle_t handle) const
+{
+ sp<AudioInputDescriptor> inputDesc = valueFor(handle);
+ audio_devices_t devices = inputDesc->mProfile->mSupportedDevices.types();
+ return devices;
+}
+
+status_t AudioInputCollection::dump(int fd) const
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+
+ snprintf(buffer, SIZE, "\nInputs dump:\n");
+ write(fd, buffer, strlen(buffer));
+ for (size_t i = 0; i < size(); i++) {
+ snprintf(buffer, SIZE, "- Input %d dump:\n", keyAt(i));
+ write(fd, buffer, strlen(buffer));
+ valueAt(i)->dump(fd);
+ }
+
+ return NO_ERROR;
+}
+
}; //namespace android
diff --git a/services/audiopolicy/managerdefault/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 4b85972..cdb5b51 100644
--- a/services/audiopolicy/managerdefault/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -17,12 +17,19 @@
#define LOG_TAG "APM::AudioOutputDescriptor"
//#define LOG_NDEBUG 0
-#include "AudioPolicyManager.h"
+#include "AudioOutputDescriptor.h"
+#include "IOProfile.h"
+#include "AudioGain.h"
+#include "HwModule.h"
+#include <media/AudioPolicy.h>
+
+// A device mask for all audio output devices that are considered "remote" when evaluating
+// active output devices in isStreamActiveRemotely()
+#define APM_AUDIO_OUT_DEVICE_REMOTE_ALL AUDIO_DEVICE_OUT_REMOTE_SUBMIX
namespace android {
-AudioOutputDescriptor::AudioOutputDescriptor(
- const sp<IOProfile>& profile)
+AudioOutputDescriptor::AudioOutputDescriptor(const sp<IOProfile>& profile)
: mId(0), mIoHandle(0), mLatency(0),
mFlags((audio_output_flags_t)0), mDevice(AUDIO_DEVICE_NONE), mPolicyMix(NULL),
mPatchHandle(0),
@@ -49,6 +56,11 @@ AudioOutputDescriptor::AudioOutputDescriptor(
}
}
+audio_module_handle_t AudioOutputDescriptor::getModuleHandle() const
+{
+ return mProfile->getModuleHandle();
+}
+
audio_devices_t AudioOutputDescriptor::device() const
{
if (isDuplicated()) {
@@ -58,6 +70,12 @@ audio_devices_t AudioOutputDescriptor::device() const
}
}
+void AudioOutputDescriptor::setIoHandle(audio_io_handle_t ioHandle)
+{
+ mId = AudioPort::getNextUniqueId();
+ mIoHandle = ioHandle;
+}
+
uint32_t AudioOutputDescriptor::latency()
{
if (isDuplicated()) {
@@ -108,23 +126,15 @@ audio_devices_t AudioOutputDescriptor::supportedDevices()
bool AudioOutputDescriptor::isActive(uint32_t inPastMs) const
{
- return isStrategyActive(NUM_STRATEGIES, inPastMs);
-}
-
-bool AudioOutputDescriptor::isStrategyActive(routing_strategy strategy,
- uint32_t inPastMs,
- nsecs_t sysTime) const
-{
- if ((sysTime == 0) && (inPastMs != 0)) {
+ nsecs_t sysTime = 0;
+ if (inPastMs != 0) {
sysTime = systemTime();
}
for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) {
if (i == AUDIO_STREAM_PATCH) {
continue;
}
- if (((AudioPolicyManager::getStrategy((audio_stream_type_t)i) == strategy) ||
- (NUM_STRATEGIES == strategy)) &&
- isStreamActive((audio_stream_type_t)i, inPastMs, sysTime)) {
+ if (isStreamActive((audio_stream_type_t)i, inPastMs, sysTime)) {
return true;
}
}
@@ -132,8 +142,8 @@ bool AudioOutputDescriptor::isStrategyActive(routing_strategy strategy,
}
bool AudioOutputDescriptor::isStreamActive(audio_stream_type_t stream,
- uint32_t inPastMs,
- nsecs_t sysTime) const
+ uint32_t inPastMs,
+ nsecs_t sysTime) const
{
if (mRefCount[stream] != 0) {
return true;
@@ -216,6 +226,108 @@ status_t AudioOutputDescriptor::dump(int fd)
return NO_ERROR;
}
+bool AudioOutputCollection::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
+{
+ nsecs_t sysTime = systemTime();
+ for (size_t i = 0; i < this->size(); i++) {
+ const sp<AudioOutputDescriptor> outputDesc = this->valueAt(i);
+ if (outputDesc->isStreamActive(stream, inPastMs, sysTime)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool AudioOutputCollection::isStreamActiveRemotely(audio_stream_type_t stream,
+ uint32_t inPastMs) const
+{
+ nsecs_t sysTime = systemTime();
+ for (size_t i = 0; i < size(); i++) {
+ const sp<AudioOutputDescriptor> outputDesc = valueAt(i);
+ if (((outputDesc->device() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) &&
+ outputDesc->isStreamActive(stream, inPastMs, sysTime)) {
+ // do not consider re routing (when the output is going to a dynamic policy)
+ // as "remote playback"
+ if (outputDesc->mPolicyMix == NULL) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+audio_io_handle_t AudioOutputCollection::getA2dpOutput() const
+{
+ for (size_t i = 0; i < size(); i++) {
+ sp<AudioOutputDescriptor> outputDesc = valueAt(i);
+ if (!outputDesc->isDuplicated() && outputDesc->device() & AUDIO_DEVICE_OUT_ALL_A2DP) {
+ return this->keyAt(i);
+ }
+ }
+ return 0;
+}
+
+sp<AudioOutputDescriptor> AudioOutputCollection::getPrimaryOutput() const
+{
+ for (size_t i = 0; i < size(); i++) {
+ const sp<AudioOutputDescriptor> outputDesc = valueAt(i);
+ if (outputDesc->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) {
+ return outputDesc;
+ }
+ }
+ return NULL;
+}
+
+sp<AudioOutputDescriptor> AudioOutputCollection::getOutputFromId(audio_port_handle_t id) const
+{
+ sp<AudioOutputDescriptor> outputDesc = NULL;
+ for (size_t i = 0; i < size(); i++) {
+ outputDesc = valueAt(i);
+ if (outputDesc->mId == id) {
+ break;
+ }
+ }
+ return outputDesc;
+}
+
+bool AudioOutputCollection::isAnyOutputActive(audio_stream_type_t streamToIgnore) const
+{
+ for (size_t s = 0 ; s < AUDIO_STREAM_CNT ; s++) {
+ if (s == (size_t) streamToIgnore) {
+ continue;
+ }
+ for (size_t i = 0; i < size(); i++) {
+ const sp<AudioOutputDescriptor> outputDesc = valueAt(i);
+ if (outputDesc->mRefCount[s] != 0) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+audio_devices_t AudioOutputCollection::getSupportedDevices(audio_io_handle_t handle) const
+{
+ sp<AudioOutputDescriptor> outputDesc = valueFor(handle);
+ audio_devices_t devices = outputDesc->mProfile->mSupportedDevices.types();
+ return devices;
+}
+
+
+status_t AudioOutputCollection::dump(int fd) const
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+
+ snprintf(buffer, SIZE, "\nOutputs dump:\n");
+ write(fd, buffer, strlen(buffer));
+ for (size_t i = 0; i < size(); i++) {
+ snprintf(buffer, SIZE, "- Output %d dump:\n", keyAt(i));
+ write(fd, buffer, strlen(buffer));
+ valueAt(i)->dump(fd);
+ }
+
+ return NO_ERROR;
+}
}; //namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp
new file mode 100644
index 0000000..3a317fa
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPatch.cpp
@@ -0,0 +1,154 @@
+/*
+ * 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::AudioPatch"
+//#define LOG_NDEBUG 0
+
+#include "AudioPatch.h"
+#include "AudioGain.h"
+#include "ConfigParsingUtils.h"
+#include <cutils/log.h>
+#include <utils/String8.h>
+
+namespace android {
+
+int32_t volatile AudioPatch::mNextUniqueId = 1;
+
+AudioPatch::AudioPatch(const struct audio_patch *patch, uid_t uid) :
+ mHandle(static_cast<audio_patch_handle_t>(android_atomic_inc(&mNextUniqueId))),
+ mPatch(*patch),
+ mUid(uid),
+ mAfPatchHandle(0)
+{
+}
+
+status_t AudioPatch::dump(int fd, int spaces, int index) const
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ snprintf(buffer, SIZE, "%*sAudio patch %d:\n", spaces, "", index+1);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "%*s- handle: %2d\n", spaces, "", mHandle);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "%*s- audio flinger handle: %2d\n", spaces, "", mAfPatchHandle);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "%*s- owner uid: %2d\n", spaces, "", mUid);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "%*s- %d sources:\n", spaces, "", mPatch.num_sources);
+ result.append(buffer);
+ for (size_t i = 0; i < mPatch.num_sources; i++) {
+ if (mPatch.sources[i].type == AUDIO_PORT_TYPE_DEVICE) {
+ snprintf(buffer, SIZE, "%*s- Device ID %d %s\n", spaces + 2, "",
+ mPatch.sources[i].id, ConfigParsingUtils::enumToString(sDeviceNameToEnumTable,
+ ARRAY_SIZE(sDeviceNameToEnumTable),
+ mPatch.sources[i].ext.device.type));
+ } else {
+ snprintf(buffer, SIZE, "%*s- Mix ID %d I/O handle %d\n", spaces + 2, "",
+ mPatch.sources[i].id, mPatch.sources[i].ext.mix.handle);
+ }
+ result.append(buffer);
+ }
+ snprintf(buffer, SIZE, "%*s- %d sinks:\n", spaces, "", mPatch.num_sinks);
+ result.append(buffer);
+ for (size_t i = 0; i < mPatch.num_sinks; i++) {
+ if (mPatch.sinks[i].type == AUDIO_PORT_TYPE_DEVICE) {
+ snprintf(buffer, SIZE, "%*s- Device ID %d %s\n", spaces + 2, "",
+ mPatch.sinks[i].id, ConfigParsingUtils::enumToString(sDeviceNameToEnumTable,
+ ARRAY_SIZE(sDeviceNameToEnumTable),
+ mPatch.sinks[i].ext.device.type));
+ } else {
+ snprintf(buffer, SIZE, "%*s- Mix ID %d I/O handle %d\n", spaces + 2, "",
+ mPatch.sinks[i].id, mPatch.sinks[i].ext.mix.handle);
+ }
+ result.append(buffer);
+ }
+
+ write(fd, result.string(), result.size());
+ return NO_ERROR;
+}
+
+status_t AudioPatchCollection::addAudioPatch(audio_patch_handle_t handle,
+ const sp<AudioPatch>& patch)
+{
+ ssize_t index = indexOfKey(handle);
+
+ if (index >= 0) {
+ ALOGW("addAudioPatch() patch %d already in", handle);
+ return ALREADY_EXISTS;
+ }
+ add(handle, patch);
+ ALOGV("addAudioPatch() handle %d af handle %d num_sources %d num_sinks %d source handle %d"
+ "sink handle %d",
+ handle, patch->mAfPatchHandle, patch->mPatch.num_sources, patch->mPatch.num_sinks,
+ patch->mPatch.sources[0].id, patch->mPatch.sinks[0].id);
+ return NO_ERROR;
+}
+
+status_t AudioPatchCollection::removeAudioPatch(audio_patch_handle_t handle)
+{
+ ssize_t index = indexOfKey(handle);
+
+ if (index < 0) {
+ ALOGW("removeAudioPatch() patch %d not in", handle);
+ return ALREADY_EXISTS;
+ }
+ ALOGV("removeAudioPatch() handle %d af handle %d", handle, valueAt(index)->mAfPatchHandle);
+ removeItemsAt(index);
+ return NO_ERROR;
+}
+
+status_t AudioPatchCollection::listAudioPatches(unsigned int *num_patches,
+ struct audio_patch *patches) const
+{
+ if (num_patches == NULL || (*num_patches != 0 && patches == NULL)) {
+ return BAD_VALUE;
+ }
+ ALOGV("listAudioPatches() num_patches %d patches %p available patches %zu",
+ *num_patches, patches, size());
+ if (patches == NULL) {
+ *num_patches = 0;
+ }
+
+ size_t patchesWritten = 0;
+ size_t patchesMax = *num_patches;
+ for (size_t i = 0; i < size() && patchesWritten < patchesMax; i++) {
+ const sp<AudioPatch> patch = valueAt(i);
+ patches[patchesWritten] = patch->mPatch;
+ patches[patchesWritten++].id = patch->mHandle;
+ ALOGV("listAudioPatches() patch %zu num_sources %d num_sinks %d",
+ i, patch->mPatch.num_sources, patch->mPatch.num_sinks);
+ }
+ *num_patches = size();
+
+ ALOGV("listAudioPatches() got %zu patches needed %d", patchesWritten, *num_patches);
+ return NO_ERROR;
+}
+
+status_t AudioPatchCollection::dump(int fd) const
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ snprintf(buffer, SIZE, "\nAudio Patches:\n");
+ write(fd, buffer, strlen(buffer));
+ for (size_t i = 0; i < size(); i++) {
+ valueAt(i)->dump(fd, 2, i);
+ }
+ return NO_ERROR;
+}
+
+}; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
new file mode 100644
index 0000000..84a53eb
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -0,0 +1,193 @@
+/*
+ * 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::AudioPolicyMix"
+//#define LOG_NDEBUG 0
+
+#include "AudioPolicyMix.h"
+#include "HwModule.h"
+#include "AudioPort.h"
+#include "IOProfile.h"
+#include "AudioGain.h"
+#include <AudioOutputDescriptor.h>
+
+namespace android {
+
+void AudioPolicyMix::setOutput(sp<AudioOutputDescriptor> &output)
+{
+ mOutput = output;
+}
+
+const sp<AudioOutputDescriptor> &AudioPolicyMix::getOutput() const
+{
+ return mOutput;
+}
+
+void AudioPolicyMix::clearOutput()
+{
+ mOutput.clear();
+}
+
+void AudioPolicyMix::setMix(AudioMix &mix)
+{
+ mMix = mix;
+}
+
+android::AudioMix &AudioPolicyMix::getMix()
+{
+ return mMix;
+}
+
+status_t AudioPolicyMixCollection::registerMix(String8 address, AudioMix mix)
+{
+ ssize_t index = indexOfKey(address);
+ if (index >= 0) {
+ ALOGE("registerPolicyMixes(): mix for address %s already registered", address.string());
+ return BAD_VALUE;
+ }
+ sp<AudioPolicyMix> policyMix = new AudioPolicyMix();
+ policyMix->setMix(mix);
+ add(address, policyMix);
+ return NO_ERROR;
+}
+
+status_t AudioPolicyMixCollection::unregisterMix(String8 address)
+{
+ ssize_t index = indexOfKey(address);
+ if (index < 0) {
+ ALOGE("unregisterPolicyMixes(): mix for address %s not registered", address.string());
+ return BAD_VALUE;
+ }
+
+ removeItemsAt(index);
+ return NO_ERROR;
+}
+
+status_t AudioPolicyMixCollection::getAudioPolicyMix(String8 address,
+ sp<AudioPolicyMix> &policyMix) const
+{
+ ssize_t index = indexOfKey(address);
+ if (index < 0) {
+ ALOGE("unregisterPolicyMixes(): mix for address %s not registered", address.string());
+ return BAD_VALUE;
+ }
+ policyMix = valueAt(index);
+ return NO_ERROR;
+}
+
+void AudioPolicyMixCollection::closeOutput(sp<AudioOutputDescriptor> &desc)
+{
+ for (size_t i = 0; i < size(); i++) {
+ sp<AudioPolicyMix> policyMix = valueAt(i);
+ if (policyMix->getOutput() == desc) {
+ policyMix->clearOutput();
+ }
+ }
+}
+
+status_t AudioPolicyMixCollection::getOutputForAttr(audio_attributes_t attributes,
+ sp<AudioOutputDescriptor> &desc)
+{
+ for (size_t i = 0; i < size(); i++) {
+ sp<AudioPolicyMix> policyMix = valueAt(i);
+ AudioMix mix = policyMix->getMix();
+
+ if (mix.mMixType == MIX_TYPE_PLAYERS) {
+ for (size_t j = 0; j < mix.mCriteria.size(); j++) {
+ if ((RULE_MATCH_ATTRIBUTE_USAGE == mix.mCriteria[j].mRule &&
+ mix.mCriteria[j].mAttr.mUsage == attributes.usage) ||
+ (RULE_EXCLUDE_ATTRIBUTE_USAGE == mix.mCriteria[j].mRule &&
+ mix.mCriteria[j].mAttr.mUsage != attributes.usage)) {
+ desc = policyMix->getOutput();
+ break;
+ }
+ if (strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
+ strncmp(attributes.tags + strlen("addr="),
+ mix.mRegistrationId.string(),
+ AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
+ desc = policyMix->getOutput();
+ break;
+ }
+ }
+ } else if (mix.mMixType == MIX_TYPE_RECORDERS) {
+ if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE &&
+ strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
+ strncmp(attributes.tags + strlen("addr="),
+ mix.mRegistrationId.string(),
+ AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
+ desc = policyMix->getOutput();
+ }
+ }
+ if (desc != 0) {
+ desc->mPolicyMix = &mix;
+ return NO_ERROR;
+ }
+ }
+ return BAD_VALUE;
+}
+
+audio_devices_t AudioPolicyMixCollection::getDeviceAndMixForInputSource(audio_source_t inputSource,
+ audio_devices_t availDevices,
+ AudioMix **policyMix)
+{
+ for (size_t i = 0; i < size(); i++) {
+ AudioMix mix = valueAt(i)->getMix();
+
+ if (mix.mMixType != MIX_TYPE_RECORDERS) {
+ continue;
+ }
+ for (size_t j = 0; j < mix.mCriteria.size(); j++) {
+ if ((RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET == mix.mCriteria[j].mRule &&
+ mix.mCriteria[j].mAttr.mSource == inputSource) ||
+ (RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET == mix.mCriteria[j].mRule &&
+ mix.mCriteria[j].mAttr.mSource != inputSource)) {
+ if (availDevices & AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
+ if (policyMix != NULL) {
+ *policyMix = &mix;
+ }
+ return AUDIO_DEVICE_IN_REMOTE_SUBMIX;
+ }
+ break;
+ }
+ }
+ }
+ return AUDIO_DEVICE_NONE;
+}
+
+status_t AudioPolicyMixCollection::getInputMixForAttr(audio_attributes_t attr, AudioMix *&policyMix)
+{
+ if (strncmp(attr.tags, "addr=", strlen("addr=")) != 0) {
+ return BAD_VALUE;
+ }
+ String8 address(attr.tags + strlen("addr="));
+
+ ssize_t index = indexOfKey(address);
+ if (index < 0) {
+ ALOGW("getInputForAttr() no policy for address %s", address.string());
+ return BAD_VALUE;
+ }
+ sp<AudioPolicyMix> audioPolicyMix = valueAt(index);
+ AudioMix mix = audioPolicyMix->getMix();
+
+ if (mix.mMixType != MIX_TYPE_PLAYERS) {
+ ALOGW("getInputForAttr() bad policy mix type for address %s", address.string());
+ return BAD_VALUE;
+ }
+ policyMix = &mix;
+ return NO_ERROR;
+}
+
+}; //namespace android
diff --git a/services/audiopolicy/managerdefault/Ports.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
index 3e55cee..46a119e 100644
--- a/services/audiopolicy/managerdefault/Ports.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
@@ -14,30 +14,46 @@
* limitations under the License.
*/
-#define LOG_TAG "APM::Ports"
+#define LOG_TAG "APM::AudioPort"
//#define LOG_NDEBUG 0
-#include "AudioPolicyManager.h"
-
+#include "AudioPort.h"
+#include "HwModule.h"
+#include "AudioGain.h"
+#include "ConfigParsingUtils.h"
#include "audio_policy_conf.h"
+#include <policy.h>
namespace android {
+int32_t volatile AudioPort::mNextUniqueId = 1;
+
// --- AudioPort class implementation
AudioPort::AudioPort(const String8& name, audio_port_type_t type,
- audio_port_role_t role, const sp<HwModule>& module) :
+ audio_port_role_t role, const sp<HwModule>& module) :
mName(name), mType(type), mRole(role), mModule(module), mFlags(0), mId(0)
{
mUseInChannelMask = ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) ||
((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK));
}
-void AudioPort::attach(const sp<HwModule>& module) {
- mId = AudioPolicyManager::nextUniqueId();
+void AudioPort::attach(const sp<HwModule>& module)
+{
+ mId = getNextUniqueId();
mModule = module;
}
+audio_port_handle_t AudioPort::getNextUniqueId()
+{
+ return static_cast<audio_port_handle_t>(android_atomic_inc(&mNextUniqueId));
+}
+
+audio_module_handle_t AudioPort::getModuleHandle() const
+{
+ return mModule->mHandle;
+}
+
void AudioPort::toAudioPort(struct audio_port *port) const
{
port->role = mRole;
@@ -785,60 +801,4 @@ void AudioPortConfig::toAudioPortConfig(struct audio_port_config *dstConfig,
}
}
-
-// --- AudioPatch class implementation
-
-AudioPatch::AudioPatch(audio_patch_handle_t handle,
- const struct audio_patch *patch, uid_t uid) :
- mHandle(handle), mPatch(*patch), mUid(uid), mAfPatchHandle(0)
-{}
-
-status_t AudioPatch::dump(int fd, int spaces, int index) const
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
- snprintf(buffer, SIZE, "%*sAudio patch %d:\n", spaces, "", index+1);
- result.append(buffer);
- snprintf(buffer, SIZE, "%*s- handle: %2d\n", spaces, "", mHandle);
- result.append(buffer);
- snprintf(buffer, SIZE, "%*s- audio flinger handle: %2d\n", spaces, "", mAfPatchHandle);
- result.append(buffer);
- snprintf(buffer, SIZE, "%*s- owner uid: %2d\n", spaces, "", mUid);
- result.append(buffer);
- snprintf(buffer, SIZE, "%*s- %d sources:\n", spaces, "", mPatch.num_sources);
- result.append(buffer);
- for (size_t i = 0; i < mPatch.num_sources; i++) {
- if (mPatch.sources[i].type == AUDIO_PORT_TYPE_DEVICE) {
- snprintf(buffer, SIZE, "%*s- Device ID %d %s\n", spaces + 2, "",
- mPatch.sources[i].id, ConfigParsingUtils::enumToString(sDeviceNameToEnumTable,
- ARRAY_SIZE(sDeviceNameToEnumTable),
- mPatch.sources[i].ext.device.type));
- } else {
- snprintf(buffer, SIZE, "%*s- Mix ID %d I/O handle %d\n", spaces + 2, "",
- mPatch.sources[i].id, mPatch.sources[i].ext.mix.handle);
- }
- result.append(buffer);
- }
- snprintf(buffer, SIZE, "%*s- %d sinks:\n", spaces, "", mPatch.num_sinks);
- result.append(buffer);
- for (size_t i = 0; i < mPatch.num_sinks; i++) {
- if (mPatch.sinks[i].type == AUDIO_PORT_TYPE_DEVICE) {
- snprintf(buffer, SIZE, "%*s- Device ID %d %s\n", spaces + 2, "",
- mPatch.sinks[i].id, ConfigParsingUtils::enumToString(sDeviceNameToEnumTable,
- ARRAY_SIZE(sDeviceNameToEnumTable),
- mPatch.sinks[i].ext.device.type));
- } else {
- snprintf(buffer, SIZE, "%*s- Mix ID %d I/O handle %d\n", spaces + 2, "",
- mPatch.sinks[i].id, mPatch.sinks[i].ext.mix.handle);
- }
- result.append(buffer);
- }
-
- write(fd, result.string(), result.size());
- return NO_ERROR;
-}
-
-
}; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp b/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
new file mode 100644
index 0000000..fe5bc5f
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/src/ConfigParsingUtils.cpp
@@ -0,0 +1,288 @@
+/*
+ * 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::ConfigParsingUtils"
+//#define LOG_NDEBUG 0
+
+#include "ConfigParsingUtils.h"
+#include "AudioGain.h"
+#include <hardware/audio.h>
+#include <utils/Log.h>
+#include <cutils/misc.h>
+
+namespace android {
+
+//static
+uint32_t ConfigParsingUtils::stringToEnum(const struct StringToEnum *table,
+ size_t size,
+ const char *name)
+{
+ for (size_t i = 0; i < size; i++) {
+ if (strcmp(table[i].name, name) == 0) {
+ ALOGV("stringToEnum() found %s", table[i].name);
+ return table[i].value;
+ }
+ }
+ return 0;
+}
+
+//static
+const char *ConfigParsingUtils::enumToString(const struct StringToEnum *table,
+ size_t size,
+ uint32_t value)
+{
+ for (size_t i = 0; i < size; i++) {
+ if (table[i].value == value) {
+ return table[i].name;
+ }
+ }
+ return "";
+}
+
+//static
+bool ConfigParsingUtils::stringToBool(const char *value)
+{
+ return ((strcasecmp("true", value) == 0) || (strcmp("1", value) == 0));
+}
+
+
+// --- audio_policy.conf file parsing
+//static
+uint32_t ConfigParsingUtils::parseOutputFlagNames(char *name)
+{
+ uint32_t flag = 0;
+
+ // it is OK to cast name to non const here as we are not going to use it after
+ // strtok() modifies it
+ char *flagName = strtok(name, "|");
+ while (flagName != NULL) {
+ if (strlen(flagName) != 0) {
+ flag |= ConfigParsingUtils::stringToEnum(sOutputFlagNameToEnumTable,
+ ARRAY_SIZE(sOutputFlagNameToEnumTable),
+ flagName);
+ }
+ flagName = strtok(NULL, "|");
+ }
+ //force direct flag if offload flag is set: offloading implies a direct output stream
+ // and all common behaviors are driven by checking only the direct flag
+ // this should normally be set appropriately in the policy configuration file
+ if ((flag & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
+ flag |= AUDIO_OUTPUT_FLAG_DIRECT;
+ }
+
+ return flag;
+}
+
+//static
+uint32_t ConfigParsingUtils::parseInputFlagNames(char *name)
+{
+ uint32_t flag = 0;
+
+ // it is OK to cast name to non const here as we are not going to use it after
+ // strtok() modifies it
+ char *flagName = strtok(name, "|");
+ while (flagName != NULL) {
+ if (strlen(flagName) != 0) {
+ flag |= stringToEnum(sInputFlagNameToEnumTable,
+ ARRAY_SIZE(sInputFlagNameToEnumTable),
+ flagName);
+ }
+ flagName = strtok(NULL, "|");
+ }
+ return flag;
+}
+
+//static
+audio_devices_t ConfigParsingUtils::parseDeviceNames(char *name)
+{
+ uint32_t device = 0;
+
+ char *devName = strtok(name, "|");
+ while (devName != NULL) {
+ if (strlen(devName) != 0) {
+ device |= stringToEnum(sDeviceNameToEnumTable,
+ ARRAY_SIZE(sDeviceNameToEnumTable),
+ devName);
+ }
+ devName = strtok(NULL, "|");
+ }
+ return device;
+}
+
+//static
+void ConfigParsingUtils::loadHwModule(cnode *root, HwModuleCollection &hwModules,
+ DeviceVector &availableInputDevices,
+ DeviceVector &availableOutputDevices,
+ sp<DeviceDescriptor> &defaultOutputDevices,
+ bool &isSpeakerDrcEnable)
+{
+ status_t status = NAME_NOT_FOUND;
+ cnode *node;
+ sp<HwModule> module = new HwModule(root->name);
+
+ node = config_find(root, DEVICES_TAG);
+ if (node != NULL) {
+ node = node->first_child;
+ while (node) {
+ ALOGV("loadHwModule() loading device %s", node->name);
+ status_t tmpStatus = module->loadDevice(node);
+ if (status == NAME_NOT_FOUND || status == NO_ERROR) {
+ status = tmpStatus;
+ }
+ node = node->next;
+ }
+ }
+ node = config_find(root, OUTPUTS_TAG);
+ if (node != NULL) {
+ node = node->first_child;
+ while (node) {
+ ALOGV("loadHwModule() loading output %s", node->name);
+ status_t tmpStatus = module->loadOutput(node);
+ if (status == NAME_NOT_FOUND || status == NO_ERROR) {
+ status = tmpStatus;
+ }
+ node = node->next;
+ }
+ }
+ node = config_find(root, INPUTS_TAG);
+ if (node != NULL) {
+ node = node->first_child;
+ while (node) {
+ ALOGV("loadHwModule() loading input %s", node->name);
+ status_t tmpStatus = module->loadInput(node);
+ if (status == NAME_NOT_FOUND || status == NO_ERROR) {
+ status = tmpStatus;
+ }
+ node = node->next;
+ }
+ }
+ loadGlobalConfig(root, module, availableInputDevices, availableOutputDevices,
+ defaultOutputDevices, isSpeakerDrcEnable);
+
+ if (status == NO_ERROR) {
+ hwModules.add(module);
+ }
+}
+
+//static
+void ConfigParsingUtils::loadHwModules(cnode *root, HwModuleCollection &hwModules,
+ DeviceVector &availableInputDevices,
+ DeviceVector &availableOutputDevices,
+ sp<DeviceDescriptor> &defaultOutputDevices,
+ bool &isSpeakerDrcEnabled)
+{
+ cnode *node = config_find(root, AUDIO_HW_MODULE_TAG);
+ if (node == NULL) {
+ return;
+ }
+
+ node = node->first_child;
+ while (node) {
+ ALOGV("loadHwModules() loading module %s", node->name);
+ loadHwModule(node, hwModules, availableInputDevices, availableOutputDevices,
+ defaultOutputDevices, isSpeakerDrcEnabled);
+ node = node->next;
+ }
+}
+
+//static
+void ConfigParsingUtils::loadGlobalConfig(cnode *root, const sp<HwModule>& module,
+ DeviceVector &availableInputDevices,
+ DeviceVector &availableOutputDevices,
+ sp<DeviceDescriptor> &defaultOutputDevice,
+ bool &speakerDrcEnabled)
+{
+ cnode *node = config_find(root, GLOBAL_CONFIG_TAG);
+
+ if (node == NULL) {
+ return;
+ }
+ DeviceVector declaredDevices;
+ if (module != NULL) {
+ declaredDevices = module->mDeclaredDevices;
+ }
+
+ node = node->first_child;
+ while (node) {
+ if (strcmp(ATTACHED_OUTPUT_DEVICES_TAG, node->name) == 0) {
+ availableOutputDevices.loadDevicesFromName((char *)node->value,
+ declaredDevices);
+ ALOGV("loadGlobalConfig() Attached Output Devices %08x",
+ availableOutputDevices.types());
+ } else if (strcmp(DEFAULT_OUTPUT_DEVICE_TAG, node->name) == 0) {
+ audio_devices_t device = (audio_devices_t)stringToEnum(
+ sDeviceNameToEnumTable,
+ ARRAY_SIZE(sDeviceNameToEnumTable),
+ (char *)node->value);
+ if (device != AUDIO_DEVICE_NONE) {
+ defaultOutputDevice = new DeviceDescriptor(String8("default-output"), device);
+ } else {
+ ALOGW("loadGlobalConfig() default device not specified");
+ }
+ ALOGV("loadGlobalConfig() mDefaultOutputDevice %08x", defaultOutputDevice->type());
+ } else if (strcmp(ATTACHED_INPUT_DEVICES_TAG, node->name) == 0) {
+ availableInputDevices.loadDevicesFromName((char *)node->value,
+ declaredDevices);
+ ALOGV("loadGlobalConfig() Available InputDevices %08x", availableInputDevices.types());
+ } else if (strcmp(SPEAKER_DRC_ENABLED_TAG, node->name) == 0) {
+ speakerDrcEnabled = stringToBool((char *)node->value);
+ ALOGV("loadGlobalConfig() mSpeakerDrcEnabled = %d", speakerDrcEnabled);
+ } else if (strcmp(AUDIO_HAL_VERSION_TAG, node->name) == 0) {
+ uint32_t major, minor;
+ sscanf((char *)node->value, "%u.%u", &major, &minor);
+ module->mHalVersion = HARDWARE_DEVICE_API_VERSION(major, minor);
+ ALOGV("loadGlobalConfig() mHalVersion = %04x major %u minor %u",
+ module->mHalVersion, major, minor);
+ }
+ node = node->next;
+ }
+}
+
+//static
+status_t ConfigParsingUtils::loadAudioPolicyConfig(const char *path,
+ HwModuleCollection &hwModules,
+ DeviceVector &availableInputDevices,
+ DeviceVector &availableOutputDevices,
+ sp<DeviceDescriptor> &defaultOutputDevices,
+ bool &isSpeakerDrcEnabled)
+{
+ cnode *root;
+ char *data;
+
+ data = (char *)load_file(path, NULL);
+ if (data == NULL) {
+ return -ENODEV;
+ }
+ root = config_node("", "");
+ config_load(root, data);
+
+ loadHwModules(root, hwModules,
+ availableInputDevices, availableOutputDevices,
+ defaultOutputDevices, isSpeakerDrcEnabled);
+ // legacy audio_policy.conf files have one global_configuration section
+ loadGlobalConfig(root, hwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY),
+ availableInputDevices, availableOutputDevices,
+ defaultOutputDevices, isSpeakerDrcEnabled);
+ config_free(root);
+ free(root);
+ free(data);
+
+ ALOGI("loadAudioPolicyConfig() loaded %s\n", path);
+
+ return NO_ERROR;
+}
+
+}; // namespace android
diff --git a/services/audiopolicy/managerdefault/Devices.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index 13c8bbc..7df7d75 100644
--- a/services/audiopolicy/managerdefault/Devices.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -17,18 +17,21 @@
#define LOG_TAG "APM::Devices"
//#define LOG_NDEBUG 0
-#include "AudioPolicyManager.h"
+#include "DeviceDescriptor.h"
+#include "AudioGain.h"
+#include "HwModule.h"
+#include "ConfigParsingUtils.h"
namespace android {
String8 DeviceDescriptor::emptyNameStr = String8("");
DeviceDescriptor::DeviceDescriptor(const String8& name, audio_devices_t type) :
- AudioPort(name, AUDIO_PORT_TYPE_DEVICE,
- audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
- AUDIO_PORT_ROLE_SOURCE,
- NULL),
- mDeviceType(type), mAddress("")
+ AudioPort(name, AUDIO_PORT_TYPE_DEVICE,
+ audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
+ AUDIO_PORT_ROLE_SOURCE,
+ NULL),
+ mAddress(""), mDeviceType(type)
{
}
@@ -57,7 +60,7 @@ void DeviceVector::refreshTypes()
{
mDeviceTypes = AUDIO_DEVICE_NONE;
for(size_t i = 0; i < size(); i++) {
- mDeviceTypes |= itemAt(i)->mDeviceType;
+ mDeviceTypes |= itemAt(i)->type();
}
ALOGV("DeviceVector::refreshTypes() mDeviceTypes %08x", mDeviceTypes);
}
@@ -82,7 +85,7 @@ ssize_t DeviceVector::add(const sp<DeviceDescriptor>& item)
refreshTypes();
}
} else {
- ALOGW("DeviceVector::add device %08x already in", item->mDeviceType);
+ ALOGW("DeviceVector::add device %08x already in", item->type());
ret = -1;
}
return ret;
@@ -94,7 +97,7 @@ ssize_t DeviceVector::remove(const sp<DeviceDescriptor>& item)
ssize_t ret = indexOf(item);
if (ret < 0) {
- ALOGW("DeviceVector::remove device %08x not in", item->mDeviceType);
+ ALOGW("DeviceVector::remove device %08x not in", item->type());
} else {
ret = SortedVector::removeAt(ret);
if (ret >= 0) {
@@ -104,6 +107,17 @@ ssize_t DeviceVector::remove(const sp<DeviceDescriptor>& item)
return ret;
}
+audio_devices_t DeviceVector::getDevicesFromHwModule(audio_module_handle_t moduleHandle) const
+{
+ audio_devices_t devices = AUDIO_DEVICE_NONE;
+ for (size_t i = 0; i < size(); i++) {
+ if (itemAt(i)->getModuleHandle() == moduleHandle) {
+ devices |= itemAt(i)->type();
+ }
+ }
+ return devices;
+}
+
void DeviceVector::loadDevicesFromType(audio_devices_t types)
{
DeviceVector deviceList;
@@ -151,7 +165,7 @@ sp<DeviceDescriptor> DeviceVector::getDevice(audio_devices_t type, String8 addre
{
sp<DeviceDescriptor> device;
for (size_t i = 0; i < size(); i++) {
- if (itemAt(i)->mDeviceType == type) {
+ if (itemAt(i)->type() == type) {
if (address == "" || itemAt(i)->mAddress == address) {
device = itemAt(i);
if (itemAt(i)->mAddress == address) {
@@ -180,12 +194,16 @@ sp<DeviceDescriptor> DeviceVector::getDeviceFromId(audio_port_handle_t id) const
DeviceVector DeviceVector::getDevicesFromType(audio_devices_t type) const
{
DeviceVector devices;
+ bool isOutput = audio_is_output_devices(type);
+ type &= ~AUDIO_DEVICE_BIT_IN;
for (size_t i = 0; (i < size()) && (type != AUDIO_DEVICE_NONE); i++) {
- if (itemAt(i)->mDeviceType & type & ~AUDIO_DEVICE_BIT_IN) {
+ bool curIsOutput = audio_is_output_devices(itemAt(i)->mDeviceType);
+ audio_devices_t curType = itemAt(i)->mDeviceType & ~AUDIO_DEVICE_BIT_IN;
+ if ((isOutput == curIsOutput) && ((type & curType) != 0)) {
devices.add(itemAt(i));
- type &= ~itemAt(i)->mDeviceType;
+ type &= ~curType;
ALOGV("DeviceVector::getDevicesFromType() for type %x found %p",
- itemAt(i)->mDeviceType, itemAt(i).get());
+ itemAt(i)->type(), itemAt(i).get());
}
}
return devices;
@@ -196,7 +214,7 @@ DeviceVector DeviceVector::getDevicesFromTypeAddr(
{
DeviceVector devices;
for (size_t i = 0; i < size(); i++) {
- if (itemAt(i)->mDeviceType == type) {
+ if (itemAt(i)->type() == type) {
if (itemAt(i)->mAddress == address) {
devices.add(itemAt(i));
}
@@ -217,6 +235,26 @@ sp<DeviceDescriptor> DeviceVector::getDeviceFromName(const String8& name) const
return device;
}
+
+status_t DeviceVector::dump(int fd, const String8 &direction) const
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+
+ snprintf(buffer, SIZE, "\n Available %s devices:\n", direction.string());
+ write(fd, buffer, strlen(buffer));
+ for (size_t i = 0; i < size(); i++) {
+ itemAt(i)->dump(fd, 2, i);
+ }
+ return NO_ERROR;
+}
+
+audio_policy_dev_state_t DeviceVector::getDeviceConnectionState(const sp<DeviceDescriptor> &devDesc) const
+{
+ ssize_t index = indexOf(devDesc);
+ return index >= 0 ? AUDIO_POLICY_DEVICE_STATE_AVAILABLE : AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
+}
+
void DeviceDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig) const
{
@@ -237,7 +275,7 @@ void DeviceDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
// without the test?
// This has been demonstrated to NOT be true (at start up)
// ALOG_ASSERT(mModule != NULL);
- dstConfig->ext.device.hw_module = mModule != NULL ? mModule->mHandle : NULL;
+ dstConfig->ext.device.hw_module = mModule != 0 ? mModule->mHandle : AUDIO_IO_HANDLE_NONE;
strncpy(dstConfig->ext.device.address, mAddress.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN);
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
new file mode 100644
index 0000000..33d838d
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
@@ -0,0 +1,192 @@
+/*
+ * 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::EffectDescriptor"
+//#define LOG_NDEBUG 0
+
+#include "EffectDescriptor.h"
+#include <utils/String8.h>
+
+namespace android {
+
+status_t EffectDescriptor::dump(int fd)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ snprintf(buffer, SIZE, " I/O: %d\n", mIo);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Strategy: %d\n", mStrategy);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Session: %d\n", mSession);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Name: %s\n", mDesc.name);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " %s\n", mEnabled ? "Enabled" : "Disabled");
+ result.append(buffer);
+ write(fd, result.string(), result.size());
+
+ return NO_ERROR;
+}
+
+EffectDescriptorCollection::EffectDescriptorCollection() :
+ mTotalEffectsCpuLoad(0),
+ mTotalEffectsMemory(0)
+{
+
+}
+
+status_t EffectDescriptorCollection::registerEffect(const effect_descriptor_t *desc,
+ audio_io_handle_t io,
+ uint32_t strategy,
+ int session,
+ int id)
+{
+ if (mTotalEffectsMemory + desc->memoryUsage > getMaxEffectsMemory()) {
+ ALOGW("registerEffect() memory limit exceeded for Fx %s, Memory %d KB",
+ desc->name, desc->memoryUsage);
+ return INVALID_OPERATION;
+ }
+ mTotalEffectsMemory += desc->memoryUsage;
+ ALOGV("registerEffect() effect %s, io %d, strategy %d session %d id %d",
+ desc->name, io, strategy, session, id);
+ ALOGV("registerEffect() memory %d, total memory %d", desc->memoryUsage, mTotalEffectsMemory);
+
+ sp<EffectDescriptor> effectDesc = new EffectDescriptor();
+ memcpy (&effectDesc->mDesc, desc, sizeof(effect_descriptor_t));
+ effectDesc->mIo = io;
+ effectDesc->mStrategy = static_cast<routing_strategy>(strategy);
+ effectDesc->mSession = session;
+ effectDesc->mEnabled = false;
+
+ add(id, effectDesc);
+
+ return NO_ERROR;
+}
+
+status_t EffectDescriptorCollection::unregisterEffect(int id)
+{
+ ssize_t index = indexOfKey(id);
+ if (index < 0) {
+ ALOGW("unregisterEffect() unknown effect ID %d", id);
+ return INVALID_OPERATION;
+ }
+
+ sp<EffectDescriptor> effectDesc = valueAt(index);
+
+ setEffectEnabled(effectDesc, false);
+
+ if (mTotalEffectsMemory < effectDesc->mDesc.memoryUsage) {
+ ALOGW("unregisterEffect() memory %d too big for total %d",
+ effectDesc->mDesc.memoryUsage, mTotalEffectsMemory);
+ effectDesc->mDesc.memoryUsage = mTotalEffectsMemory;
+ }
+ mTotalEffectsMemory -= effectDesc->mDesc.memoryUsage;
+ ALOGV("unregisterEffect() effect %s, ID %d, memory %d total memory %d",
+ effectDesc->mDesc.name, id, effectDesc->mDesc.memoryUsage, mTotalEffectsMemory);
+
+ removeItem(id);
+
+ return NO_ERROR;
+}
+
+status_t EffectDescriptorCollection::setEffectEnabled(int id, bool enabled)
+{
+ ssize_t index = indexOfKey(id);
+ if (index < 0) {
+ ALOGW("unregisterEffect() unknown effect ID %d", id);
+ return INVALID_OPERATION;
+ }
+
+ return setEffectEnabled(valueAt(index), enabled);
+}
+
+
+status_t EffectDescriptorCollection::setEffectEnabled(const sp<EffectDescriptor> &effectDesc,
+ bool enabled)
+{
+ if (enabled == effectDesc->mEnabled) {
+ ALOGV("setEffectEnabled(%s) effect already %s",
+ enabled?"true":"false", enabled?"enabled":"disabled");
+ return INVALID_OPERATION;
+ }
+
+ if (enabled) {
+ if (mTotalEffectsCpuLoad + effectDesc->mDesc.cpuLoad > getMaxEffectsCpuLoad()) {
+ ALOGW("setEffectEnabled(true) CPU Load limit exceeded for Fx %s, CPU %f MIPS",
+ effectDesc->mDesc.name, (float)effectDesc->mDesc.cpuLoad/10);
+ return INVALID_OPERATION;
+ }
+ mTotalEffectsCpuLoad += effectDesc->mDesc.cpuLoad;
+ ALOGV("setEffectEnabled(true) total CPU %d", mTotalEffectsCpuLoad);
+ } else {
+ if (mTotalEffectsCpuLoad < effectDesc->mDesc.cpuLoad) {
+ ALOGW("setEffectEnabled(false) CPU load %d too high for total %d",
+ effectDesc->mDesc.cpuLoad, mTotalEffectsCpuLoad);
+ effectDesc->mDesc.cpuLoad = mTotalEffectsCpuLoad;
+ }
+ mTotalEffectsCpuLoad -= effectDesc->mDesc.cpuLoad;
+ ALOGV("setEffectEnabled(false) total CPU %d", mTotalEffectsCpuLoad);
+ }
+ effectDesc->mEnabled = enabled;
+ return NO_ERROR;
+}
+
+bool EffectDescriptorCollection::isNonOffloadableEffectEnabled()
+{
+ for (size_t i = 0; i < size(); i++) {
+ sp<EffectDescriptor> effectDesc = valueAt(i);
+ if (effectDesc->mEnabled && (effectDesc->mStrategy == STRATEGY_MEDIA) &&
+ ((effectDesc->mDesc.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) == 0)) {
+ ALOGV("isNonOffloadableEffectEnabled() non offloadable effect %s enabled on session %d",
+ effectDesc->mDesc.name, effectDesc->mSession);
+ return true;
+ }
+ }
+ return false;
+}
+
+uint32_t EffectDescriptorCollection::getMaxEffectsCpuLoad() const
+{
+ return MAX_EFFECTS_CPU_LOAD;
+}
+
+uint32_t EffectDescriptorCollection::getMaxEffectsMemory() const
+{
+ return MAX_EFFECTS_MEMORY;
+}
+
+status_t EffectDescriptorCollection::dump(int fd)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+
+ snprintf(buffer, SIZE, "\nTotal Effects CPU: %f MIPS, Total Effects memory: %d KB\n",
+ (float)mTotalEffectsCpuLoad/10, mTotalEffectsMemory);
+ write(fd, buffer, strlen(buffer));
+
+ snprintf(buffer, SIZE, "Registered effects:\n");
+ write(fd, buffer, strlen(buffer));
+ for (size_t i = 0; i < size(); i++) {
+ snprintf(buffer, SIZE, "- Effect %d dump:\n", keyAt(i));
+ write(fd, buffer, strlen(buffer));
+ valueAt(i)->dump(fd);
+ }
+ return NO_ERROR;
+}
+
+}; //namespace android
diff --git a/services/audiopolicy/managerdefault/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index a04bdc8..0097d69 100644
--- a/services/audiopolicy/managerdefault/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -17,9 +17,13 @@
#define LOG_TAG "APM::HwModule"
//#define LOG_NDEBUG 0
-#include "AudioPolicyManager.h"
+#include "HwModule.h"
+#include "IOProfile.h"
+#include "AudioGain.h"
+#include "ConfigParsingUtils.h"
#include "audio_policy_conf.h"
#include <hardware/audio.h>
+#include <policy.h>
namespace android {
@@ -138,7 +142,7 @@ status_t HwModule::loadDevice(cnode *root)
audio_devices_t type = AUDIO_DEVICE_NONE;
while (node) {
- if (strcmp(node->name, DEVICE_TYPE) == 0) {
+ if (strcmp(node->name, APM_DEVICE_TYPE) == 0) {
type = ConfigParsingUtils::parseDeviceNames((char *)node->value);
break;
}
@@ -154,7 +158,7 @@ status_t HwModule::loadDevice(cnode *root)
node = root->first_child;
while (node) {
- if (strcmp(node->name, DEVICE_ADDRESS) == 0) {
+ if (strcmp(node->name, APM_DEVICE_ADDRESS) == 0) {
deviceDesc->mAddress = String8((char *)node->value);
} else if (strcmp(node->name, CHANNELS_TAG) == 0) {
if (audio_is_input_device(type)) {
@@ -276,4 +280,92 @@ void HwModule::dump(int fd)
}
}
+sp <HwModule> HwModuleCollection::getModuleFromName(const char *name) const
+{
+ sp <HwModule> module;
+
+ for (size_t i = 0; i < size(); i++)
+ {
+ if (strcmp(itemAt(i)->mName, name) == 0) {
+ return itemAt(i);
+ }
+ }
+ return module;
+}
+
+
+sp <HwModule> HwModuleCollection::getModuleForDevice(audio_devices_t device) const
+{
+ sp <HwModule> module;
+
+ for (size_t i = 0; i < size(); i++) {
+ if (itemAt(i)->mHandle == 0) {
+ continue;
+ }
+ if (audio_is_output_device(device)) {
+ for (size_t j = 0; j < itemAt(i)->mOutputProfiles.size(); j++)
+ {
+ if (itemAt(i)->mOutputProfiles[j]->mSupportedDevices.types() & device) {
+ return itemAt(i);
+ }
+ }
+ } else {
+ for (size_t j = 0; j < itemAt(i)->mInputProfiles.size(); j++) {
+ if (itemAt(i)->mInputProfiles[j]->mSupportedDevices.types() &
+ device & ~AUDIO_DEVICE_BIT_IN) {
+ return itemAt(i);
+ }
+ }
+ }
+ }
+ return module;
+}
+
+sp<DeviceDescriptor> HwModuleCollection::getDeviceDescriptor(const audio_devices_t device,
+ const char *device_address,
+ const char *device_name) const
+{
+ String8 address = (device_address == NULL) ? String8("") : String8(device_address);
+ // handle legacy remote submix case where the address was not always specified
+ if (device_distinguishes_on_address(device) && (address.length() == 0)) {
+ address = String8("0");
+ }
+
+ for (size_t i = 0; i < size(); i++) {
+ const sp<HwModule> hwModule = itemAt(i);
+ if (hwModule->mHandle == 0) {
+ continue;
+ }
+ DeviceVector deviceList =
+ hwModule->mDeclaredDevices.getDevicesFromTypeAddr(device, address);
+ if (!deviceList.isEmpty()) {
+ return deviceList.itemAt(0);
+ }
+ deviceList = hwModule->mDeclaredDevices.getDevicesFromType(device);
+ if (!deviceList.isEmpty()) {
+ return deviceList.itemAt(0);
+ }
+ }
+
+ sp<DeviceDescriptor> devDesc =
+ new DeviceDescriptor(String8(device_name != NULL ? device_name : ""), device);
+ devDesc->mAddress = address;
+ return devDesc;
+}
+
+status_t HwModuleCollection::dump(int fd) const
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+
+ snprintf(buffer, SIZE, "\nHW Modules dump:\n");
+ write(fd, buffer, strlen(buffer));
+ for (size_t i = 0; i < size(); i++) {
+ snprintf(buffer, SIZE, "- HW Module %zu:\n", i + 1);
+ write(fd, buffer, strlen(buffer));
+ itemAt(i)->dump(fd);
+ }
+ return NO_ERROR;
+}
+
} //namespace android
diff --git a/services/audiopolicy/managerdefault/IOProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
index 538ac1a..376dd22 100644
--- a/services/audiopolicy/managerdefault/IOProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
@@ -17,7 +17,9 @@
#define LOG_TAG "APM::IOProfile"
//#define LOG_NDEBUG 0
-#include "AudioPolicyManager.h"
+#include "IOProfile.h"
+#include "HwModule.h"
+#include "AudioGain.h"
namespace android {
@@ -35,19 +37,27 @@ IOProfile::~IOProfile()
// Sampling rate, format and channel mask must be specified in order to
// get a valid a match
bool IOProfile::isCompatibleProfile(audio_devices_t device,
- String8 address,
- uint32_t samplingRate,
- uint32_t *updatedSamplingRate,
- audio_format_t format,
- audio_channel_mask_t channelMask,
- uint32_t flags) const
+ String8 address,
+ uint32_t samplingRate,
+ uint32_t *updatedSamplingRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ uint32_t flags) const
{
const bool isPlaybackThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SOURCE;
const bool isRecordThread = mType == AUDIO_PORT_TYPE_MIX && mRole == AUDIO_PORT_ROLE_SINK;
ALOG_ASSERT(isPlaybackThread != isRecordThread);
- if (device != AUDIO_DEVICE_NONE && mSupportedDevices.getDevice(device, address) == 0) {
- return false;
+
+ if (device != AUDIO_DEVICE_NONE) {
+ // just check types if multiple devices are selected
+ if (popcount(device & ~AUDIO_DEVICE_BIT_IN) > 1) {
+ if ((mSupportedDevices.types() & device) != device) {
+ return false;
+ }
+ } else if (mSupportedDevices.getDevice(device, address) == 0) {
+ return false;
+ }
}
if (samplingRate == 0) {
diff --git a/services/audiopolicy/common/managerdefinitions/src/SoundTriggerSession.cpp b/services/audiopolicy/common/managerdefinitions/src/SoundTriggerSession.cpp
new file mode 100644
index 0000000..8ca3ae0
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/src/SoundTriggerSession.cpp
@@ -0,0 +1,45 @@
+/*
+ * 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::SoundTriggerSession"
+//#define LOG_NDEBUG 0
+
+#include "SoundTriggerSession.h"
+
+
+namespace android {
+
+status_t SoundTriggerSessionCollection::acquireSession(audio_session_t session,
+ audio_io_handle_t ioHandle)
+{
+ add(session, ioHandle);
+
+ return NO_ERROR;
+}
+
+status_t SoundTriggerSessionCollection::releaseSession(audio_session_t session)
+{
+ ssize_t index = indexOfKey(session);
+ if (index < 0) {
+ ALOGW("acquireSoundTriggerSession() session %d not registered", session);
+ return BAD_VALUE;
+ }
+
+ removeItem(session);
+ return NO_ERROR;
+}
+
+}; //namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp
new file mode 100644
index 0000000..b682e2c
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp
@@ -0,0 +1,162 @@
+/*
+ * 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::Volumes"
+//#define LOG_NDEBUG 0
+
+//#define VERY_VERBOSE_LOGGING
+#ifdef VERY_VERBOSE_LOGGING
+#define ALOGVV ALOGV
+#else
+#define ALOGVV(a...) do { } while(0)
+#endif
+
+#include "StreamDescriptor.h"
+#include <utils/Log.h>
+#include <utils/String8.h>
+
+namespace android {
+
+// --- StreamDescriptor class implementation
+
+StreamDescriptor::StreamDescriptor()
+ : mIndexMin(0), mIndexMax(1), mCanBeMuted(true)
+{
+ mIndexCur.add(AUDIO_DEVICE_OUT_DEFAULT, 0);
+}
+
+int StreamDescriptor::getVolumeIndex(audio_devices_t device) const
+{
+ device = Volume::getDeviceForVolume(device);
+ // there is always a valid entry for AUDIO_DEVICE_OUT_DEFAULT
+ if (mIndexCur.indexOfKey(device) < 0) {
+ device = AUDIO_DEVICE_OUT_DEFAULT;
+ }
+ return mIndexCur.valueFor(device);
+}
+
+void StreamDescriptor::clearCurrentVolumeIndex()
+{
+ mIndexCur.clear();
+}
+
+void StreamDescriptor::addCurrentVolumeIndex(audio_devices_t device, int index)
+{
+ mIndexCur.add(device, index);
+}
+
+void StreamDescriptor::setVolumeIndexMin(int volIndexMin)
+{
+ mIndexMin = volIndexMin;
+}
+
+void StreamDescriptor::setVolumeIndexMax(int volIndexMax)
+{
+ mIndexMax = volIndexMax;
+}
+
+void StreamDescriptor::setVolumeCurvePoint(Volume::device_category deviceCategory,
+ const VolumeCurvePoint *point)
+{
+ mVolumeCurve[deviceCategory] = point;
+}
+
+void StreamDescriptor::dump(int fd) const
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ snprintf(buffer, SIZE, "%s %02d %02d ",
+ mCanBeMuted ? "true " : "false", mIndexMin, mIndexMax);
+ result.append(buffer);
+ for (size_t i = 0; i < mIndexCur.size(); i++) {
+ snprintf(buffer, SIZE, "%04x : %02d, ",
+ mIndexCur.keyAt(i),
+ mIndexCur.valueAt(i));
+ result.append(buffer);
+ }
+ result.append("\n");
+
+ write(fd, result.string(), result.size());
+}
+
+StreamDescriptorCollection::StreamDescriptorCollection()
+{
+ for (size_t stream = 0 ; stream < AUDIO_STREAM_CNT; stream++) {
+ add(static_cast<audio_stream_type_t>(stream), StreamDescriptor());
+ }
+}
+
+bool StreamDescriptorCollection::canBeMuted(audio_stream_type_t stream)
+{
+ return valueAt(stream).canBeMuted();
+}
+
+void StreamDescriptorCollection::clearCurrentVolumeIndex(audio_stream_type_t stream)
+{
+ editValueAt(stream).clearCurrentVolumeIndex();
+}
+
+void StreamDescriptorCollection::addCurrentVolumeIndex(audio_stream_type_t stream,
+ audio_devices_t device, int index)
+{
+ editValueAt(stream).addCurrentVolumeIndex(device, index);
+}
+
+void StreamDescriptorCollection::setVolumeCurvePoint(audio_stream_type_t stream,
+ Volume::device_category deviceCategory,
+ const VolumeCurvePoint *point)
+{
+ editValueAt(stream).setVolumeCurvePoint(deviceCategory, point);
+}
+
+const VolumeCurvePoint *StreamDescriptorCollection::getVolumeCurvePoint(audio_stream_type_t stream,
+ Volume::device_category deviceCategory) const
+{
+ return valueAt(stream).getVolumeCurvePoint(deviceCategory);
+}
+
+void StreamDescriptorCollection::setVolumeIndexMin(audio_stream_type_t stream,int volIndexMin)
+{
+ return editValueAt(stream).setVolumeIndexMin(volIndexMin);
+}
+
+void StreamDescriptorCollection::setVolumeIndexMax(audio_stream_type_t stream,int volIndexMax)
+{
+ return editValueAt(stream).setVolumeIndexMax(volIndexMax);
+}
+
+status_t StreamDescriptorCollection::dump(int fd) const
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+
+ snprintf(buffer, SIZE, "\nStreams dump:\n");
+ write(fd, buffer, strlen(buffer));
+ snprintf(buffer, SIZE,
+ " Stream Can be muted Index Min Index Max Index Cur [device : index]...\n");
+ write(fd, buffer, strlen(buffer));
+ for (size_t i = 0; i < size(); i++) {
+ snprintf(buffer, SIZE, " %02zu ", i);
+ write(fd, buffer, strlen(buffer));
+ valueAt(i).dump(fd);
+ }
+
+ return NO_ERROR;
+}
+
+}; // namespace android
diff --git a/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h b/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
new file mode 100755
index 0000000..eadaa77
--- /dev/null
+++ b/services/audiopolicy/engine/interface/AudioPolicyManagerInterface.h
@@ -0,0 +1,171 @@
+/*
+ * 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 <AudioPolicyManagerObserver.h>
+#include <RoutingStrategy.h>
+#include <Volume.h>
+#include <HwModule.h>
+#include <DeviceDescriptor.h>
+#include <system/audio.h>
+#include <system/audio_policy.h>
+#include <utils/Errors.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+/**
+ * This interface is dedicated to the policy manager that a Policy Engine shall implement.
+ */
+class AudioPolicyManagerInterface
+{
+public:
+ /**
+ * Checks if the engine was correctly initialized.
+ *
+ * @return NO_ERROR if initialization has been done correctly, error code otherwise..
+ */
+ virtual status_t initCheck() = 0;
+
+ /**
+ * Sets the Manager observer that allows the engine to retrieve information on collection
+ * of devices, streams, HwModules, ...
+ *
+ * @param[in] observer handle on the manager.
+ */
+ virtual void setObserver(AudioPolicyManagerObserver *observer) = 0;
+
+ /**
+ * Get the input device selected for a given input source.
+ *
+ * @param[in] inputSource to get the selected input device associated to
+ *
+ * @return selected input device for the given input source, may be none if error.
+ */
+ virtual audio_devices_t getDeviceForInputSource(audio_source_t inputSource) const = 0;
+
+ /**
+ * Get the output device associated to a given strategy.
+ *
+ * @param[in] stream type for which the selected ouput device is requested.
+ *
+ * @return selected ouput device for the given strategy, may be none if error.
+ */
+ virtual audio_devices_t getDeviceForStrategy(routing_strategy stategy) const = 0;
+
+ /**
+ * Get the strategy selected for a given stream type.
+ *
+ * @param[in] stream: for which the selected strategy followed by is requested.
+ *
+ * @return strategy to be followed.
+ */
+ virtual routing_strategy getStrategyForStream(audio_stream_type_t stream) = 0;
+
+ /**
+ * Get the strategy selected for a given usage.
+ *
+ * @param[in] usage to get the selected strategy followed by.
+ *
+ * @return strategy to be followed.
+ */
+ virtual routing_strategy getStrategyForUsage(audio_usage_t usage) = 0;
+
+ /**
+ * Set the Telephony Mode.
+ *
+ * @param[in] mode: Android Phone state (normal, ringtone, csv, in communication)
+ *
+ * @return NO_ERROR if Telephony Mode set correctly, error code otherwise.
+ */
+ virtual status_t setPhoneState(audio_mode_t mode) = 0;
+
+ /**
+ * Get the telephony Mode
+ *
+ * @return the current telephony mode
+ */
+ virtual audio_mode_t getPhoneState() const = 0;
+
+ /**
+ * Set Force Use config for a given usage.
+ *
+ * @param[in] usage for which a configuration shall be forced.
+ * @param[in] config wished to be forced for the given usage.
+ *
+ * @return NO_ERROR if the Force Use config was set correctly, error code otherwise (e.g. config not
+ * allowed a given usage...)
+ */
+ virtual status_t setForceUse(audio_policy_force_use_t usage,
+ audio_policy_forced_cfg_t config) = 0;
+
+ /**
+ * Get Force Use config for a given usage.
+ *
+ * @param[in] usage for which a configuration shall be forced.
+ *
+ * @return config wished to be forced for the given usage.
+ */
+ virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) const = 0;
+
+ /**
+ * Set the connection state of device(s).
+ *
+ * @param[in] devDesc for which the state has changed.
+ * @param[in] state of availability of this(these) device(s).
+ *
+ * @return NO_ERROR if devices criterion updated correctly, error code otherwise.
+ */
+ virtual status_t setDeviceConnectionState(const android::sp<android::DeviceDescriptor> devDesc,
+ audio_policy_dev_state_t state) = 0;
+
+ /**
+ * Translate a volume index given by the UI to an amplification value for a stream type
+ * and a device category.
+ *
+ * @param[in] deviceCategory for which the conversion is requested.
+ * @param[in] stream type for which the conversion is requested.
+ * @param[in] indexInUi index received from the UI to be translated.
+ *
+ * @return amplification value matching the UI index for this given device and stream.
+ */
+ virtual float volIndexToAmpl(Volume::device_category deviceCategory, audio_stream_type_t stream,
+ int indexInUi) = 0;
+
+ /**
+ * Initialize the min / max index of volume applicable for a given stream type. These indexes
+ * will be used upon conversion of UI index to volume amplification.
+ *
+ * @param[in] stream type for which the indexes need to be set
+ * @param[in] indexMin Minimum index allowed for this stream.
+ * @param[in] indexMax Maximum index allowed for this stream.
+ */
+ virtual status_t initStreamVolume(audio_stream_type_t stream, int indexMin, int indexMax) = 0;
+
+ /**
+ * Initialize volume curves for each strategy and device category
+ *
+ * @param[in] isSpeakerDrcEnabled true on devices that use DRC on the DEVICE_CATEGORY_SPEAKER
+ path to boost soft sounds, used to adjust volume curves accordingly
+ */
+ virtual void initializeVolumeCurves(bool isSpeakerDrcEnabled) = 0;
+
+protected:
+ virtual ~AudioPolicyManagerInterface() {}
+};
+
+}; // namespace android
diff --git a/services/audiopolicy/engine/interface/AudioPolicyManagerObserver.h b/services/audiopolicy/engine/interface/AudioPolicyManagerObserver.h
new file mode 100755
index 0000000..4f5427e
--- /dev/null
+++ b/services/audiopolicy/engine/interface/AudioPolicyManagerObserver.h
@@ -0,0 +1,62 @@
+/*
+ * 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 <AudioGain.h>
+#include <AudioPort.h>
+#include <AudioPatch.h>
+#include <IOProfile.h>
+#include <DeviceDescriptor.h>
+#include <AudioInputDescriptor.h>
+#include <AudioOutputDescriptor.h>
+#include <AudioPolicyMix.h>
+#include <SoundTriggerSession.h>
+#include <StreamDescriptor.h>
+
+namespace android {
+
+/**
+ * This interface is an observer that the manager shall implement to allows e.g. the engine
+ * to access to policy pillars elements (like output / input descritors collections,
+ * HwModule collections, AudioMix, ...
+ */
+class AudioPolicyManagerObserver
+{
+public:
+ virtual const AudioPatchCollection &getAudioPatches() const = 0;
+
+ virtual const SoundTriggerSessionCollection &getSoundTriggerSessionCollection() const = 0;
+
+ virtual const AudioPolicyMixCollection &getAudioPolicyMixCollection() const = 0;
+
+ virtual const AudioOutputCollection &getOutputs() const = 0;
+
+ virtual const AudioInputCollection &getInputs() const = 0;
+
+ virtual const DeviceVector &getAvailableOutputDevices() const = 0;
+
+ virtual const DeviceVector &getAvailableInputDevices() const = 0;
+
+ virtual StreamDescriptorCollection &getStreamDescriptors() = 0;
+
+ virtual const sp<DeviceDescriptor> &getDefaultOutputDevice() const = 0;
+
+protected:
+ virtual ~AudioPolicyManagerObserver() {}
+};
+
+}; // namespace android
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..1fd3341
--- /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
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 53ec0f6..797a2b4 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -24,20 +24,11 @@
#define ALOGVV(a...) do { } while(0)
#endif
-// A device mask for all audio input devices that are considered "virtual" when evaluating
-// active inputs in getActiveInput()
-#define APM_AUDIO_IN_DEVICE_VIRTUAL_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX|AUDIO_DEVICE_IN_FM_TUNER)
-// A device mask for all audio output devices that are considered "remote" when evaluating
-// active output devices in isStreamActiveRemotely()
-#define APM_AUDIO_OUT_DEVICE_REMOTE_ALL AUDIO_DEVICE_OUT_REMOTE_SUBMIX
-// A device mask for all audio input and output devices where matching inputs/outputs on device
-// type alone is not enough: the address must match too
-#define APM_AUDIO_DEVICE_MATCH_ADDRESS_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX | \
- AUDIO_DEVICE_OUT_REMOTE_SUBMIX)
-
#include <inttypes.h>
#include <math.h>
+#include <AudioPolicyManagerInterface.h>
+#include <AudioPolicyEngineInstance.h>
#include <cutils/properties.h>
#include <utils/Log.h>
#include <hardware/audio.h>
@@ -47,6 +38,8 @@
#include <soundtrigger/SoundTrigger.h>
#include "AudioPolicyManager.h"
#include "audio_policy_conf.h"
+#include <ConfigParsingUtils.h>
+#include <policy.h>
namespace android {
@@ -73,7 +66,8 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device,
// connect/disconnect only 1 device at a time
if (!audio_is_output_device(device) && !audio_is_input_device(device)) return BAD_VALUE;
- sp<DeviceDescriptor> devDesc = getDeviceDescriptor(device, device_address, device_name);
+ sp<DeviceDescriptor> devDesc =
+ mHwModules.getDeviceDescriptor(device, device_address, device_name);
// handle output devices
if (audio_is_output_device(device)) {
@@ -97,7 +91,7 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device,
// register new device as available
index = mAvailableOutputDevices.add(devDesc);
if (index >= 0) {
- sp<HwModule> module = getModuleForDevice(device);
+ sp<HwModule> module = mHwModules.getModuleForDevice(device);
if (module == 0) {
ALOGD("setDeviceConnectionState() could not find HW module for device %08x",
device);
@@ -113,6 +107,9 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device,
mAvailableOutputDevices.remove(devDesc);
return INVALID_OPERATION;
}
+ // Propagate device availability to Engine
+ mEngine->setDeviceConnectionState(devDesc, state);
+
// outputs should never be empty here
ALOG_ASSERT(outputs.size() != 0, "setDeviceConnectionState():"
"checkOutputsForDevice() returned no outputs but status OK");
@@ -143,6 +140,9 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device,
mAvailableOutputDevices.remove(devDesc);
checkOutputsForDevice(devDesc, state, outputs, devDesc->mAddress);
+
+ // Propagate device availability to Engine
+ mEngine->setDeviceConnectionState(devDesc, state);
} break;
default:
@@ -171,20 +171,20 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device,
}
updateDevicesAndOutputs();
- if (mPhoneState == AUDIO_MODE_IN_CALL) {
+ if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL) {
audio_devices_t newDevice = getNewOutputDevice(mPrimaryOutput, false /*fromCache*/);
updateCallRouting(newDevice);
}
for (size_t i = 0; i < mOutputs.size(); i++) {
audio_io_handle_t output = mOutputs.keyAt(i);
- if ((mPhoneState != AUDIO_MODE_IN_CALL) || (output != mPrimaryOutput)) {
+ if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (output != mPrimaryOutput)) {
audio_devices_t newDevice = getNewOutputDevice(mOutputs.keyAt(i),
true /*fromCache*/);
// do not force device change on duplicated output because if device is 0, it will
// also force a device 0 for the two outputs it is duplicated to which may override
// a valid device selection on those outputs.
bool force = !mOutputs.valueAt(i)->isDuplicated()
- && (!deviceDistinguishesOnAddress(device)
+ && (!device_distinguishes_on_address(device)
// always force when disconnecting (a non-duplicated device)
|| (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
setOutputDevice(output, newDevice, force, 0);
@@ -208,7 +208,7 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device,
ALOGW("setDeviceConnectionState() device already connected: %d", device);
return INVALID_OPERATION;
}
- sp<HwModule> module = getModuleForDevice(device);
+ sp<HwModule> module = mHwModules.getModuleForDevice(device);
if (module == NULL) {
ALOGW("setDeviceConnectionState(): could not find HW module for device %08x",
device);
@@ -230,6 +230,8 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device,
param.addInt(String8(AUDIO_PARAMETER_DEVICE_CONNECT), device);
mpClientInterface->setParameters(AUDIO_IO_HANDLE_NONE, param.toString());
+ // Propagate device availability to Engine
+ mEngine->setDeviceConnectionState(devDesc, state);
} break;
// handle input device disconnection
@@ -249,6 +251,8 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device,
checkInputsForDevice(device, state, inputs, devDesc->mAddress);
mAvailableInputDevices.remove(devDesc);
+ // Propagate device availability to Engine
+ mEngine->setDeviceConnectionState(devDesc, state);
} break;
default:
@@ -258,7 +262,7 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device,
closeAllInputs();
- if (mPhoneState == AUDIO_MODE_IN_CALL) {
+ if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL) {
audio_devices_t newDevice = getNewOutputDevice(mPrimaryOutput, false /*fromCache*/);
updateCallRouting(newDevice);
}
@@ -272,9 +276,10 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device,
}
audio_policy_dev_state_t AudioPolicyManager::getDeviceConnectionState(audio_devices_t device,
- const char *device_address)
+ const char *device_address)
{
- sp<DeviceDescriptor> devDesc = getDeviceDescriptor(device, device_address, "");
+ sp<DeviceDescriptor> devDesc = mHwModules.getDeviceDescriptor(device, device_address, "");
+
DeviceVector *deviceVector;
if (audio_is_output_device(device)) {
@@ -285,44 +290,7 @@ audio_policy_dev_state_t AudioPolicyManager::getDeviceConnectionState(audio_devi
ALOGW("getDeviceConnectionState() invalid device type %08x", device);
return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
}
-
- ssize_t index = deviceVector->indexOf(devDesc);
- if (index >= 0) {
- return AUDIO_POLICY_DEVICE_STATE_AVAILABLE;
- } else {
- return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
- }
-}
-
-sp<DeviceDescriptor> AudioPolicyManager::getDeviceDescriptor(const audio_devices_t device,
- const char *device_address,
- const char *device_name)
-{
- String8 address = (device_address == NULL) ? String8("") : String8(device_address);
- // handle legacy remote submix case where the address was not always specified
- if (deviceDistinguishesOnAddress(device) && (address.length() == 0)) {
- address = String8("0");
- }
-
- for (size_t i = 0; i < mHwModules.size(); i++) {
- if (mHwModules[i]->mHandle == 0) {
- continue;
- }
- DeviceVector deviceList =
- mHwModules[i]->mDeclaredDevices.getDevicesFromTypeAddr(device, address);
- if (!deviceList.isEmpty()) {
- return deviceList.itemAt(0);
- }
- deviceList = mHwModules[i]->mDeclaredDevices.getDevicesFromType(device);
- if (!deviceList.isEmpty()) {
- return deviceList.itemAt(0);
- }
- }
-
- sp<DeviceDescriptor> devDesc =
- new DeviceDescriptor(String8(device_name != NULL ? device_name : ""), device);
- devDesc->mAddress = address;
- return devDesc;
+ return deviceVector->getDeviceConnectionState(devDesc);
}
void AudioPolicyManager::updateCallRouting(audio_devices_t rxDevice, int delayMs)
@@ -393,8 +361,7 @@ void AudioPolicyManager::updateCallRouting(audio_devices_t rxDevice, int delayMs
ALOGW_IF(status != NO_ERROR, "updateCallRouting() error %d creating RX audio patch",
status);
if (status == NO_ERROR) {
- mCallRxPatch = new AudioPatch((audio_patch_handle_t)nextUniqueId(),
- &patch, mUidCached);
+ mCallRxPatch = new AudioPatch(&patch, mUidCached);
mCallRxPatch->mAfPatchHandle = afPatchHandle;
mCallRxPatch->mUid = mUidCached;
}
@@ -436,8 +403,7 @@ void AudioPolicyManager::updateCallRouting(audio_devices_t rxDevice, int delayMs
ALOGW_IF(status != NO_ERROR, "setPhoneState() error %d creating TX audio patch",
status);
if (status == NO_ERROR) {
- mCallTxPatch = new AudioPatch((audio_patch_handle_t)nextUniqueId(),
- &patch, mUidCached);
+ mCallTxPatch = new AudioPatch(&patch, mUidCached);
mCallTxPatch->mAfPatchHandle = afPatchHandle;
mCallTxPatch->mUid = mUidCached;
}
@@ -447,16 +413,14 @@ void AudioPolicyManager::updateCallRouting(audio_devices_t rxDevice, int delayMs
void AudioPolicyManager::setPhoneState(audio_mode_t state)
{
ALOGV("setPhoneState() state %d", state);
- if (state < 0 || state >= AUDIO_MODE_CNT) {
- ALOGW("setPhoneState() invalid state %d", state);
- return;
- }
+ // store previous phone state for management of sonification strategy below
+ int oldState = mEngine->getPhoneState();
- if (state == mPhoneState ) {
- ALOGW("setPhoneState() setting same state %d", state);
+ if (mEngine->setPhoneState(state) != NO_ERROR) {
+ ALOGW("setPhoneState() invalid or same state %d", state);
return;
}
-
+ /// Opens: can these line be executed after the switch of volume curves???
// if leaving call state, handle special case of active streams
// pertaining to sonification strategy see handleIncallSonification()
if (isInCall()) {
@@ -472,36 +436,12 @@ void AudioPolicyManager::setPhoneState(audio_mode_t state)
mpClientInterface->invalidateStream(AUDIO_STREAM_ACCESSIBILITY);
}
- // store previous phone state for management of sonification strategy below
- int oldState = mPhoneState;
- mPhoneState = state;
- bool force = false;
-
- // are we entering or starting a call
- if (!isStateInCall(oldState) && isStateInCall(state)) {
- ALOGV(" Entering call in setPhoneState()");
- // force routing command to audio hardware when starting a call
- // even if no device change is needed
- force = true;
- for (int j = 0; j < ApmGains::DEVICE_CATEGORY_CNT; j++) {
- mStreams[AUDIO_STREAM_DTMF].mVolumeCurve[j] =
- ApmGains::sVolumeProfiles[AUDIO_STREAM_VOICE_CALL][j];
- }
- } else if (isStateInCall(oldState) && !isStateInCall(state)) {
- ALOGV(" Exiting call in setPhoneState()");
- // force routing command to audio hardware when exiting a call
- // even if no device change is needed
- force = true;
- for (int j = 0; j < ApmGains::DEVICE_CATEGORY_CNT; j++) {
- mStreams[AUDIO_STREAM_DTMF].mVolumeCurve[j] =
- ApmGains::sVolumeProfiles[AUDIO_STREAM_DTMF][j];
- }
- } else if (isStateInCall(state) && (state != oldState)) {
- ALOGV(" Switching between telephony and VoIP in setPhoneState()");
- // force routing command to audio hardware when switching between telephony and VoIP
- // even if no device change is needed
- force = true;
- }
+ /**
+ * Switching to or from incall state or switching between telephony and VoIP lead to force
+ * routing command.
+ */
+ bool force = ((is_state_in_call(oldState) != is_state_in_call(state))
+ || (is_state_in_call(state) && (state != oldState)));
// check for device and output changes triggered by new phone state
checkA2dpSuspend();
@@ -518,12 +458,12 @@ void AudioPolicyManager::setPhoneState(audio_mode_t state)
// mute media and sonification strategies and delay device switch by the largest
// latency of any output where either strategy is active.
// This avoid sending the ring tone or music tail into the earpiece or headset.
- if ((desc->isStrategyActive(STRATEGY_MEDIA,
- SONIFICATION_HEADSET_MUSIC_DELAY,
- sysTime) ||
- desc->isStrategyActive(STRATEGY_SONIFICATION,
- SONIFICATION_HEADSET_MUSIC_DELAY,
- sysTime)) &&
+ if ((isStrategyActive(desc, STRATEGY_MEDIA,
+ SONIFICATION_HEADSET_MUSIC_DELAY,
+ sysTime) ||
+ isStrategyActive(desc, STRATEGY_SONIFICATION,
+ SONIFICATION_HEADSET_MUSIC_DELAY,
+ sysTime)) &&
(delayMs < (int)desc->mLatency*2)) {
delayMs = desc->mLatency*2;
}
@@ -581,84 +521,35 @@ void AudioPolicyManager::setPhoneState(audio_mode_t state)
}
}
+audio_mode_t AudioPolicyManager::getPhoneState() {
+ return mEngine->getPhoneState();
+}
+
void AudioPolicyManager::setForceUse(audio_policy_force_use_t usage,
audio_policy_forced_cfg_t config)
{
- ALOGV("setForceUse() usage %d, config %d, mPhoneState %d", usage, config, mPhoneState);
-
- bool forceVolumeReeval = false;
- 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;
- }
- forceVolumeReeval = true;
- 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;
- }
- 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;
- }
- 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);
- }
- forceVolumeReeval = true;
- 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);
- }
- forceVolumeReeval = true;
- 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;
+ ALOGV("setForceUse() usage %d, config %d, mPhoneState %d", usage, config, mEngine->getPhoneState());
+
+ if (mEngine->setForceUse(usage, config) != NO_ERROR) {
+ ALOGW("setForceUse() could not set force cfg %d for usage %d", config, usage);
+ return;
}
+ bool forceVolumeReeval = (usage == AUDIO_POLICY_FORCE_FOR_COMMUNICATION) ||
+ (usage == AUDIO_POLICY_FORCE_FOR_DOCK) ||
+ (usage == AUDIO_POLICY_FORCE_FOR_SYSTEM);
// check for device and output changes triggered by new force usage
checkA2dpSuspend();
checkOutputForAllStrategies();
updateDevicesAndOutputs();
- if (mPhoneState == AUDIO_MODE_IN_CALL) {
+ if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL) {
audio_devices_t newDevice = getNewOutputDevice(mPrimaryOutput, true /*fromCache*/);
updateCallRouting(newDevice);
}
for (size_t i = 0; i < mOutputs.size(); i++) {
audio_io_handle_t output = mOutputs.keyAt(i);
audio_devices_t newDevice = getNewOutputDevice(output, true /*fromCache*/);
- if ((mPhoneState != AUDIO_MODE_IN_CALL) || (output != mPrimaryOutput)) {
+ if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (output != mPrimaryOutput)) {
setOutputDevice(output, newDevice, (newDevice != AUDIO_DEVICE_NONE));
}
if (forceVolumeReeval && (newDevice != AUDIO_DEVICE_NONE)) {
@@ -666,18 +557,13 @@ void AudioPolicyManager::setForceUse(audio_policy_force_use_t usage,
}
}
- audio_io_handle_t activeInput = getActiveInput();
+ audio_io_handle_t activeInput = mInputs.getActiveInput();
if (activeInput != 0) {
setInputDevice(activeInput, getNewInputDevice(activeInput));
}
}
-audio_policy_forced_cfg_t AudioPolicyManager::getForceUse(audio_policy_force_use_t usage)
-{
- return mForceUse[usage];
-}
-
void AudioPolicyManager::setSystemProperty(const char* property, const char* value)
{
ALOGV("setSystemProperty() property %s, value %s", property, value);
@@ -711,11 +597,11 @@ sp<IOProfile> AudioPolicyManager::getProfileForDirectOutput(
}
audio_io_handle_t AudioPolicyManager::getOutput(audio_stream_type_t stream,
- uint32_t samplingRate,
- audio_format_t format,
- audio_channel_mask_t channelMask,
- audio_output_flags_t flags,
- const audio_offload_info_t *offloadInfo)
+ uint32_t samplingRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ audio_output_flags_t flags,
+ const audio_offload_info_t *offloadInfo)
{
routing_strategy strategy = getStrategy(stream);
audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
@@ -753,45 +639,16 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
}
stream_type_to_audio_attributes(*stream, &attributes);
}
-
- for (size_t i = 0; i < mPolicyMixes.size(); i++) {
- sp<AudioOutputDescriptor> desc;
- if (mPolicyMixes[i]->mMix.mMixType == MIX_TYPE_PLAYERS) {
- for (size_t j = 0; j < mPolicyMixes[i]->mMix.mCriteria.size(); j++) {
- if ((RULE_MATCH_ATTRIBUTE_USAGE == mPolicyMixes[i]->mMix.mCriteria[j].mRule &&
- mPolicyMixes[i]->mMix.mCriteria[j].mAttr.mUsage == attributes.usage) ||
- (RULE_EXCLUDE_ATTRIBUTE_USAGE == mPolicyMixes[i]->mMix.mCriteria[j].mRule &&
- mPolicyMixes[i]->mMix.mCriteria[j].mAttr.mUsage != attributes.usage)) {
- desc = mPolicyMixes[i]->mOutput;
- break;
- }
- if (strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
- strncmp(attributes.tags + strlen("addr="),
- mPolicyMixes[i]->mMix.mRegistrationId.string(),
- AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
- desc = mPolicyMixes[i]->mOutput;
- break;
- }
- }
- } else if (mPolicyMixes[i]->mMix.mMixType == MIX_TYPE_RECORDERS) {
- if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE &&
- strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
- strncmp(attributes.tags + strlen("addr="),
- mPolicyMixes[i]->mMix.mRegistrationId.string(),
- AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
- desc = mPolicyMixes[i]->mOutput;
- }
- }
- if (desc != 0) {
- if (!audio_is_linear_pcm(format)) {
- return BAD_VALUE;
- }
- desc->mPolicyMix = &mPolicyMixes[i]->mMix;
- *stream = streamTypefromAttributesInt(&attributes);
- *output = desc->mIoHandle;
- ALOGV("getOutputForAttr() returns output %d", *output);
- return NO_ERROR;
+ sp<AudioOutputDescriptor> desc;
+ if (mPolicyMixes.getOutputForAttr(attributes, desc) == NO_ERROR) {
+ ALOG_ASSERT(desc != 0, "Invalid desc returned by getOutputForAttr");
+ if (!audio_is_linear_pcm(format)) {
+ return BAD_VALUE;
}
+ *stream = streamTypefromAttributesInt(&attributes);
+ *output = desc->mIoHandle;
+ ALOGV("getOutputForAttr() returns output %d", *output);
+ return NO_ERROR;
}
if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE) {
ALOGW("getOutputForAttr() no policy mix found for usage AUDIO_USAGE_VIRTUAL_SOURCE");
@@ -799,7 +656,7 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
}
ALOGV("getOutputForAttr() usage=%d, content=%d, tag=%s flags=%08x",
- attributes.usage, attributes.content_type, attributes.tags, attributes.flags);
+ attributes.usage, attributes.content_type, attributes.tags, attributes.flags);
routing_strategy strategy = (routing_strategy) getStrategyForAttr(&attributes);
audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
@@ -909,7 +766,7 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevice(
// in the background.
if (((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) ||
- !isNonOffloadableEffectEnabled()) {
+ !mEffects.isNonOffloadableEffectEnabled()) {
profile = getProfileForDirectOutput(device,
samplingRate,
format,
@@ -1095,7 +952,7 @@ status_t AudioPolicyManager::startOutput(audio_io_handle_t output,
uint32_t beaconMuteLatency = 0;
if (stream == AUDIO_STREAM_TTS) {
ALOGV("\t found BEACON stream");
- if (isAnyOutputActive(AUDIO_STREAM_TTS /*streamToIgnore*/)) {
+ if (mOutputs.isAnyOutputActive(AUDIO_STREAM_TTS /*streamToIgnore*/)) {
return INVALID_OPERATION;
} else {
beaconMuteLatency = handleEventForBeacon(STARTING_BEACON);
@@ -1274,7 +1131,7 @@ void AudioPolicyManager::releaseOutput(audio_io_handle_t output,
sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(index);
if (outputDesc->isActive()) {
mpClientInterface->closeOutput(output);
- mOutputs.removeItem(output);
+ removeOutput(output);
mTestOutputs[testIndex] = 0;
}
return;
@@ -1332,19 +1189,13 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr,
if (inputSource == AUDIO_SOURCE_REMOTE_SUBMIX &&
strncmp(attr->tags, "addr=", strlen("addr=")) == 0) {
- device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
- address = String8(attr->tags + strlen("addr="));
- ssize_t index = mPolicyMixes.indexOfKey(address);
- if (index < 0) {
- ALOGW("getInputForAttr() no policy for address %s", address.string());
- return BAD_VALUE;
+ status_t ret = mPolicyMixes.getInputMixForAttr(*attr, policyMix);
+ if (ret != NO_ERROR) {
+ return ret;
}
- if (mPolicyMixes[index]->mMix.mMixType != MIX_TYPE_PLAYERS) {
- ALOGW("getInputForAttr() bad policy mix type for address %s", address.string());
- return BAD_VALUE;
- }
- policyMix = &mPolicyMixes[index]->mMix;
*inputType = API_INPUT_MIX_EXT_POLICY_REROUTE;
+ device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
+ address = String8(attr->tags + strlen("addr="));
} else {
device = getDeviceAndMixForInputSource(inputSource, &policyMix);
if (device == AUDIO_DEVICE_NONE) {
@@ -1482,10 +1333,10 @@ status_t AudioPolicyManager::startInput(audio_io_handle_t input,
}
// virtual input devices are compatible with other input devices
- if (!isVirtualInputDevice(inputDesc->mDevice)) {
+ if (!is_virtual_input_device(inputDesc->mDevice)) {
// for a non-virtual input device, check if there is another (non-virtual) active input
- audio_io_handle_t activeInput = getActiveInput();
+ audio_io_handle_t activeInput = mInputs.getActiveInput();
if (activeInput != 0 && activeInput != input) {
// If the already active input uses AUDIO_SOURCE_HOTWORD then it is closed,
@@ -1503,7 +1354,7 @@ status_t AudioPolicyManager::startInput(audio_io_handle_t input,
}
if (inputDesc->mRefCount == 0) {
- if (activeInputsCount() == 0) {
+ if (mInputs.activeInputsCount() == 0) {
SoundTrigger::setCaptureState(true);
}
setInputDevice(input, getNewInputDevice(input), true /* force */);
@@ -1575,7 +1426,7 @@ status_t AudioPolicyManager::stopInput(audio_io_handle_t input,
resetInputDevice(input);
- if (activeInputsCount() == 0) {
+ if (mInputs.activeInputsCount() == 0) {
SoundTrigger::setCaptureState(false);
}
}
@@ -1642,25 +1493,20 @@ void AudioPolicyManager::initStreamVolume(audio_stream_type_t stream,
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;
- }
- mStreams[stream].mIndexMin = indexMin;
- mStreams[stream].mIndexMax = indexMax;
+ mEngine->initStreamVolume(stream, indexMin, indexMax);
//FIXME: AUDIO_STREAM_ACCESSIBILITY volume follows AUDIO_STREAM_MUSIC for now
if (stream == AUDIO_STREAM_MUSIC) {
- mStreams[AUDIO_STREAM_ACCESSIBILITY].mIndexMin = indexMin;
- mStreams[AUDIO_STREAM_ACCESSIBILITY].mIndexMax = indexMax;
+ mEngine->initStreamVolume(AUDIO_STREAM_ACCESSIBILITY, indexMin, indexMax);
}
}
status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream,
- int index,
- audio_devices_t device)
+ int index,
+ audio_devices_t device)
{
- if ((index < mStreams[stream].mIndexMin) || (index > mStreams[stream].mIndexMax)) {
+ if ((index < mStreams[stream].getVolumeIndexMin()) ||
+ (index > mStreams[stream].getVolumeIndexMax())) {
return BAD_VALUE;
}
if (!audio_is_output_device(device)) {
@@ -1668,7 +1514,7 @@ status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream,
}
// Force max volume if stream cannot be muted
- if (!mStreams[stream].mCanBeMuted) index = mStreams[stream].mIndexMax;
+ if (!mStreams.canBeMuted(stream)) index = mStreams[stream].getVolumeIndexMax();
ALOGV("setStreamVolumeIndex() stream %d, device %04x, index %d",
stream, device, index);
@@ -1676,9 +1522,9 @@ status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream,
// if device is AUDIO_DEVICE_OUT_DEFAULT set default value and
// clear all device specific values
if (device == AUDIO_DEVICE_OUT_DEFAULT) {
- mStreams[stream].mIndexCur.clear();
+ mStreams.clearCurrentVolumeIndex(stream);
}
- mStreams[stream].mIndexCur.add(device, index);
+ mStreams.addCurrentVolumeIndex(stream, device, index);
// update volume on all outputs whose current device is also selected by the same
// strategy as the device specified by the caller
@@ -1688,7 +1534,7 @@ status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream,
//FIXME: AUDIO_STREAM_ACCESSIBILITY volume follows AUDIO_STREAM_MUSIC for now
audio_devices_t accessibilityDevice = AUDIO_DEVICE_NONE;
if (stream == AUDIO_STREAM_MUSIC) {
- mStreams[AUDIO_STREAM_ACCESSIBILITY].mIndexCur.add(device, index);
+ mStreams.addCurrentVolumeIndex(AUDIO_STREAM_ACCESSIBILITY, device, index);
accessibilityDevice = getDeviceForStrategy(STRATEGY_ACCESSIBILITY, true /*fromCache*/);
}
if ((device != AUDIO_DEVICE_OUT_DEFAULT) &&
@@ -1697,8 +1543,7 @@ status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream,
}
status_t status = NO_ERROR;
for (size_t i = 0; i < mOutputs.size(); i++) {
- audio_devices_t curDevice =
- ApmGains::getDeviceForVolume(mOutputs.valueAt(i)->device());
+ audio_devices_t curDevice = Volume::getDeviceForVolume(mOutputs.valueAt(i)->device());
if ((device == AUDIO_DEVICE_OUT_DEFAULT) || ((curDevice & strategyDevice) != 0)) {
status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt(i), curDevice);
if (volStatus != NO_ERROR) {
@@ -1728,7 +1573,7 @@ status_t AudioPolicyManager::getStreamVolumeIndex(audio_stream_type_t stream,
if (device == AUDIO_DEVICE_OUT_DEFAULT) {
device = getDeviceForStrategy(getStrategy(stream), true /*fromCache*/);
}
- device = ApmGains::getDeviceForVolume(device);
+ device = Volume::getDeviceForVolume(device);
*index = mStreams[stream].getVolumeIndex(device);
ALOGV("getStreamVolumeIndex() stream %d device %08x index %d", stream, device, *index);
@@ -1805,137 +1650,7 @@ status_t AudioPolicyManager::registerEffect(const effect_descriptor_t *desc,
return INVALID_OPERATION;
}
}
-
- if (mTotalEffectsMemory + desc->memoryUsage > getMaxEffectsMemory()) {
- ALOGW("registerEffect() memory limit exceeded for Fx %s, Memory %d KB",
- desc->name, desc->memoryUsage);
- return INVALID_OPERATION;
- }
- mTotalEffectsMemory += desc->memoryUsage;
- ALOGV("registerEffect() effect %s, io %d, strategy %d session %d id %d",
- desc->name, io, strategy, session, id);
- ALOGV("registerEffect() memory %d, total memory %d", desc->memoryUsage, mTotalEffectsMemory);
-
- sp<EffectDescriptor> effectDesc = new EffectDescriptor();
- memcpy (&effectDesc->mDesc, desc, sizeof(effect_descriptor_t));
- effectDesc->mIo = io;
- effectDesc->mStrategy = (routing_strategy)strategy;
- effectDesc->mSession = session;
- effectDesc->mEnabled = false;
-
- mEffects.add(id, effectDesc);
-
- return NO_ERROR;
-}
-
-status_t AudioPolicyManager::unregisterEffect(int id)
-{
- ssize_t index = mEffects.indexOfKey(id);
- if (index < 0) {
- ALOGW("unregisterEffect() unknown effect ID %d", id);
- return INVALID_OPERATION;
- }
-
- sp<EffectDescriptor> effectDesc = mEffects.valueAt(index);
-
- setEffectEnabled(effectDesc, false);
-
- if (mTotalEffectsMemory < effectDesc->mDesc.memoryUsage) {
- ALOGW("unregisterEffect() memory %d too big for total %d",
- effectDesc->mDesc.memoryUsage, mTotalEffectsMemory);
- effectDesc->mDesc.memoryUsage = mTotalEffectsMemory;
- }
- mTotalEffectsMemory -= effectDesc->mDesc.memoryUsage;
- ALOGV("unregisterEffect() effect %s, ID %d, memory %d total memory %d",
- effectDesc->mDesc.name, id, effectDesc->mDesc.memoryUsage, mTotalEffectsMemory);
-
- mEffects.removeItem(id);
-
- return NO_ERROR;
-}
-
-status_t AudioPolicyManager::setEffectEnabled(int id, bool enabled)
-{
- ssize_t index = mEffects.indexOfKey(id);
- if (index < 0) {
- ALOGW("unregisterEffect() unknown effect ID %d", id);
- return INVALID_OPERATION;
- }
-
- return setEffectEnabled(mEffects.valueAt(index), enabled);
-}
-
-status_t AudioPolicyManager::setEffectEnabled(const sp<EffectDescriptor>& effectDesc, bool enabled)
-{
- if (enabled == effectDesc->mEnabled) {
- ALOGV("setEffectEnabled(%s) effect already %s",
- enabled?"true":"false", enabled?"enabled":"disabled");
- return INVALID_OPERATION;
- }
-
- if (enabled) {
- if (mTotalEffectsCpuLoad + effectDesc->mDesc.cpuLoad > getMaxEffectsCpuLoad()) {
- ALOGW("setEffectEnabled(true) CPU Load limit exceeded for Fx %s, CPU %f MIPS",
- effectDesc->mDesc.name, (float)effectDesc->mDesc.cpuLoad/10);
- return INVALID_OPERATION;
- }
- mTotalEffectsCpuLoad += effectDesc->mDesc.cpuLoad;
- ALOGV("setEffectEnabled(true) total CPU %d", mTotalEffectsCpuLoad);
- } else {
- if (mTotalEffectsCpuLoad < effectDesc->mDesc.cpuLoad) {
- ALOGW("setEffectEnabled(false) CPU load %d too high for total %d",
- effectDesc->mDesc.cpuLoad, mTotalEffectsCpuLoad);
- effectDesc->mDesc.cpuLoad = mTotalEffectsCpuLoad;
- }
- mTotalEffectsCpuLoad -= effectDesc->mDesc.cpuLoad;
- ALOGV("setEffectEnabled(false) total CPU %d", mTotalEffectsCpuLoad);
- }
- effectDesc->mEnabled = enabled;
- return NO_ERROR;
-}
-
-bool AudioPolicyManager::isNonOffloadableEffectEnabled()
-{
- for (size_t i = 0; i < mEffects.size(); i++) {
- sp<EffectDescriptor> effectDesc = mEffects.valueAt(i);
- if (effectDesc->mEnabled && (effectDesc->mStrategy == STRATEGY_MEDIA) &&
- ((effectDesc->mDesc.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) == 0)) {
- ALOGV("isNonOffloadableEffectEnabled() non offloadable effect %s enabled on session %d",
- effectDesc->mDesc.name, effectDesc->mSession);
- return true;
- }
- }
- return false;
-}
-
-bool AudioPolicyManager::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
-{
- nsecs_t sysTime = systemTime();
- for (size_t i = 0; i < mOutputs.size(); i++) {
- const sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
- if (outputDesc->isStreamActive(stream, inPastMs, sysTime)) {
- return true;
- }
- }
- return false;
-}
-
-bool AudioPolicyManager::isStreamActiveRemotely(audio_stream_type_t stream,
- uint32_t inPastMs) const
-{
- nsecs_t sysTime = systemTime();
- for (size_t i = 0; i < mOutputs.size(); i++) {
- const sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
- if (((outputDesc->device() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) &&
- outputDesc->isStreamActive(stream, inPastMs, sysTime)) {
- // do not consider re routing (when the output is going to a dynamic policy)
- // as "remote playback"
- if (outputDesc->mPolicyMix == NULL) {
- return true;
- }
- }
- }
- return false;
+ return mEffects.registerEffect(desc, io, strategy, session, id);
}
bool AudioPolicyManager::isSourceActive(audio_source_t source) const
@@ -2005,9 +1720,8 @@ status_t AudioPolicyManager::registerPolicyMixes(Vector<AudioMix> mixes)
for (size_t i = 0; i < mixes.size(); i++) {
String8 address = mixes[i].mRegistrationId;
- ssize_t index = mPolicyMixes.indexOfKey(address);
- if (index >= 0) {
- ALOGE("registerPolicyMixes(): mix for address %s already registered", address.string());
+
+ if (mPolicyMixes.registerMix(address, mixes[i]) != NO_ERROR) {
continue;
}
audio_config_t outputConfig = mixes[i].mFormat;
@@ -2020,9 +1734,7 @@ status_t AudioPolicyManager::registerPolicyMixes(Vector<AudioMix> mixes)
AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address);
module->addInputProfile(address, &inputConfig,
AUDIO_DEVICE_IN_REMOTE_SUBMIX, address);
- sp<AudioPolicyMix> policyMix = new AudioPolicyMix();
- policyMix->mMix = mixes[i];
- mPolicyMixes.add(address, policyMix);
+
if (mixes[i].mMixType == MIX_TYPE_PLAYERS) {
setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
@@ -2055,14 +1767,11 @@ status_t AudioPolicyManager::unregisterPolicyMixes(Vector<AudioMix> mixes)
for (size_t i = 0; i < mixes.size(); i++) {
String8 address = mixes[i].mRegistrationId;
- ssize_t index = mPolicyMixes.indexOfKey(address);
- if (index < 0) {
- ALOGE("unregisterPolicyMixes(): mix for address %s not registered", address.string());
+
+ if (mPolicyMixes.unregisterMix(address) != NO_ERROR) {
continue;
}
- mPolicyMixes.removeItemsAt(index);
-
if (getDeviceConnectionState(AUDIO_DEVICE_IN_REMOTE_SUBMIX, address.string()) ==
AUDIO_POLICY_DEVICE_STATE_AVAILABLE)
{
@@ -2096,87 +1805,32 @@ status_t AudioPolicyManager::dump(int fd)
snprintf(buffer, SIZE, " Primary Output: %d\n", mPrimaryOutput);
result.append(buffer);
- snprintf(buffer, SIZE, " Phone state: %d\n", mPhoneState);
+ snprintf(buffer, SIZE, " Phone state: %d\n", mEngine->getPhoneState());
result.append(buffer);
snprintf(buffer, SIZE, " Force use for communications %d\n",
- mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]);
+ mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION));
result.append(buffer);
- snprintf(buffer, SIZE, " Force use for media %d\n", mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA]);
+ snprintf(buffer, SIZE, " Force use for media %d\n", mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA));
result.append(buffer);
- snprintf(buffer, SIZE, " Force use for record %d\n", mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD]);
+ snprintf(buffer, SIZE, " Force use for record %d\n", mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD));
result.append(buffer);
- snprintf(buffer, SIZE, " Force use for dock %d\n", mForceUse[AUDIO_POLICY_FORCE_FOR_DOCK]);
+ snprintf(buffer, SIZE, " Force use for dock %d\n", mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_DOCK));
result.append(buffer);
- snprintf(buffer, SIZE, " Force use for system %d\n", mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM]);
+ snprintf(buffer, SIZE, " Force use for system %d\n", mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM));
result.append(buffer);
snprintf(buffer, SIZE, " Force use for hdmi system audio %d\n",
- mForceUse[AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO]);
- result.append(buffer);
-
- snprintf(buffer, SIZE, " Available output devices:\n");
+ mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO));
result.append(buffer);
write(fd, result.string(), result.size());
- for (size_t i = 0; i < mAvailableOutputDevices.size(); i++) {
- mAvailableOutputDevices[i]->dump(fd, 2, i);
- }
- snprintf(buffer, SIZE, "\n Available input devices:\n");
- write(fd, buffer, strlen(buffer));
- for (size_t i = 0; i < mAvailableInputDevices.size(); i++) {
- mAvailableInputDevices[i]->dump(fd, 2, i);
- }
- snprintf(buffer, SIZE, "\nHW Modules dump:\n");
- write(fd, buffer, strlen(buffer));
- for (size_t i = 0; i < mHwModules.size(); i++) {
- snprintf(buffer, SIZE, "- HW Module %zu:\n", i + 1);
- write(fd, buffer, strlen(buffer));
- mHwModules[i]->dump(fd);
- }
-
- snprintf(buffer, SIZE, "\nOutputs dump:\n");
- write(fd, buffer, strlen(buffer));
- for (size_t i = 0; i < mOutputs.size(); i++) {
- snprintf(buffer, SIZE, "- Output %d dump:\n", mOutputs.keyAt(i));
- write(fd, buffer, strlen(buffer));
- mOutputs.valueAt(i)->dump(fd);
- }
-
- snprintf(buffer, SIZE, "\nInputs dump:\n");
- write(fd, buffer, strlen(buffer));
- for (size_t i = 0; i < mInputs.size(); i++) {
- snprintf(buffer, SIZE, "- Input %d dump:\n", mInputs.keyAt(i));
- write(fd, buffer, strlen(buffer));
- mInputs.valueAt(i)->dump(fd);
- }
-
- snprintf(buffer, SIZE, "\nStreams dump:\n");
- write(fd, buffer, strlen(buffer));
- snprintf(buffer, SIZE,
- " Stream Can be muted Index Min Index Max Index Cur [device : index]...\n");
- write(fd, buffer, strlen(buffer));
- for (size_t i = 0; i < AUDIO_STREAM_CNT; i++) {
- snprintf(buffer, SIZE, " %02zu ", i);
- write(fd, buffer, strlen(buffer));
- mStreams[i].dump(fd);
- }
-
- snprintf(buffer, SIZE, "\nTotal Effects CPU: %f MIPS, Total Effects memory: %d KB\n",
- (float)mTotalEffectsCpuLoad/10, mTotalEffectsMemory);
- write(fd, buffer, strlen(buffer));
-
- snprintf(buffer, SIZE, "Registered effects:\n");
- write(fd, buffer, strlen(buffer));
- for (size_t i = 0; i < mEffects.size(); i++) {
- snprintf(buffer, SIZE, "- Effect %d dump:\n", mEffects.keyAt(i));
- write(fd, buffer, strlen(buffer));
- mEffects.valueAt(i)->dump(fd);
- }
-
- snprintf(buffer, SIZE, "\nAudio Patches:\n");
- write(fd, buffer, strlen(buffer));
- for (size_t i = 0; i < mAudioPatches.size(); i++) {
- mAudioPatches[i]->dump(fd, 2, i);
- }
+ mAvailableOutputDevices.dump(fd, String8("output"));
+ mAvailableInputDevices.dump(fd, String8("input"));
+ mHwModules.dump(fd);
+ mOutputs.dump(fd);
+ mInputs.dump(fd);
+ mStreams.dump(fd);
+ mEffects.dump(fd);
+ mAudioPatches.dump(fd);
return NO_ERROR;
}
@@ -2233,7 +1887,7 @@ bool AudioPolicyManager::isOffloadSupported(const audio_offload_info_t& offloadI
// FIXME: We should check the audio session here but we do not have it in this context.
// This may prevent offloading in rare situations where effects are left active by apps
// in the background.
- if (isNonOffloadableEffectEnabled()) {
+ if (mEffects.isNonOffloadableEffectEnabled()) {
return false;
}
@@ -2312,93 +1966,6 @@ status_t AudioPolicyManager::getAudioPort(struct audio_port *port __unused)
return NO_ERROR;
}
-sp<AudioOutputDescriptor> AudioPolicyManager::getOutputFromId(
- audio_port_handle_t id) const
-{
- sp<AudioOutputDescriptor> outputDesc = NULL;
- for (size_t i = 0; i < mOutputs.size(); i++) {
- outputDesc = mOutputs.valueAt(i);
- if (outputDesc->mId == id) {
- break;
- }
- }
- return outputDesc;
-}
-
-sp<AudioInputDescriptor> AudioPolicyManager::getInputFromId(
- audio_port_handle_t id) const
-{
- sp<AudioInputDescriptor> inputDesc = NULL;
- for (size_t i = 0; i < mInputs.size(); i++) {
- inputDesc = mInputs.valueAt(i);
- if (inputDesc->mId == id) {
- break;
- }
- }
- return inputDesc;
-}
-
-sp <HwModule> AudioPolicyManager::getModuleForDevice(
- audio_devices_t device) const
-{
- sp <HwModule> module;
-
- for (size_t i = 0; i < mHwModules.size(); i++) {
- if (mHwModules[i]->mHandle == 0) {
- continue;
- }
- if (audio_is_output_device(device)) {
- for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)
- {
- if (mHwModules[i]->mOutputProfiles[j]->mSupportedDevices.types() & device) {
- return mHwModules[i];
- }
- }
- } else {
- for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++) {
- if (mHwModules[i]->mInputProfiles[j]->mSupportedDevices.types() &
- device & ~AUDIO_DEVICE_BIT_IN) {
- return mHwModules[i];
- }
- }
- }
- }
- return module;
-}
-
-sp <HwModule> AudioPolicyManager::getModuleFromName(const char *name) const
-{
- sp <HwModule> module;
-
- for (size_t i = 0; i < mHwModules.size(); i++)
- {
- if (strcmp(mHwModules[i]->mName, name) == 0) {
- return mHwModules[i];
- }
- }
- return module;
-}
-
-audio_devices_t AudioPolicyManager::availablePrimaryOutputDevices()
-{
- sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(mPrimaryOutput);
- audio_devices_t devices = outputDesc->mProfile->mSupportedDevices.types();
- return devices & mAvailableOutputDevices.types();
-}
-
-audio_devices_t AudioPolicyManager::availablePrimaryInputDevices()
-{
- audio_module_handle_t primaryHandle =
- mOutputs.valueFor(mPrimaryOutput)->mProfile->mModule->mHandle;
- audio_devices_t devices = AUDIO_DEVICE_NONE;
- for (size_t i = 0; i < mAvailableInputDevices.size(); i++) {
- if (mAvailableInputDevices[i]->mModule->mHandle == primaryHandle) {
- devices |= mAvailableInputDevices[i]->mDeviceType;
- }
- }
- return devices;
-}
-
status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch,
audio_patch_handle_t *handle,
uid_t uid)
@@ -2454,7 +2021,7 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch,
}
if (patch->sources[0].type == AUDIO_PORT_TYPE_MIX) {
- sp<AudioOutputDescriptor> outputDesc = getOutputFromId(patch->sources[0].id);
+ sp<AudioOutputDescriptor> outputDesc = mOutputs.getOutputFromId(patch->sources[0].id);
if (outputDesc == NULL) {
ALOGV("createAudioPatch() output not found for id %d", patch->sources[0].id);
return BAD_VALUE;
@@ -2483,15 +2050,14 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch,
return BAD_VALUE;
}
- if (!outputDesc->mProfile->isCompatibleProfile(devDesc->mDeviceType,
+ if (!outputDesc->mProfile->isCompatibleProfile(devDesc->type(),
devDesc->mAddress,
patch->sources[0].sample_rate,
- NULL, // updatedSamplingRate
- patch->sources[0].format,
- patch->sources[0].channel_mask,
- AUDIO_OUTPUT_FLAG_NONE /*FIXME*/)) {
- ALOGV("createAudioPatch() profile not supported for device %08x",
- devDesc->mDeviceType);
+ NULL, // updatedSamplingRate
+ patch->sources[0].format,
+ patch->sources[0].channel_mask,
+ AUDIO_OUTPUT_FLAG_NONE /*FIXME*/)) {
+ ALOGV("createAudioPatch() profile not supported for device %08x", devDesc->type());
return INVALID_OPERATION;
}
devices.add(devDesc);
@@ -2523,7 +2089,7 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch,
if (patch->num_sinks > 1) {
return INVALID_OPERATION;
}
- sp<AudioInputDescriptor> inputDesc = getInputFromId(patch->sinks[0].id);
+ sp<AudioInputDescriptor> inputDesc = mInputs.getInputFromId(patch->sinks[0].id);
if (inputDesc == NULL) {
return BAD_VALUE;
}
@@ -2538,7 +2104,7 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch,
return BAD_VALUE;
}
- if (!inputDesc->mProfile->isCompatibleProfile(devDesc->mDeviceType,
+ if (!inputDesc->mProfile->isCompatibleProfile(devDesc->type(),
devDesc->mAddress,
patch->sinks[0].sample_rate,
NULL, /*updatedSampleRate*/
@@ -2552,8 +2118,8 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch,
}
// TODO: reconfigure output format and channels here
ALOGV("createAudioPatch() setting device %08x on output %d",
- devDesc->mDeviceType, inputDesc->mIoHandle);
- setInputDevice(inputDesc->mIoHandle, devDesc->mDeviceType, true, handle);
+ devDesc->type(), inputDesc->mIoHandle);
+ setInputDevice(inputDesc->mIoHandle, devDesc->type(), true, handle);
index = mAudioPatches.indexOfKey(*handle);
if (index >= 0) {
if (patchDesc != 0 && patchDesc != mAudioPatches.valueAt(index)) {
@@ -2603,8 +2169,7 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch,
return INVALID_OPERATION;
}
SortedVector<audio_io_handle_t> outputs =
- getOutputsForDevice(sinkDeviceDesc->mDeviceType,
- mOutputs);
+ getOutputsForDevice(sinkDeviceDesc->type(), mOutputs);
// if the sink device is reachable via an opened output stream, request to go via
// this output stream by adding a second source to the patch description
audio_io_handle_t output = selectOutput(outputs,
@@ -2634,8 +2199,7 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch,
status, afPatchHandle);
if (status == NO_ERROR) {
if (index < 0) {
- patchDesc = new AudioPatch((audio_patch_handle_t)nextUniqueId(),
- &newPatch, uid);
+ patchDesc = new AudioPatch(&newPatch, uid);
addAudioPatch(patchDesc->mHandle, patchDesc);
} else {
patchDesc->mPatch = newPatch;
@@ -2678,7 +2242,7 @@ status_t AudioPolicyManager::releaseAudioPatch(audio_patch_handle_t handle,
struct audio_patch *patch = &patchDesc->mPatch;
patchDesc->mUid = mUidCached;
if (patch->sources[0].type == AUDIO_PORT_TYPE_MIX) {
- sp<AudioOutputDescriptor> outputDesc = getOutputFromId(patch->sources[0].id);
+ sp<AudioOutputDescriptor> outputDesc = mOutputs.getOutputFromId(patch->sources[0].id);
if (outputDesc == NULL) {
ALOGV("releaseAudioPatch() output not found for id %d", patch->sources[0].id);
return BAD_VALUE;
@@ -2691,7 +2255,7 @@ status_t AudioPolicyManager::releaseAudioPatch(audio_patch_handle_t handle,
NULL);
} else if (patch->sources[0].type == AUDIO_PORT_TYPE_DEVICE) {
if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) {
- sp<AudioInputDescriptor> inputDesc = getInputFromId(patch->sinks[0].id);
+ sp<AudioInputDescriptor> inputDesc = mInputs.getInputFromId(patch->sinks[0].id);
if (inputDesc == NULL) {
ALOGV("releaseAudioPatch() input not found for id %d", patch->sinks[0].id);
return BAD_VALUE;
@@ -2721,30 +2285,11 @@ status_t AudioPolicyManager::listAudioPatches(unsigned int *num_patches,
struct audio_patch *patches,
unsigned int *generation)
{
- if (num_patches == NULL || (*num_patches != 0 && patches == NULL) ||
- generation == NULL) {
+ if (generation == NULL) {
return BAD_VALUE;
}
- ALOGV("listAudioPatches() num_patches %d patches %p available patches %zu",
- *num_patches, patches, mAudioPatches.size());
- if (patches == NULL) {
- *num_patches = 0;
- }
-
- size_t patchesWritten = 0;
- size_t patchesMax = *num_patches;
- for (size_t i = 0;
- i < mAudioPatches.size() && patchesWritten < patchesMax; i++) {
- patches[patchesWritten] = mAudioPatches[i]->mPatch;
- patches[patchesWritten++].id = mAudioPatches[i]->mHandle;
- ALOGV("listAudioPatches() patch %zu num_sources %d num_sinks %d",
- i, mAudioPatches[i]->mPatch.num_sources, mAudioPatches[i]->mPatch.num_sinks);
- }
- *num_patches = mAudioPatches.size();
-
*generation = curAudioPortGeneration();
- ALOGV("listAudioPatches() got %zu patches needed %d", patchesWritten, *num_patches);
- return NO_ERROR;
+ return mAudioPatches.listAudioPatches(num_patches, patches);
}
status_t AudioPolicyManager::setAudioPortConfig(const struct audio_port_config *config)
@@ -2763,7 +2308,7 @@ status_t AudioPolicyManager::setAudioPortConfig(const struct audio_port_config *
sp<AudioPortConfig> audioPortConfig;
if (config->type == AUDIO_PORT_TYPE_MIX) {
if (config->role == AUDIO_PORT_ROLE_SOURCE) {
- sp<AudioOutputDescriptor> outputDesc = getOutputFromId(config->id);
+ sp<AudioOutputDescriptor> outputDesc = mOutputs.getOutputFromId(config->id);
if (outputDesc == NULL) {
return BAD_VALUE;
}
@@ -2772,7 +2317,7 @@ status_t AudioPolicyManager::setAudioPortConfig(const struct audio_port_config *
outputDesc->mIoHandle);
audioPortConfig = outputDesc;
} else if (config->role == AUDIO_PORT_ROLE_SINK) {
- sp<AudioInputDescriptor> inputDesc = getInputFromId(config->id);
+ sp<AudioInputDescriptor> inputDesc = mInputs.getInputFromId(config->id);
if (inputDesc == NULL) {
return BAD_VALUE;
}
@@ -2829,79 +2374,24 @@ status_t AudioPolicyManager::acquireSoundTriggerSession(audio_session_t *session
*ioHandle = (audio_io_handle_t)mpClientInterface->newAudioUniqueId();
*device = getDeviceAndMixForInputSource(AUDIO_SOURCE_HOTWORD);
- mSoundTriggerSessions.add(*session, *ioHandle);
-
- return NO_ERROR;
-}
-
-status_t AudioPolicyManager::releaseSoundTriggerSession(audio_session_t session)
-{
- ssize_t index = mSoundTriggerSessions.indexOfKey(session);
- if (index < 0) {
- ALOGW("acquireSoundTriggerSession() session %d not registered", session);
- return BAD_VALUE;
- }
-
- mSoundTriggerSessions.removeItem(session);
- return NO_ERROR;
-}
-
-status_t AudioPolicyManager::addAudioPatch(audio_patch_handle_t handle,
- const sp<AudioPatch>& patch)
-{
- ssize_t index = mAudioPatches.indexOfKey(handle);
-
- if (index >= 0) {
- ALOGW("addAudioPatch() patch %d already in", handle);
- return ALREADY_EXISTS;
- }
- mAudioPatches.add(handle, patch);
- ALOGV("addAudioPatch() handle %d af handle %d num_sources %d num_sinks %d source handle %d"
- "sink handle %d",
- handle, patch->mAfPatchHandle, patch->mPatch.num_sources, patch->mPatch.num_sinks,
- patch->mPatch.sources[0].id, patch->mPatch.sinks[0].id);
- return NO_ERROR;
-}
-
-status_t AudioPolicyManager::removeAudioPatch(audio_patch_handle_t handle)
-{
- ssize_t index = mAudioPatches.indexOfKey(handle);
-
- if (index < 0) {
- ALOGW("removeAudioPatch() patch %d not in", handle);
- return ALREADY_EXISTS;
- }
- ALOGV("removeAudioPatch() handle %d af handle %d", handle,
- mAudioPatches.valueAt(index)->mAfPatchHandle);
- mAudioPatches.removeItemsAt(index);
- return NO_ERROR;
+ return mSoundTriggerSessions.acquireSession(*session, *ioHandle);
}
// ----------------------------------------------------------------------------
// AudioPolicyManager
// ----------------------------------------------------------------------------
-
-uint32_t AudioPolicyManager::nextUniqueId()
-{
- return android_atomic_inc(&mNextUniqueId);
-}
-
uint32_t AudioPolicyManager::nextAudioPortGeneration()
{
return android_atomic_inc(&mAudioPortGeneration);
}
-int32_t volatile AudioPolicyManager::mNextUniqueId = 1;
-
AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
:
#ifdef AUDIO_POLICY_TEST
Thread(false),
#endif //AUDIO_POLICY_TEST
mPrimaryOutput((audio_io_handle_t)0),
- mPhoneState(AUDIO_MODE_NORMAL),
mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
- mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0),
mA2dpSuspended(false),
mSpeakerDrcEnabled(false),
mAudioPortGeneration(1),
@@ -2909,24 +2399,39 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa
mBeaconPlayingRefCount(0),
mBeaconMuted(false)
{
+ audio_policy::EngineInstance *engineInstance = audio_policy::EngineInstance::getInstance();
+ if (!engineInstance) {
+ ALOGE("%s: Could not get an instance of policy engine", __FUNCTION__);
+ return;
+ }
+ // Retrieve the Policy Manager Interface
+ mEngine = engineInstance->queryInterface<AudioPolicyManagerInterface>();
+ if (mEngine == NULL) {
+ ALOGE("%s: Failed to get Policy Engine Interface", __FUNCTION__);
+ return;
+ }
+ mEngine->setObserver(this);
+ status_t status = mEngine->initCheck();
+ ALOG_ASSERT(status == NO_ERROR, "Policy engine not initialized(err=%d)", status);
+
mUidCached = getuid();
mpClientInterface = clientInterface;
- for (int i = 0; i < AUDIO_POLICY_FORCE_USE_CNT; i++) {
- mForceUse[i] = AUDIO_POLICY_FORCE_NONE;
- }
-
mDefaultOutputDevice = new DeviceDescriptor(String8("Speaker"), AUDIO_DEVICE_OUT_SPEAKER);
- if (loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE) != NO_ERROR) {
- if (loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE) != NO_ERROR) {
+ if (ConfigParsingUtils::loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE,
+ mHwModules, mAvailableInputDevices, mAvailableOutputDevices,
+ mDefaultOutputDevice, mSpeakerDrcEnabled) != NO_ERROR) {
+ if (ConfigParsingUtils::loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE,
+ mHwModules, mAvailableInputDevices, mAvailableOutputDevices,
+ mDefaultOutputDevice, mSpeakerDrcEnabled) != NO_ERROR) {
ALOGE("could not load audio policy configuration file, setting defaults");
defaultAudioPolicyConfig();
}
}
// mAvailableOutputDevices and mAvailableInputDevices now contain all attached devices
- // must be done after reading the policy
- initializeVolumeCurves();
+ // must be done after reading the policy (since conditionned by Speaker Drc Enabling)
+ mEngine->initializeVolumeCurves(mSpeakerDrcEnabled);
// open all output streams needed to access attached devices
audio_devices_t outputDeviceTypes = mAvailableOutputDevices.types();
@@ -2954,13 +2459,13 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa
continue;
}
audio_devices_t profileType = outProfile->mSupportedDevices.types();
- if ((profileType & mDefaultOutputDevice->mDeviceType) != AUDIO_DEVICE_NONE) {
- profileType = mDefaultOutputDevice->mDeviceType;
+ if ((profileType & mDefaultOutputDevice->type()) != AUDIO_DEVICE_NONE) {
+ profileType = mDefaultOutputDevice->type();
} else {
// chose first device present in mSupportedDevices also part of
// outputDeviceTypes
for (size_t k = 0; k < outProfile->mSupportedDevices.size(); k++) {
- profileType = outProfile->mSupportedDevices[k]->mDeviceType;
+ profileType = outProfile->mSupportedDevices[k]->type();
if ((profileType & outputDeviceTypes) != 0) {
break;
}
@@ -2995,7 +2500,7 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa
outputDesc->mFormat = config.format;
for (size_t k = 0; k < outProfile->mSupportedDevices.size(); k++) {
- audio_devices_t type = outProfile->mSupportedDevices[k]->mDeviceType;
+ audio_devices_t type = outProfile->mSupportedDevices[k]->type();
ssize_t index =
mAvailableOutputDevices.indexOf(outProfile->mSupportedDevices[k]);
// give a valid ID to an attached device once confirmed it is reachable
@@ -3027,7 +2532,7 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa
// inputDeviceTypes
audio_devices_t profileType = AUDIO_DEVICE_NONE;
for (size_t k = 0; k < inProfile->mSupportedDevices.size(); k++) {
- profileType = inProfile->mSupportedDevices[k]->mDeviceType;
+ profileType = inProfile->mSupportedDevices[k]->type();
if (profileType & inputDeviceTypes) {
break;
}
@@ -3063,7 +2568,7 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa
if (status == NO_ERROR) {
for (size_t k = 0; k < inProfile->mSupportedDevices.size(); k++) {
- audio_devices_t type = inProfile->mSupportedDevices[k]->mDeviceType;
+ audio_devices_t type = inProfile->mSupportedDevices[k]->type();
ssize_t index =
mAvailableInputDevices.indexOf(inProfile->mSupportedDevices[k]);
// give a valid ID to an attached device once confirmed it is reachable
@@ -3082,23 +2587,29 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa
// make sure all attached devices have been allocated a unique ID
for (size_t i = 0; i < mAvailableOutputDevices.size();) {
if (!mAvailableOutputDevices[i]->isAttached()) {
- ALOGW("Input device %08x unreachable", mAvailableOutputDevices[i]->mDeviceType);
+ ALOGW("Input device %08x unreachable", mAvailableOutputDevices[i]->type());
mAvailableOutputDevices.remove(mAvailableOutputDevices[i]);
continue;
}
+ // The device is now validated and can be appended to the available devices of the engine
+ mEngine->setDeviceConnectionState(mAvailableOutputDevices[i],
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
i++;
}
for (size_t i = 0; i < mAvailableInputDevices.size();) {
if (!mAvailableInputDevices[i]->isAttached()) {
- ALOGW("Input device %08x unreachable", mAvailableInputDevices[i]->mDeviceType);
+ ALOGW("Input device %08x unreachable", mAvailableInputDevices[i]->type());
mAvailableInputDevices.remove(mAvailableInputDevices[i]);
continue;
}
+ // The device is now validated and can be appended to the available devices of the engine
+ mEngine->setDeviceConnectionState(mAvailableInputDevices[i],
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
i++;
}
// make sure default device is reachable
if (mAvailableOutputDevices.indexOf(mDefaultOutputDevice) < 0) {
- ALOGE("Default device %08x is unreachable", mDefaultOutputDevice->mDeviceType);
+ ALOGE("Default device %08x is unreachable", mDefaultOutputDevice->type());
}
ALOGE_IF((mPrimaryOutput == 0), "Failed to open primary output");
@@ -3254,8 +2765,7 @@ bool AudioPolicyManager::threadLoop()
audio_module_handle_t moduleHandle = outputDesc->mModule->mHandle;
- mOutputs.removeItem(mPrimaryOutput);
-
+ removeOutput(mPrimaryOutput);
sp<AudioOutputDescriptor> outputDesc = new AudioOutputDescriptor(NULL);
outputDesc->mDevice = AUDIO_DEVICE_OUT_SPEAKER;
audio_config_t config = AUDIO_CONFIG_INITIALIZER;
@@ -3314,16 +2824,19 @@ int AudioPolicyManager::testOutputIndex(audio_io_handle_t output)
void AudioPolicyManager::addOutput(audio_io_handle_t output, sp<AudioOutputDescriptor> outputDesc)
{
- outputDesc->mIoHandle = output;
- outputDesc->mId = nextUniqueId();
+ outputDesc->setIoHandle(output);
mOutputs.add(output, outputDesc);
nextAudioPortGeneration();
}
+void AudioPolicyManager::removeOutput(audio_io_handle_t output)
+{
+ mOutputs.removeItem(output);
+}
+
void AudioPolicyManager::addInput(audio_io_handle_t input, sp<AudioInputDescriptor> inputDesc)
{
- inputDesc->mIoHandle = input;
- inputDesc->mId = nextUniqueId();
+ inputDesc->setIoHandle(input);
mInputs.add(input, inputDesc);
nextAudioPortGeneration();
}
@@ -3342,11 +2855,11 @@ void AudioPolicyManager::findIoHandlesByAddress(sp<AudioOutputDescriptor> desc /
}
status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> devDesc,
- audio_policy_dev_state_t state,
- SortedVector<audio_io_handle_t>& outputs,
- const String8 address)
+ audio_policy_dev_state_t state,
+ SortedVector<audio_io_handle_t>& outputs,
+ const String8 address)
{
- audio_devices_t device = devDesc->mDeviceType;
+ audio_devices_t device = devDesc->type();
sp<AudioOutputDescriptor> desc;
// erase all current sample rates, formats and channel masks
devDesc->clearCapabilities();
@@ -3356,7 +2869,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> de
for (size_t i = 0; i < mOutputs.size(); i++) {
desc = mOutputs.valueAt(i);
if (!desc->isDuplicated() && (desc->mProfile->mSupportedDevices.types() & device)) {
- if (!deviceDistinguishesOnAddress(device)) {
+ if (!device_distinguishes_on_address(device)) {
ALOGV("checkOutputsForDevice(): adding opened output %d", mOutputs.keyAt(i));
outputs.add(mOutputs.keyAt(i));
} else {
@@ -3376,7 +2889,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> de
{
sp<IOProfile> profile = mHwModules[i]->mOutputProfiles[j];
if (profile->mSupportedDevices.types() & device) {
- if (!deviceDistinguishesOnAddress(device) ||
+ if (!device_distinguishes_on_address(device) ||
address == profile->mSupportedDevices[0]->mAddress) {
profiles.add(profile);
ALOGV("checkOutputsForDevice(): adding profile %zu from module %zu", j, i);
@@ -3512,15 +3025,15 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> de
if (output != AUDIO_IO_HANDLE_NONE) {
addOutput(output, desc);
- if (deviceDistinguishesOnAddress(device) && address != "0") {
- ssize_t index = mPolicyMixes.indexOfKey(address);
- if (index >= 0) {
- mPolicyMixes[index]->mOutput = desc;
- desc->mPolicyMix = &mPolicyMixes[index]->mMix;
- } else {
+ if (device_distinguishes_on_address(device) && address != "0") {
+ sp<AudioPolicyMix> policyMix;
+ if (mPolicyMixes.getAudioPolicyMix(address, policyMix) != NO_ERROR) {
ALOGE("checkOutputsForDevice() cannot find policy for address %s",
address.string());
}
+ policyMix->setOutput(desc);
+ desc->mPolicyMix = &(policyMix->getMix());
+
} else if ((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) {
// no duplicated output for direct outputs and
// outputs used by dynamic policy mixes
@@ -3550,7 +3063,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> de
ALOGW("checkOutputsForDevice() could not open dup output for %d and %d",
mPrimaryOutput, output);
mpClientInterface->closeOutput(output);
- mOutputs.removeItem(output);
+ removeOutput(output);
nextAudioPortGeneration();
output = AUDIO_IO_HANDLE_NONE;
}
@@ -3567,7 +3080,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> de
outputs.add(output);
devDesc->importAudioPort(profile);
- if (deviceDistinguishesOnAddress(device)) {
+ if (device_distinguishes_on_address(device)) {
ALOGV("checkOutputsForDevice(): setOutputDevice(dev=0x%x, addr=%s)",
device, address.string());
setOutputDevice(output, device, true/*force*/, 0/*delay*/,
@@ -3587,7 +3100,7 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> de
desc = mOutputs.valueAt(i);
if (!desc->isDuplicated()) {
// exact match on device
- if (deviceDistinguishesOnAddress(device) &&
+ if (device_distinguishes_on_address(device) &&
(desc->mProfile->mSupportedDevices.types() == device)) {
findIoHandlesByAddress(desc, device, address, outputs);
} else if (!(desc->mProfile->mSupportedDevices.types()
@@ -3630,9 +3143,9 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor> de
}
status_t AudioPolicyManager::checkInputsForDevice(audio_devices_t device,
- audio_policy_dev_state_t state,
- SortedVector<audio_io_handle_t>& inputs,
- const String8 address)
+ audio_policy_dev_state_t state,
+ SortedVector<audio_io_handle_t>& inputs,
+ const String8 address)
{
sp<AudioInputDescriptor> desc;
if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
@@ -3659,7 +3172,7 @@ status_t AudioPolicyManager::checkInputsForDevice(audio_devices_t device,
sp<IOProfile> profile = mHwModules[module_idx]->mInputProfiles[profile_index];
if (profile->mSupportedDevices.types() & (device & ~AUDIO_DEVICE_BIT_IN)) {
- if (!deviceDistinguishesOnAddress(device) ||
+ if (!device_distinguishes_on_address(device) ||
address == profile->mSupportedDevices[0]->mAddress) {
profiles.add(profile);
ALOGV("checkInputsForDevice(): adding profile %zu from module %zu",
@@ -3831,12 +3344,7 @@ void AudioPolicyManager::closeOutput(audio_io_handle_t output)
ALOGW("closeOutput() unknown output %d", output);
return;
}
-
- for (size_t i = 0; i < mPolicyMixes.size(); i++) {
- if (mPolicyMixes[i]->mOutput == outputDesc) {
- mPolicyMixes[i]->mOutput.clear();
- }
- }
+ mPolicyMixes.closeOutput(outputDesc);
// look for duplicated outputs connected to the output being removed.
for (size_t i = 0; i < mOutputs.size(); i++) {
@@ -3862,7 +3370,7 @@ void AudioPolicyManager::closeOutput(audio_io_handle_t output)
ALOGV("closeOutput() closing also duplicated output %d", duplicatedOutput);
mpClientInterface->closeOutput(duplicatedOutput);
- mOutputs.removeItem(duplicatedOutput);
+ removeOutput(duplicatedOutput);
}
}
@@ -3881,7 +3389,7 @@ void AudioPolicyManager::closeOutput(audio_io_handle_t output)
mpClientInterface->setParameters(output, param.toString());
mpClientInterface->closeOutput(output);
- mOutputs.removeItem(output);
+ removeOutput(output);
mPreviousOutputs = mOutputs;
}
@@ -3910,7 +3418,7 @@ void AudioPolicyManager::closeInput(audio_io_handle_t input)
}
SortedVector<audio_io_handle_t> AudioPolicyManager::getOutputsForDevice(audio_devices_t device,
- DefaultKeyedVector<audio_io_handle_t, sp<AudioOutputDescriptor> > openOutputs)
+ AudioOutputCollection openOutputs)
{
SortedVector<audio_io_handle_t> outputs;
@@ -3927,7 +3435,7 @@ SortedVector<audio_io_handle_t> AudioPolicyManager::getOutputsForDevice(audio_de
}
bool AudioPolicyManager::vectorsEqual(SortedVector<audio_io_handle_t>& outputs1,
- SortedVector<audio_io_handle_t>& outputs2)
+ SortedVector<audio_io_handle_t>& outputs2)
{
if (outputs1.size() != outputs2.size()) {
return false;
@@ -3971,7 +3479,7 @@ void AudioPolicyManager::checkOutputForStrategy(routing_strategy strategy)
// mute strategy while moving tracks from one output to another
for (size_t i = 0; i < srcOutputs.size(); i++) {
sp<AudioOutputDescriptor> desc = mOutputs.valueFor(srcOutputs[i]);
- if (desc->isStrategyActive(strategy)) {
+ if (isStrategyActive(desc, strategy)) {
setStrategyMute(strategy, true, srcOutputs[i]);
setStrategyMute(strategy, false, srcOutputs[i], MUTE_TIME_MS, newDevice);
}
@@ -4010,10 +3518,10 @@ void AudioPolicyManager::checkOutputForStrategy(routing_strategy strategy)
void AudioPolicyManager::checkOutputForAllStrategies()
{
- if (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)
+ if (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)
checkOutputForStrategy(STRATEGY_ENFORCED_AUDIBLE);
checkOutputForStrategy(STRATEGY_PHONE);
- if (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] != AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)
+ if (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) != AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)
checkOutputForStrategy(STRATEGY_ENFORCED_AUDIBLE);
checkOutputForStrategy(STRATEGY_SONIFICATION);
checkOutputForStrategy(STRATEGY_SONIFICATION_RESPECTFUL);
@@ -4023,21 +3531,9 @@ void AudioPolicyManager::checkOutputForAllStrategies()
checkOutputForStrategy(STRATEGY_REROUTING);
}
-audio_io_handle_t AudioPolicyManager::getA2dpOutput()
-{
- for (size_t i = 0; i < mOutputs.size(); i++) {
- sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
- if (!outputDesc->isDuplicated() && outputDesc->device() & AUDIO_DEVICE_OUT_ALL_A2DP) {
- return mOutputs.keyAt(i);
- }
- }
-
- return 0;
-}
-
void AudioPolicyManager::checkA2dpSuspend()
{
- audio_io_handle_t a2dpOutput = getA2dpOutput();
+ audio_io_handle_t a2dpOutput = mOutputs.getA2dpOutput();
if (a2dpOutput == 0) {
mA2dpSuspended = false;
return;
@@ -4061,20 +3557,20 @@ void AudioPolicyManager::checkA2dpSuspend()
//
if (mA2dpSuspended) {
if ((!isScoConnected ||
- ((mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION] != AUDIO_POLICY_FORCE_BT_SCO) &&
- (mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] != AUDIO_POLICY_FORCE_BT_SCO))) &&
- ((mPhoneState != AUDIO_MODE_IN_CALL) &&
- (mPhoneState != AUDIO_MODE_RINGTONE))) {
+ ((mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION) != AUDIO_POLICY_FORCE_BT_SCO) &&
+ (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) != AUDIO_POLICY_FORCE_BT_SCO))) &&
+ ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) &&
+ (mEngine->getPhoneState() != AUDIO_MODE_RINGTONE))) {
mpClientInterface->restoreOutput(a2dpOutput);
mA2dpSuspended = false;
}
} else {
if ((isScoConnected &&
- ((mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION] == AUDIO_POLICY_FORCE_BT_SCO) ||
- (mForceUse[AUDIO_POLICY_FORCE_FOR_RECORD] == AUDIO_POLICY_FORCE_BT_SCO))) ||
- ((mPhoneState == AUDIO_MODE_IN_CALL) ||
- (mPhoneState == AUDIO_MODE_RINGTONE))) {
+ ((mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION) == AUDIO_POLICY_FORCE_BT_SCO) ||
+ (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_RECORD) == AUDIO_POLICY_FORCE_BT_SCO))) ||
+ ((mEngine->getPhoneState() == AUDIO_MODE_IN_CALL) ||
+ (mEngine->getPhoneState() == AUDIO_MODE_RINGTONE))) {
mpClientInterface->suspendOutput(a2dpOutput);
mA2dpSuspended = true;
@@ -4117,27 +3613,27 @@ audio_devices_t AudioPolicyManager::getNewOutputDevice(audio_io_handle_t output,
// use device for strategy DTMF
// 9: the strategy for beacon, a.k.a. "transmitted through speaker" is active on the output:
// use device for strategy t-t-s
- if (outputDesc->isStrategyActive(STRATEGY_ENFORCED_AUDIBLE) &&
- mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) {
+ if (isStrategyActive(outputDesc, STRATEGY_ENFORCED_AUDIBLE) &&
+ mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) {
device = getDeviceForStrategy(STRATEGY_ENFORCED_AUDIBLE, fromCache);
} else if (isInCall() ||
- outputDesc->isStrategyActive(STRATEGY_PHONE)) {
+ isStrategyActive(outputDesc, STRATEGY_PHONE)) {
device = getDeviceForStrategy(STRATEGY_PHONE, fromCache);
- } else if (outputDesc->isStrategyActive(STRATEGY_ENFORCED_AUDIBLE)) {
+ } else if (isStrategyActive(outputDesc, STRATEGY_ENFORCED_AUDIBLE)) {
device = getDeviceForStrategy(STRATEGY_ENFORCED_AUDIBLE, fromCache);
- } else if (outputDesc->isStrategyActive(STRATEGY_SONIFICATION)) {
+ } else if (isStrategyActive(outputDesc, STRATEGY_SONIFICATION)) {
device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache);
- } else if (outputDesc->isStrategyActive(STRATEGY_SONIFICATION_RESPECTFUL)) {
+ } else if (isStrategyActive(outputDesc, STRATEGY_SONIFICATION_RESPECTFUL)) {
device = getDeviceForStrategy(STRATEGY_SONIFICATION_RESPECTFUL, fromCache);
- } else if (outputDesc->isStrategyActive(STRATEGY_ACCESSIBILITY)) {
+ } else if (isStrategyActive(outputDesc, STRATEGY_ACCESSIBILITY)) {
device = getDeviceForStrategy(STRATEGY_ACCESSIBILITY, fromCache);
- } else if (outputDesc->isStrategyActive(STRATEGY_MEDIA)) {
+ } else if (isStrategyActive(outputDesc, STRATEGY_MEDIA)) {
device = getDeviceForStrategy(STRATEGY_MEDIA, fromCache);
- } else if (outputDesc->isStrategyActive(STRATEGY_DTMF)) {
+ } else if (isStrategyActive(outputDesc, STRATEGY_DTMF)) {
device = getDeviceForStrategy(STRATEGY_DTMF, fromCache);
- } else if (outputDesc->isStrategyActive(STRATEGY_TRANSMITTED_THROUGH_SPEAKER)) {
+ } else if (isStrategyActive(outputDesc, STRATEGY_TRANSMITTED_THROUGH_SPEAKER)) {
device = getDeviceForStrategy(STRATEGY_TRANSMITTED_THROUGH_SPEAKER, fromCache);
- } else if (outputDesc->isStrategyActive(STRATEGY_REROUTING)) {
+ } else if (isStrategyActive(outputDesc, STRATEGY_REROUTING)) {
device = getDeviceForStrategy(STRATEGY_REROUTING, fromCache);
}
@@ -4182,7 +3678,7 @@ audio_devices_t AudioPolicyManager::getDevicesForStream(audio_stream_type_t stre
SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(devices, mOutputs);
for (size_t i = 0; i < outputs.size(); i++) {
sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(outputs[i]);
- if (outputDesc->isStrategyActive(strategy)) {
+ if (isStrategyActive(outputDesc, strategy)) {
devices = outputDesc->device();
break;
}
@@ -4198,39 +3694,10 @@ audio_devices_t AudioPolicyManager::getDevicesForStream(audio_stream_type_t stre
return devices;
}
-routing_strategy AudioPolicyManager::getStrategy(
- audio_stream_type_t stream) {
-
+routing_strategy AudioPolicyManager::getStrategy(audio_stream_type_t stream) const
+{
ALOG_ASSERT(stream != AUDIO_STREAM_PATCH,"getStrategy() called for AUDIO_STREAM_PATCH");
-
- // 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;
- }
+ return mEngine->getStrategyForStream(stream);
}
uint32_t AudioPolicyManager::getStrategyForAttr(const audio_attributes_t *attr) {
@@ -4241,45 +3708,8 @@ uint32_t AudioPolicyManager::getStrategyForAttr(const audio_attributes_t *attr)
if ((attr->flags & AUDIO_FLAG_AUDIBILITY_ENFORCED) == AUDIO_FLAG_AUDIBILITY_ENFORCED) {
return (uint32_t) STRATEGY_ENFORCED_AUDIBLE;
}
-
// usage to strategy mapping
- switch (attr->usage) {
- case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
- if (isStreamActive(AUDIO_STREAM_RING) || isStreamActive(AUDIO_STREAM_ALARM)) {
- return (uint32_t) STRATEGY_SONIFICATION;
- }
- if (isInCall()) {
- return (uint32_t) STRATEGY_PHONE;
- }
- return (uint32_t) STRATEGY_ACCESSIBILITY;
-
- case AUDIO_USAGE_MEDIA:
- case AUDIO_USAGE_GAME:
- case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
- case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
- return (uint32_t) STRATEGY_MEDIA;
-
- case AUDIO_USAGE_VOICE_COMMUNICATION:
- return (uint32_t) STRATEGY_PHONE;
-
- case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
- return (uint32_t) STRATEGY_DTMF;
-
- case AUDIO_USAGE_ALARM:
- case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
- return (uint32_t) 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 (uint32_t) STRATEGY_SONIFICATION_RESPECTFUL;
-
- case AUDIO_USAGE_UNKNOWN:
- default:
- return (uint32_t) STRATEGY_MEDIA;
- }
+ return static_cast<uint32_t>(mEngine->getStrategyForUsage(attr->usage));
}
void AudioPolicyManager::handleNotificationRoutingForStream(audio_stream_type_t stream) {
@@ -4293,21 +3723,6 @@ void AudioPolicyManager::handleNotificationRoutingForStream(audio_stream_type_t
}
}
-bool AudioPolicyManager::isAnyOutputActive(audio_stream_type_t streamToIgnore) {
- for (size_t s = 0 ; s < AUDIO_STREAM_CNT ; s++) {
- if (s == (size_t) streamToIgnore) {
- continue;
- }
- for (size_t i = 0; i < mOutputs.size(); i++) {
- const sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
- if (outputDesc->mRefCount[s] != 0) {
- return true;
- }
- }
- }
- return false;
-}
-
uint32_t AudioPolicyManager::handleEventForBeacon(int event) {
switch(event) {
case STARTING_OUTPUT:
@@ -4362,292 +3777,14 @@ uint32_t AudioPolicyManager::setBeaconMute(bool mute) {
}
audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strategy,
- bool fromCache)
+ bool fromCache)
{
- uint32_t device = AUDIO_DEVICE_NONE;
-
if (fromCache) {
ALOGVV("getDeviceForStrategy() from cache strategy %d, device %x",
strategy, mDeviceForStrategy[strategy]);
return mDeviceForStrategy[strategy];
}
- audio_devices_t availableOutputDeviceTypes = mAvailableOutputDevices.types();
- switch (strategy) {
-
- case STRATEGY_TRANSMITTED_THROUGH_SPEAKER:
- device = availableOutputDeviceTypes & 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, false /*fromCache*/);
- } else if (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, false /*fromCache*/);
- //user "safe" speaker if available instead of normal speaker to avoid triggering
- //other acoustic safety mechanisms for notification
- if (device == AUDIO_DEVICE_OUT_SPEAKER && (availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER_SAFE))
- device = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
- } else if (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, false /*fromCache*/);
- } else {
- // when media is not playing anymore, fall back on the sonification behavior
- device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/);
- //user "safe" speaker if available instead of normal speaker to avoid triggering
- //other acoustic safety mechanisms for notification
- if (device == AUDIO_DEVICE_OUT_SPEAKER && (availableOutputDeviceTypes & 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, false /*fromCache*/);
- 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 (mPhoneState == AUDIO_MODE_IN_CALL) {
- audio_devices_t txDevice =
- getDeviceAndMixForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION);
- sp<AudioOutputDescriptor> hwOutputDesc = mOutputs.valueFor(mPrimaryOutput);
- if (((mAvailableInputDevices.types() &
- AUDIO_DEVICE_IN_TELEPHONY_RX & ~AUDIO_DEVICE_BIT_IN) == 0) ||
- (((txDevice & availablePrimaryInputDevices() & ~AUDIO_DEVICE_BIT_IN) != 0) &&
- (hwOutputDesc->getAudioPort()->mModule->mHalVersion <
- AUDIO_DEVICE_API_VERSION_3_0))) {
- availableOutputDeviceTypes = availablePrimaryOutputDevices();
- }
- }
- // 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 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
- if (device) break;
- }
- device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
- if (device) break;
- device = availableOutputDeviceTypes & 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) &&
- (getA2dpOutput() != 0)) {
- device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
- if (device) break;
- device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
- if (device) break;
- }
- device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
- if (device) break;
- device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_WIRED_HEADSET;
- if (device) break;
- device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_DEVICE;
- if (device) break;
- if (!isInCall()) {
- device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_ACCESSORY;
- if (device) break;
- device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
- if (device) break;
- device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_AUX_DIGITAL;
- if (device) break;
- device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
- if (device) break;
- }
- device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_EARPIECE;
- if (device) break;
- device = mDefaultOutputDevice->mDeviceType;
- 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) &&
- (getA2dpOutput() != 0)) {
- device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
- if (device) break;
- }
- if (!isInCall()) {
- device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_ACCESSORY;
- if (device) break;
- device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_DEVICE;
- if (device) break;
- device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
- if (device) break;
- device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_AUX_DIGITAL;
- if (device) break;
- device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
- if (device) break;
- }
- device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_LINE;
- if (device) break;
- device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER;
- if (device) break;
- device = mDefaultOutputDevice->mDeviceType;
- 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, false /*fromCache*/);
- 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 = availableOutputDeviceTypes & 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 < mOutputs.size(); i++) {
- sp<AudioOutputDescriptor> desc = mOutputs.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) {
- availableOutputDeviceTypes = availableOutputDeviceTypes & ~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 (mAvailableOutputDevices.getDevice(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, String8("0")) != 0) {
- device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
- }
- }
- if ((device2 == AUDIO_DEVICE_NONE) &&
- (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
- (getA2dpOutput() != 0)) {
- device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
- if (device2 == AUDIO_DEVICE_NONE) {
- device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
- }
- if (device2 == AUDIO_DEVICE_NONE) {
- device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
- }
- }
- if ((device2 == AUDIO_DEVICE_NONE) &&
- (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] == AUDIO_POLICY_FORCE_SPEAKER)) {
- device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER;
- }
- if (device2 == AUDIO_DEVICE_NONE) {
- device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
- }
- if ((device2 == AUDIO_DEVICE_NONE)) {
- device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_LINE;
- }
- if (device2 == AUDIO_DEVICE_NONE) {
- device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_WIRED_HEADSET;
- }
- if (device2 == AUDIO_DEVICE_NONE) {
- device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_ACCESSORY;
- }
- if (device2 == AUDIO_DEVICE_NONE) {
- device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_USB_DEVICE;
- }
- if (device2 == AUDIO_DEVICE_NONE) {
- device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
- }
- if ((device2 == AUDIO_DEVICE_NONE) && (strategy != STRATEGY_SONIFICATION)) {
- // no sonification on aux digital (e.g. HDMI)
- device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_AUX_DIGITAL;
- }
- if ((device2 == AUDIO_DEVICE_NONE) &&
- (mForceUse[AUDIO_POLICY_FORCE_FOR_DOCK] == AUDIO_POLICY_FORCE_ANALOG_DOCK)) {
- device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
- }
- if (device2 == AUDIO_DEVICE_NONE) {
- device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER;
- }
- int device3 = AUDIO_DEVICE_NONE;
- if (strategy == STRATEGY_MEDIA) {
- // ARC, SPDIF and AUX_LINE can co-exist with others.
- device3 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_HDMI_ARC;
- device3 |= (availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPDIF);
- device3 |= (availableOutputDeviceTypes & 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 = mDefaultOutputDevice->mDeviceType;
- 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;
+ return mEngine->getDeviceForStrategy(strategy);
}
void AudioPolicyManager::updateDevicesAndOutputs()
@@ -4698,7 +3835,7 @@ uint32_t AudioPolicyManager::checkDeviceMuteStrategies(sp<AudioOutputDescriptor>
ALOGVV("checkDeviceMuteStrategies() %s strategy %d (curDevice %04x) on output %d",
mute ? "muting" : "unmuting", i, curDevice, curOutput);
setStrategyMute((routing_strategy)i, mute, curOutput, mute ? 0 : delayMs);
- if (desc->isStrategyActive((routing_strategy)i)) {
+ if (isStrategyActive(desc, (routing_strategy)i)) {
if (mute) {
// FIXME: should not need to double latency if volume could be applied
// immediately by the audioflinger mixer. We must account for the delay
@@ -4721,7 +3858,7 @@ uint32_t AudioPolicyManager::checkDeviceMuteStrategies(sp<AudioOutputDescriptor>
muteWaitMs = outputDesc->latency() * 2;
}
for (size_t i = 0; i < NUM_STRATEGIES; i++) {
- if (outputDesc->isStrategyActive((routing_strategy)i)) {
+ if (isStrategyActive(outputDesc, (routing_strategy)i)) {
setStrategyMute((routing_strategy)i, true, outputDesc->mIoHandle);
// do tempMute unmute after twice the mute wait time
setStrategyMute((routing_strategy)i, false, outputDesc->mIoHandle,
@@ -4827,8 +3964,7 @@ uint32_t AudioPolicyManager::setOutputDevice(audio_io_handle_t output,
status, afPatchHandle, patch.num_sources, patch.num_sinks);
if (status == NO_ERROR) {
if (index < 0) {
- patchDesc = new AudioPatch((audio_patch_handle_t)nextUniqueId(),
- &patch, mUidCached);
+ patchDesc = new AudioPatch(&patch, mUidCached);
addAudioPatch(patchDesc->mHandle, patchDesc);
} else {
patchDesc->mPatch = patch;
@@ -4847,7 +3983,7 @@ uint32_t AudioPolicyManager::setOutputDevice(audio_io_handle_t output,
// inform all input as well
for (size_t i = 0; i < mInputs.size(); i++) {
const sp<AudioInputDescriptor> inputDescriptor = mInputs.valueAt(i);
- if (!isVirtualInputDevice(inputDescriptor->mDevice)) {
+ if (!is_virtual_input_device(inputDescriptor->mDevice)) {
AudioParameter inputCmd = AudioParameter();
ALOGV("%s: inform input %d of device:%d", __func__,
inputDescriptor->mIoHandle, device);
@@ -4934,8 +4070,7 @@ status_t AudioPolicyManager::setInputDevice(audio_io_handle_t input,
status, afPatchHandle);
if (status == NO_ERROR) {
if (index < 0) {
- patchDesc = new AudioPatch((audio_patch_handle_t)nextUniqueId(),
- &patch, mUidCached);
+ patchDesc = new AudioPatch(&patch, mUidCached);
addAudioPatch(patchDesc->mHandle, patchDesc);
} else {
patchDesc->mPatch = patch;
@@ -4978,11 +4113,11 @@ status_t AudioPolicyManager::resetInputDevice(audio_io_handle_t input,
}
sp<IOProfile> AudioPolicyManager::getInputProfile(audio_devices_t device,
- String8 address,
- uint32_t& samplingRate,
- audio_format_t format,
- audio_channel_mask_t channelMask,
- audio_input_flags_t flags)
+ String8 address,
+ uint32_t& samplingRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ audio_input_flags_t flags)
{
// Choose an input profile based on the requested capture parameters: select the first available
// profile supporting all requested parameters.
@@ -5009,224 +4144,35 @@ sp<IOProfile> AudioPolicyManager::getInputProfile(audio_devices_t device,
audio_devices_t AudioPolicyManager::getDeviceAndMixForInputSource(audio_source_t inputSource,
- AudioMix **policyMix)
+ AudioMix **policyMix)
{
- audio_devices_t availableDeviceTypes = mAvailableInputDevices.types() &
- ~AUDIO_DEVICE_BIT_IN;
+ audio_devices_t availableDeviceTypes = mAvailableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN;
+ audio_devices_t selectedDeviceFromMix =
+ mPolicyMixes.getDeviceAndMixForInputSource(inputSource, availableDeviceTypes, policyMix);
- for (size_t i = 0; i < mPolicyMixes.size(); i++) {
- if (mPolicyMixes[i]->mMix.mMixType != MIX_TYPE_RECORDERS) {
- continue;
- }
- for (size_t j = 0; j < mPolicyMixes[i]->mMix.mCriteria.size(); j++) {
- if ((RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET == mPolicyMixes[i]->mMix.mCriteria[j].mRule &&
- mPolicyMixes[i]->mMix.mCriteria[j].mAttr.mSource == inputSource) ||
- (RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET == mPolicyMixes[i]->mMix.mCriteria[j].mRule &&
- mPolicyMixes[i]->mMix.mCriteria[j].mAttr.mSource != inputSource)) {
- if (availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
- if (policyMix != NULL) {
- *policyMix = &mPolicyMixes[i]->mMix;
- }
- return AUDIO_DEVICE_IN_REMOTE_SUBMIX;
- }
- break;
- }
- }
+ if (selectedDeviceFromMix != AUDIO_DEVICE_NONE) {
+ return selectedDeviceFromMix;
}
-
return getDeviceForInputSource(inputSource);
}
audio_devices_t AudioPolicyManager::getDeviceForInputSource(audio_source_t inputSource)
{
- uint32_t device = AUDIO_DEVICE_NONE;
- audio_devices_t availableDeviceTypes = mAvailableInputDevices.types() &
- ~AUDIO_DEVICE_BIT_IN;
-
- 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 ((mPhoneState == AUDIO_MODE_IN_CALL) &&
- (mAvailableOutputDevices.types() & AUDIO_DEVICE_OUT_TELEPHONY_TX) == 0) {
- availableDeviceTypes = availablePrimaryInputDevices() & ~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;
-}
-
-bool AudioPolicyManager::isVirtualInputDevice(audio_devices_t device)
-{
- if ((device & AUDIO_DEVICE_BIT_IN) != 0) {
- device &= ~AUDIO_DEVICE_BIT_IN;
- if ((popcount(device) == 1) && ((device & ~APM_AUDIO_IN_DEVICE_VIRTUAL_ALL) == 0))
- return true;
- }
- return false;
-}
-
-bool AudioPolicyManager::deviceDistinguishesOnAddress(audio_devices_t device) {
- return ((device & APM_AUDIO_DEVICE_MATCH_ADDRESS_ALL & ~AUDIO_DEVICE_BIT_IN) != 0);
-}
-
-audio_io_handle_t AudioPolicyManager::getActiveInput(bool ignoreVirtualInputs)
-{
- for (size_t i = 0; i < mInputs.size(); i++) {
- const sp<AudioInputDescriptor> input_descriptor = mInputs.valueAt(i);
- if ((input_descriptor->mRefCount > 0)
- && (!ignoreVirtualInputs || !isVirtualInputDevice(input_descriptor->mDevice))) {
- return mInputs.keyAt(i);
- }
- }
- return 0;
-}
-
-uint32_t AudioPolicyManager::activeInputsCount() const
-{
- uint32_t count = 0;
- for (size_t i = 0; i < mInputs.size(); i++) {
- const sp<AudioInputDescriptor> desc = mInputs.valueAt(i);
- if (desc->mRefCount > 0) {
- count++;
- }
- }
- return count;
-}
-
-
-void AudioPolicyManager::initializeVolumeCurves()
-{
- for (int i = 0; i < AUDIO_STREAM_CNT; i++) {
- for (int j = 0; j < ApmGains::DEVICE_CATEGORY_CNT; j++) {
- mStreams[i].mVolumeCurve[j] =
- ApmGains::sVolumeProfiles[i][j];
- }
- }
-
- // Check availability of DRC on speaker path: if available, override some of the speaker curves
- if (mSpeakerDrcEnabled) {
- mStreams[AUDIO_STREAM_SYSTEM].mVolumeCurve[ApmGains::DEVICE_CATEGORY_SPEAKER] =
- ApmGains::sDefaultSystemVolumeCurveDrc;
- mStreams[AUDIO_STREAM_RING].mVolumeCurve[ApmGains::DEVICE_CATEGORY_SPEAKER] =
- ApmGains::sSpeakerSonificationVolumeCurveDrc;
- mStreams[AUDIO_STREAM_ALARM].mVolumeCurve[ApmGains::DEVICE_CATEGORY_SPEAKER] =
- ApmGains::sSpeakerSonificationVolumeCurveDrc;
- mStreams[AUDIO_STREAM_NOTIFICATION].mVolumeCurve[ApmGains::DEVICE_CATEGORY_SPEAKER] =
- ApmGains::sSpeakerSonificationVolumeCurveDrc;
- mStreams[AUDIO_STREAM_MUSIC].mVolumeCurve[ApmGains::DEVICE_CATEGORY_SPEAKER] =
- ApmGains::sSpeakerMediaVolumeCurveDrc;
- mStreams[AUDIO_STREAM_ACCESSIBILITY].mVolumeCurve[ApmGains::DEVICE_CATEGORY_SPEAKER] =
- ApmGains::sSpeakerMediaVolumeCurveDrc;
- }
+ return mEngine->getDeviceForInputSource(inputSource);
}
float AudioPolicyManager::computeVolume(audio_stream_type_t stream,
- int index,
- audio_io_handle_t output,
- audio_devices_t device)
+ int index,
+ audio_io_handle_t output,
+ audio_devices_t device)
{
float volume = 1.0;
sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
- StreamDescriptor &streamDesc = mStreams[stream];
if (device == AUDIO_DEVICE_NONE) {
device = outputDesc->device();
}
-
- volume = ApmGains::volIndexToAmpl(device, streamDesc, index);
+ volume = mEngine->volIndexToAmpl(Volume::getDeviceCategory(device), stream, index);
// if a headset is connected, apply the following rules to ring tones and notifications
// to avoid sound level bursts in user's ears:
@@ -5242,8 +4188,8 @@ float AudioPolicyManager::computeVolume(audio_stream_type_t stream,
|| (stream_strategy == STRATEGY_SONIFICATION_RESPECTFUL)
|| (stream == AUDIO_STREAM_SYSTEM)
|| ((stream_strategy == STRATEGY_ENFORCED_AUDIBLE) &&
- (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_NONE))) &&
- streamDesc.mCanBeMuted) {
+ (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_NONE))) &&
+ mStreams.canBeMuted(stream)) {
volume *= SONIFICATION_HEADSET_VOLUME_FACTOR;
// when the phone is ringing we must consider that music could have been paused just before
// by the music application and behave as if music was active if the last music track was
@@ -5268,11 +4214,11 @@ float AudioPolicyManager::computeVolume(audio_stream_type_t stream,
}
status_t AudioPolicyManager::checkAndSetVolume(audio_stream_type_t stream,
- int index,
- audio_io_handle_t output,
- audio_devices_t device,
- int delayMs,
- bool force)
+ int index,
+ audio_io_handle_t output,
+ audio_devices_t device,
+ int delayMs,
+ bool force)
{
// do not change actual stream volume if the stream is muted
@@ -5281,14 +4227,13 @@ status_t AudioPolicyManager::checkAndSetVolume(audio_stream_type_t stream,
stream, mOutputs.valueFor(output)->mMuteCount[stream]);
return NO_ERROR;
}
-
+ audio_policy_forced_cfg_t forceUseForComm =
+ mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_COMMUNICATION);
// do not change in call volume if bluetooth is connected and vice versa
- if ((stream == AUDIO_STREAM_VOICE_CALL &&
- mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION] == AUDIO_POLICY_FORCE_BT_SCO) ||
- (stream == AUDIO_STREAM_BLUETOOTH_SCO &&
- mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION] != AUDIO_POLICY_FORCE_BT_SCO)) {
+ if ((stream == AUDIO_STREAM_VOICE_CALL && forceUseForComm == AUDIO_POLICY_FORCE_BT_SCO) ||
+ (stream == AUDIO_STREAM_BLUETOOTH_SCO && forceUseForComm != AUDIO_POLICY_FORCE_BT_SCO)) {
ALOGV("checkAndSetVolume() cannot set stream %d volume with force use = %d for comm",
- stream, mForceUse[AUDIO_POLICY_FORCE_FOR_COMMUNICATION]);
+ stream, forceUseForComm);
return INVALID_OPERATION;
}
@@ -5325,7 +4270,7 @@ status_t AudioPolicyManager::checkAndSetVolume(audio_stream_type_t stream,
float voiceVolume;
// Force voice volume to max for bluetooth SCO as volume is managed by the headset
if (stream == AUDIO_STREAM_VOICE_CALL) {
- voiceVolume = (float)index/(float)mStreams[stream].mIndexMax;
+ voiceVolume = (float)index/(float)mStreams[stream].getVolumeIndexMax();
} else {
voiceVolume = 1.0;
}
@@ -5340,9 +4285,9 @@ status_t AudioPolicyManager::checkAndSetVolume(audio_stream_type_t stream,
}
void AudioPolicyManager::applyStreamVolumes(audio_io_handle_t output,
- audio_devices_t device,
- int delayMs,
- bool force)
+ audio_devices_t device,
+ int delayMs,
+ bool force)
{
ALOGVV("applyStreamVolumes() for output %d and device %x", output, device);
@@ -5360,10 +4305,10 @@ void AudioPolicyManager::applyStreamVolumes(audio_io_handle_t output,
}
void AudioPolicyManager::setStrategyMute(routing_strategy strategy,
- bool on,
- audio_io_handle_t output,
- int delayMs,
- audio_devices_t device)
+ bool on,
+ audio_io_handle_t output,
+ int delayMs,
+ audio_devices_t device)
{
ALOGVV("setStrategyMute() strategy %d, mute %d, output %d", strategy, on, output);
for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) {
@@ -5377,12 +4322,12 @@ void AudioPolicyManager::setStrategyMute(routing_strategy strategy,
}
void AudioPolicyManager::setStreamMute(audio_stream_type_t stream,
- bool on,
- audio_io_handle_t output,
- int delayMs,
- audio_devices_t device)
+ bool on,
+ audio_io_handle_t output,
+ int delayMs,
+ audio_devices_t device)
{
- StreamDescriptor &streamDesc = mStreams[stream];
+ const StreamDescriptor &streamDesc = mStreams[stream];
sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
if (device == AUDIO_DEVICE_NONE) {
device = outputDesc->device();
@@ -5393,9 +4338,9 @@ void AudioPolicyManager::setStreamMute(audio_stream_type_t stream,
if (on) {
if (outputDesc->mMuteCount[stream] == 0) {
- if (streamDesc.mCanBeMuted &&
+ if (streamDesc.canBeMuted() &&
((stream != AUDIO_STREAM_ENFORCED_AUDIBLE) ||
- (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_NONE))) {
+ (mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_NONE))) {
checkAndSetVolume(stream, 0, output, device, delayMs);
}
}
@@ -5461,192 +4406,6 @@ void AudioPolicyManager::handleIncallSonification(audio_stream_type_t stream,
}
}
-bool AudioPolicyManager::isInCall()
-{
- return isStateInCall(mPhoneState);
-}
-
-bool AudioPolicyManager::isStateInCall(int state) {
- return ((state == AUDIO_MODE_IN_CALL) ||
- (state == AUDIO_MODE_IN_COMMUNICATION));
-}
-
-uint32_t AudioPolicyManager::getMaxEffectsCpuLoad()
-{
- return MAX_EFFECTS_CPU_LOAD;
-}
-
-uint32_t AudioPolicyManager::getMaxEffectsMemory()
-{
- return MAX_EFFECTS_MEMORY;
-}
-
-
-// --- EffectDescriptor class implementation
-
-status_t AudioPolicyManager::EffectDescriptor::dump(int fd)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
- snprintf(buffer, SIZE, " I/O: %d\n", mIo);
- result.append(buffer);
- snprintf(buffer, SIZE, " Strategy: %d\n", mStrategy);
- result.append(buffer);
- snprintf(buffer, SIZE, " Session: %d\n", mSession);
- result.append(buffer);
- snprintf(buffer, SIZE, " Name: %s\n", mDesc.name);
- result.append(buffer);
- snprintf(buffer, SIZE, " %s\n", mEnabled ? "Enabled" : "Disabled");
- result.append(buffer);
- write(fd, result.string(), result.size());
-
- return NO_ERROR;
-}
-
-
-// --- audio_policy.conf file parsing
-// TODO candidate to be moved to ConfigParsingUtils
-void AudioPolicyManager::loadHwModule(cnode *root)
-{
- status_t status = NAME_NOT_FOUND;
- cnode *node;
- sp<HwModule> module = new HwModule(root->name);
-
- node = config_find(root, DEVICES_TAG);
- if (node != NULL) {
- node = node->first_child;
- while (node) {
- ALOGV("loadHwModule() loading device %s", node->name);
- status_t tmpStatus = module->loadDevice(node);
- if (status == NAME_NOT_FOUND || status == NO_ERROR) {
- status = tmpStatus;
- }
- node = node->next;
- }
- }
- node = config_find(root, OUTPUTS_TAG);
- if (node != NULL) {
- node = node->first_child;
- while (node) {
- ALOGV("loadHwModule() loading output %s", node->name);
- status_t tmpStatus = module->loadOutput(node);
- if (status == NAME_NOT_FOUND || status == NO_ERROR) {
- status = tmpStatus;
- }
- node = node->next;
- }
- }
- node = config_find(root, INPUTS_TAG);
- if (node != NULL) {
- node = node->first_child;
- while (node) {
- ALOGV("loadHwModule() loading input %s", node->name);
- status_t tmpStatus = module->loadInput(node);
- if (status == NAME_NOT_FOUND || status == NO_ERROR) {
- status = tmpStatus;
- }
- node = node->next;
- }
- }
- loadGlobalConfig(root, module);
-
- if (status == NO_ERROR) {
- mHwModules.add(module);
- }
-}
-
-// TODO candidate to be moved to ConfigParsingUtils
-void AudioPolicyManager::loadHwModules(cnode *root)
-{
- cnode *node = config_find(root, AUDIO_HW_MODULE_TAG);
- if (node == NULL) {
- return;
- }
-
- node = node->first_child;
- while (node) {
- ALOGV("loadHwModules() loading module %s", node->name);
- loadHwModule(node);
- node = node->next;
- }
-}
-
-// TODO candidate to be moved to ConfigParsingUtils
-void AudioPolicyManager::loadGlobalConfig(cnode *root, const sp<HwModule>& module)
-{
- cnode *node = config_find(root, GLOBAL_CONFIG_TAG);
-
- if (node == NULL) {
- return;
- }
- DeviceVector declaredDevices;
- if (module != NULL) {
- declaredDevices = module->mDeclaredDevices;
- }
-
- node = node->first_child;
- while (node) {
- if (strcmp(ATTACHED_OUTPUT_DEVICES_TAG, node->name) == 0) {
- mAvailableOutputDevices.loadDevicesFromName((char *)node->value,
- declaredDevices);
- ALOGV("loadGlobalConfig() Attached Output Devices %08x",
- mAvailableOutputDevices.types());
- } else if (strcmp(DEFAULT_OUTPUT_DEVICE_TAG, node->name) == 0) {
- audio_devices_t device = (audio_devices_t)ConfigParsingUtils::stringToEnum(
- sDeviceNameToEnumTable,
- ARRAY_SIZE(sDeviceNameToEnumTable),
- (char *)node->value);
- if (device != AUDIO_DEVICE_NONE) {
- mDefaultOutputDevice = new DeviceDescriptor(String8("default-output"), device);
- } else {
- ALOGW("loadGlobalConfig() default device not specified");
- }
- ALOGV("loadGlobalConfig() mDefaultOutputDevice %08x", mDefaultOutputDevice->mDeviceType);
- } else if (strcmp(ATTACHED_INPUT_DEVICES_TAG, node->name) == 0) {
- mAvailableInputDevices.loadDevicesFromName((char *)node->value,
- declaredDevices);
- ALOGV("loadGlobalConfig() Available InputDevices %08x", mAvailableInputDevices.types());
- } else if (strcmp(SPEAKER_DRC_ENABLED_TAG, node->name) == 0) {
- mSpeakerDrcEnabled = ConfigParsingUtils::stringToBool((char *)node->value);
- ALOGV("loadGlobalConfig() mSpeakerDrcEnabled = %d", mSpeakerDrcEnabled);
- } else if (strcmp(AUDIO_HAL_VERSION_TAG, node->name) == 0) {
- uint32_t major, minor;
- sscanf((char *)node->value, "%u.%u", &major, &minor);
- module->mHalVersion = HARDWARE_DEVICE_API_VERSION(major, minor);
- ALOGV("loadGlobalConfig() mHalVersion = %04x major %u minor %u",
- module->mHalVersion, major, minor);
- }
- node = node->next;
- }
-}
-
-// TODO candidate to be moved to ConfigParsingUtils
-status_t AudioPolicyManager::loadAudioPolicyConfig(const char *path)
-{
- cnode *root;
- char *data;
-
- data = (char *)load_file(path, NULL);
- if (data == NULL) {
- return -ENODEV;
- }
- root = config_node("", "");
- config_load(root, data);
-
- loadHwModules(root);
- // legacy audio_policy.conf files have one global_configuration section
- loadGlobalConfig(root, getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY));
- config_free(root);
- free(root);
- free(data);
-
- ALOGI("loadAudioPolicyConfig() loaded %s\n", path);
-
- return NO_ERROR;
-}
-
void AudioPolicyManager::defaultAudioPolicyConfig(void)
{
sp<HwModule> module;
@@ -5732,7 +4491,8 @@ audio_stream_type_t AudioPolicyManager::streamTypefromAttributesInt(const audio_
}
}
-bool AudioPolicyManager::isValidAttributes(const audio_attributes_t *paa) {
+bool AudioPolicyManager::isValidAttributes(const audio_attributes_t *paa)
+{
// has flags that map to a strategy?
if ((paa->flags & (AUDIO_FLAG_AUDIBILITY_ENFORCED | AUDIO_FLAG_SCO | AUDIO_FLAG_BEACON)) != 0) {
return true;
@@ -5763,4 +4523,39 @@ bool AudioPolicyManager::isValidAttributes(const audio_attributes_t *paa) {
return true;
}
+bool AudioPolicyManager::isStrategyActive(const sp<AudioOutputDescriptor> outputDesc,
+ routing_strategy strategy, uint32_t inPastMs,
+ nsecs_t sysTime) const
+{
+ if ((sysTime == 0) && (inPastMs != 0)) {
+ sysTime = systemTime();
+ }
+ for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) {
+ if (i == AUDIO_STREAM_PATCH) {
+ continue;
+ }
+ if (((getStrategy((audio_stream_type_t)i) == strategy) ||
+ (NUM_STRATEGIES == strategy)) &&
+ outputDesc->isStreamActive((audio_stream_type_t)i, inPastMs, sysTime)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+audio_policy_forced_cfg_t AudioPolicyManager::getForceUse(audio_policy_force_use_t usage)
+{
+ return mEngine->getForceUse(usage);
+}
+
+bool AudioPolicyManager::isInCall()
+{
+ return isStateInCall(mEngine->getPhoneState());
+}
+
+bool AudioPolicyManager::isStateInCall(int state)
+{
+ return is_state_in_call(state);
+}
+
}; // namespace android
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 61ea6f2..02b678a 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#pragma once
#include <stdint.h>
#include <sys/types.h>
@@ -26,14 +27,21 @@
#include <media/AudioPolicy.h>
#include "AudioPolicyInterface.h"
-#include "Gains.h"
-#include "Ports.h"
-#include "ConfigParsingUtils.h"
-#include "Devices.h"
-#include "IOProfile.h"
-#include "HwModule.h"
-#include "AudioInputDescriptor.h"
-#include "AudioOutputDescriptor.h"
+#include <AudioPolicyManagerInterface.h>
+#include <AudioPolicyManagerObserver.h>
+#include <AudioGain.h>
+#include <AudioPort.h>
+#include <AudioPatch.h>
+#include <ConfigParsingUtils.h>
+#include <DeviceDescriptor.h>
+#include <IOProfile.h>
+#include <HwModule.h>
+#include <AudioInputDescriptor.h>
+#include <AudioOutputDescriptor.h>
+#include <AudioPolicyMix.h>
+#include <EffectDescriptor.h>
+#include <SoundTriggerSession.h>
+#include <StreamDescriptor.h>
namespace android {
@@ -46,9 +54,7 @@ namespace android {
// Time in milliseconds during which we consider that music is still active after a music
// track was stopped - see computeVolume()
#define SONIFICATION_HEADSET_MUSIC_DELAY 5000
-// Time in milliseconds after media stopped playing during which we consider that the
-// sonification should be as unobtrusive as during the time media was playing.
-#define SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY 5000
+
// Time in milliseconds during witch some streams are muted while the audio path
// is switched
#define MUTE_TIME_MS 2000
@@ -61,14 +67,12 @@ namespace android {
// Can be overridden by the audio.offload.min.duration.secs property
#define OFFLOAD_DEFAULT_MIN_DURATION_SECS 60
-#define MAX_MIXER_SAMPLING_RATE 48000
-#define MAX_MIXER_CHANNEL_COUNT 8
-
// ----------------------------------------------------------------------------
// AudioPolicyManager implements audio policy manager behavior common to all platforms.
// ----------------------------------------------------------------------------
-class AudioPolicyManager: public AudioPolicyInterface
+class AudioPolicyManager : public AudioPolicyInterface, public AudioPolicyManagerObserver
+
#ifdef AUDIO_POLICY_TEST
, public Thread
#endif //AUDIO_POLICY_TEST
@@ -89,6 +93,7 @@ public:
virtual void setForceUse(audio_policy_force_use_t usage,
audio_policy_forced_cfg_t config);
virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage);
+
virtual void setSystemProperty(const char* property, const char* value);
virtual status_t initCheck();
virtual audio_io_handle_t getOutput(audio_stream_type_t stream,
@@ -158,16 +163,28 @@ public:
uint32_t strategy,
int session,
int id);
- virtual status_t unregisterEffect(int id);
- virtual status_t setEffectEnabled(int id, bool enabled);
+ virtual status_t unregisterEffect(int id)
+ {
+ return mEffects.unregisterEffect(id);
+ }
+ virtual status_t setEffectEnabled(int id, bool enabled)
+ {
+ return mEffects.setEffectEnabled(id, enabled);
+ }
- virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
+ virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const
+ {
+ return mOutputs.isStreamActive(stream, inPastMs);
+ }
// return whether a stream is playing remotely, override to change the definition of
// local/remote playback, used for instance by notification manager to not make
// media players lose audio focus when not playing locally
// For the base implementation, "remotely" means playing during screen mirroring which
// uses an output for playback with a non-empty, non "0" address.
- virtual bool isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
+ virtual bool isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs = 0) const
+ {
+ return mOutputs.isStreamActiveRemotely(stream, inPastMs);
+ }
virtual bool isSourceActive(audio_source_t source) const;
virtual status_t dump(int fd);
@@ -195,39 +212,61 @@ public:
audio_io_handle_t *ioHandle,
audio_devices_t *device);
- virtual status_t releaseSoundTriggerSession(audio_session_t session);
+ virtual status_t releaseSoundTriggerSession(audio_session_t session)
+ {
+ return mSoundTriggerSessions.releaseSession(session);
+ }
virtual status_t registerPolicyMixes(Vector<AudioMix> mixes);
virtual status_t unregisterPolicyMixes(Vector<AudioMix> mixes);
// Audio policy configuration file parsing (audio_policy.conf)
// TODO candidates to be moved to ConfigParsingUtils
- void loadHwModule(cnode *root);
- void loadHwModules(cnode *root);
- void loadGlobalConfig(cnode *root, const sp<HwModule>& module);
- status_t loadAudioPolicyConfig(const char *path);
void defaultAudioPolicyConfig(void);
- // return the strategy corresponding to a given stream type
- static routing_strategy getStrategy(audio_stream_type_t stream);
-
- static uint32_t nextUniqueId();
-protected:
+ // return the strategy corresponding to a given stream type
+ routing_strategy getStrategy(audio_stream_type_t stream) const;
- class EffectDescriptor : public RefBase
+ // From AudioPolicyManagerObserver
+ virtual const AudioPatchCollection &getAudioPatches() const
{
- public:
-
- status_t dump(int fd);
-
- int mIo; // io the effect is attached to
- routing_strategy mStrategy; // routing strategy the effect is associated to
- int mSession; // audio session the effect is on
- effect_descriptor_t mDesc; // effect descriptor
- bool mEnabled; // enabled state: CPU load being used or not
- };
-
+ return mAudioPatches;
+ }
+ virtual const SoundTriggerSessionCollection &getSoundTriggerSessionCollection() const
+ {
+ return mSoundTriggerSessions;
+ }
+ virtual const AudioPolicyMixCollection &getAudioPolicyMixCollection() const
+ {
+ return mPolicyMixes;
+ }
+ virtual const AudioOutputCollection &getOutputs() const
+ {
+ return mOutputs;
+ }
+ virtual const AudioInputCollection &getInputs() const
+ {
+ return mInputs;
+ }
+ virtual const DeviceVector &getAvailableOutputDevices() const
+ {
+ return mAvailableOutputDevices;
+ }
+ virtual const DeviceVector &getAvailableInputDevices() const
+ {
+ return mAvailableInputDevices;
+ }
+ virtual StreamDescriptorCollection &getStreamDescriptors()
+ {
+ return mStreams;
+ }
+ virtual const sp<DeviceDescriptor> &getDefaultOutputDevice() const
+ {
+ return mDefaultOutputDevice;
+ }
+protected:
void addOutput(audio_io_handle_t output, sp<AudioOutputDescriptor> outputDesc);
+ void removeOutput(audio_io_handle_t output);
void addInput(audio_io_handle_t input, sp<AudioInputDescriptor> inputDesc);
// return appropriate device for streams handled by the specified strategy according to current
@@ -244,6 +283,9 @@ protected:
virtual audio_devices_t getDeviceForStrategy(routing_strategy strategy,
bool fromCache);
+ bool isStrategyActive(const sp<AudioOutputDescriptor> outputDesc, routing_strategy strategy,
+ uint32_t inPastMs = 0, nsecs_t sysTime = 0) const;
+
// change the route of the specified output. Returns the number of ms we have slept to
// allow new routing to take effect in certain cases.
virtual uint32_t setOutputDevice(audio_io_handle_t output,
@@ -265,16 +307,6 @@ protected:
// select input device corresponding to requested audio source
virtual audio_devices_t getDeviceForInputSource(audio_source_t inputSource);
- // return io handle of active input or 0 if no input is active
- // Only considers inputs from physical devices (e.g. main mic, headset mic) when
- // ignoreVirtualInputs is true.
- audio_io_handle_t getActiveInput(bool ignoreVirtualInputs = true);
-
- uint32_t activeInputsCount() const;
-
- // initialize volume curves for each strategy and device category
- void initializeVolumeCurves();
-
// compute the actual volume for a given stream according to the requested index and a particular
// device
virtual float computeVolume(audio_stream_type_t stream, int index,
@@ -307,9 +339,10 @@ protected:
// a special tone in the device used for communication
void handleIncallSonification(audio_stream_type_t stream, bool starting, bool stateChange);
+ audio_mode_t getPhoneState();
+
// true if device is in a telephony or VoIP call
virtual bool isInCall();
-
// true if given state represents a device in a telephony or VoIP call
virtual bool isStateInCall(int state);
@@ -347,9 +380,6 @@ protected:
// manages A2DP output suspend/restore according to phone state and BT SCO usage
void checkA2dpSuspend();
- // returns the A2DP output handle if it is open or 0 otherwise
- audio_io_handle_t getA2dpOutput();
-
// selects the most appropriate device on output for current state
// must be called every time a condition that affects the device choice for a given output is
// changed: connected device, phone state, force use, output start, output stop..
@@ -366,18 +396,23 @@ protected:
// selects the most appropriate device on input for current state
audio_devices_t getNewInputDevice(audio_io_handle_t input);
- virtual uint32_t getMaxEffectsCpuLoad();
- virtual uint32_t getMaxEffectsMemory();
+ virtual uint32_t getMaxEffectsCpuLoad()
+ {
+ return mEffects.getMaxEffectsCpuLoad();
+ }
+
+ virtual uint32_t getMaxEffectsMemory()
+ {
+ return mEffects.getMaxEffectsMemory();
+ }
#ifdef AUDIO_POLICY_TEST
virtual bool threadLoop();
void exit();
int testOutputIndex(audio_io_handle_t output);
#endif //AUDIO_POLICY_TEST
- status_t setEffectEnabled(const sp<EffectDescriptor>& effectDesc, bool enabled);
-
SortedVector<audio_io_handle_t> getOutputsForDevice(audio_devices_t device,
- DefaultKeyedVector<audio_io_handle_t, sp<AudioOutputDescriptor> > openOutputs);
+ AudioOutputCollection openOutputs);
bool vectorsEqual(SortedVector<audio_io_handle_t>& outputs1,
SortedVector<audio_io_handle_t>& outputs2);
@@ -407,60 +442,57 @@ protected:
audio_io_handle_t selectOutputForEffects(const SortedVector<audio_io_handle_t>& outputs);
- bool isNonOffloadableEffectEnabled();
-
- virtual status_t addAudioPatch(audio_patch_handle_t handle,
- const sp<AudioPatch>& patch);
- virtual status_t removeAudioPatch(audio_patch_handle_t handle);
+ virtual status_t addAudioPatch(audio_patch_handle_t handle, const sp<AudioPatch>& patch)
+ {
+ return mAudioPatches.addAudioPatch(handle, patch);
+ }
+ virtual status_t removeAudioPatch(audio_patch_handle_t handle)
+ {
+ return mAudioPatches.removeAudioPatch(handle);
+ }
- sp<AudioOutputDescriptor> getOutputFromId(audio_port_handle_t id) const;
- sp<AudioInputDescriptor> getInputFromId(audio_port_handle_t id) const;
- sp<HwModule> getModuleForDevice(audio_devices_t device) const;
- sp<HwModule> getModuleFromName(const char *name) const;
- audio_devices_t availablePrimaryOutputDevices();
- audio_devices_t availablePrimaryInputDevices();
+ audio_devices_t availablePrimaryOutputDevices() const
+ {
+ return mOutputs.getSupportedDevices(mPrimaryOutput) & mAvailableOutputDevices.types();
+ }
+ audio_devices_t availablePrimaryInputDevices() const
+ {
+ return mAvailableInputDevices.getDevicesFromHwModule(
+ mOutputs.valueFor(mPrimaryOutput)->getModuleHandle());
+ }
void updateCallRouting(audio_devices_t rxDevice, int delayMs = 0);
-
uid_t mUidCached;
AudioPolicyClientInterface *mpClientInterface; // audio policy client interface
audio_io_handle_t mPrimaryOutput; // primary output handle
// list of descriptors for outputs currently opened
- DefaultKeyedVector<audio_io_handle_t, sp<AudioOutputDescriptor> > mOutputs;
+ AudioOutputCollection mOutputs;
// copy of mOutputs before setDeviceConnectionState() opens new outputs
// reset to mOutputs when updateDevicesAndOutputs() is called.
- DefaultKeyedVector<audio_io_handle_t, sp<AudioOutputDescriptor> > mPreviousOutputs;
- DefaultKeyedVector<audio_io_handle_t, sp<AudioInputDescriptor> > mInputs; // list of input descriptors
+ AudioOutputCollection mPreviousOutputs;
+ AudioInputCollection mInputs; // list of input descriptors
DeviceVector mAvailableOutputDevices; // all available output devices
DeviceVector mAvailableInputDevices; // all available input devices
- int mPhoneState; // current phone state
- audio_policy_forced_cfg_t mForceUse[AUDIO_POLICY_FORCE_USE_CNT]; // current forced use configuration
- StreamDescriptor mStreams[AUDIO_STREAM_CNT]; // stream descriptors for volume control
- bool mLimitRingtoneVolume; // limit ringtone volume to music volume if headset connected
+ StreamDescriptorCollection mStreams; // stream descriptors for volume control
+ bool mLimitRingtoneVolume; // limit ringtone volume to music volume if headset connected
audio_devices_t mDeviceForStrategy[NUM_STRATEGIES];
- float mLastVoiceVolume; // last voice volume value sent to audio HAL
-
- // Maximum CPU load allocated to audio effects in 0.1 MIPS (ARMv5TE, 0 WS memory) units
- static const uint32_t MAX_EFFECTS_CPU_LOAD = 1000;
- // Maximum memory allocated to audio effects in KB
- static const uint32_t MAX_EFFECTS_MEMORY = 512;
- uint32_t mTotalEffectsCpuLoad; // current CPU load used by effects
- uint32_t mTotalEffectsMemory; // current memory used by effects
- KeyedVector<int, sp<EffectDescriptor> > mEffects; // list of registered audio effects
+ float mLastVoiceVolume; // last voice volume value sent to audio HAL
+
+ EffectDescriptorCollection mEffects; // list of registered audio effects
bool mA2dpSuspended; // true if A2DP output is suspended
sp<DeviceDescriptor> mDefaultOutputDevice; // output device selected by default at boot time
bool mSpeakerDrcEnabled;// true on devices that use DRC on the DEVICE_CATEGORY_SPEAKER path
// to boost soft sounds, used to adjust volume curves accordingly
- Vector < sp<HwModule> > mHwModules;
- static volatile int32_t mNextUniqueId;
+ HwModuleCollection mHwModules;
+
volatile int32_t mAudioPortGeneration;
- DefaultKeyedVector<audio_patch_handle_t, sp<AudioPatch> > mAudioPatches;
+ AudioPatchCollection mAudioPatches;
- DefaultKeyedVector<audio_session_t, audio_io_handle_t> mSoundTriggerSessions;
+ SoundTriggerSessionCollection mSoundTriggerSessions;
sp<AudioPatch> mCallTxPatch;
sp<AudioPatch> mCallRxPatch;
@@ -477,16 +509,7 @@ protected:
uint32_t mBeaconPlayingRefCount;// ref count for the playing beacon streams
bool mBeaconMuted; // has STREAM_TTS been muted
- // custom mix entry in mPolicyMixes
- class AudioPolicyMix : public RefBase {
- public:
- AudioPolicyMix() {}
-
- AudioMix mMix; // Audio policy mix descriptor
- sp<AudioOutputDescriptor> mOutput; // Corresponding output stream
- };
- DefaultKeyedVector<String8, sp<AudioPolicyMix> > mPolicyMixes; // list of registered mixes
-
+ AudioPolicyMixCollection mPolicyMixes; // list of registered mixes
#ifdef AUDIO_POLICY_TEST
Mutex mLock;
@@ -503,14 +526,14 @@ protected:
uint32_t mTestLatencyMs;
#endif //AUDIO_POLICY_TEST
- static bool isVirtualInputDevice(audio_devices_t device);
-
uint32_t nextAudioPortGeneration();
+
+ // Audio Policy Engine Interface.
+ AudioPolicyManagerInterface *mEngine;
private:
// updates device caching and output for streams that can influence the
// routing of notifications
void handleNotificationRoutingForStream(audio_stream_type_t stream);
- static bool deviceDistinguishesOnAddress(audio_devices_t device);
// find the outputs on a given output descriptor that have the given address.
// to be called on an AudioOutputDescriptor whose supported devices (as defined
// in mProfile->mSupportedDevices) matches the device whose address is to be matched.
@@ -533,8 +556,6 @@ private:
const audio_offload_info_t *offloadInfo);
// internal function to derive a stream type value from audio attributes
audio_stream_type_t streamTypefromAttributesInt(const audio_attributes_t *attr);
- // return true if any output is playing anything besides the stream to ignore
- bool isAnyOutputActive(audio_stream_type_t streamToIgnore);
// event is one of STARTING_OUTPUT, STARTING_BEACON, STOPPING_OUTPUT, STOPPING_BEACON
// returns 0 if no mute/unmute event happened, the largest latency of the device where
// the mute/unmute happened
@@ -552,9 +573,6 @@ private:
audio_policy_dev_state_t state,
const char *device_address,
const char *device_name);
- sp<DeviceDescriptor> getDeviceDescriptor(const audio_devices_t device,
- const char *device_address,
- const char *device_name);
};
};
diff --git a/services/audiopolicy/managerdefault/ConfigParsingUtils.cpp b/services/audiopolicy/managerdefault/ConfigParsingUtils.cpp
deleted file mode 100644
index 1afd487..0000000
--- a/services/audiopolicy/managerdefault/ConfigParsingUtils.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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::ConfigParsingUtils"
-//#define LOG_NDEBUG 0
-
-#include "AudioPolicyManager.h"
-
-namespace android {
-
-//static
-uint32_t ConfigParsingUtils::stringToEnum(const struct StringToEnum *table,
- size_t size,
- const char *name)
-{
- for (size_t i = 0; i < size; i++) {
- if (strcmp(table[i].name, name) == 0) {
- ALOGV("stringToEnum() found %s", table[i].name);
- return table[i].value;
- }
- }
- return 0;
-}
-
-//static
-const char *ConfigParsingUtils::enumToString(const struct StringToEnum *table,
- size_t size,
- uint32_t value)
-{
- for (size_t i = 0; i < size; i++) {
- if (table[i].value == value) {
- return table[i].name;
- }
- }
- return "";
-}
-
-//static
-bool ConfigParsingUtils::stringToBool(const char *value)
-{
- return ((strcasecmp("true", value) == 0) || (strcmp("1", value) == 0));
-}
-
-
-// --- audio_policy.conf file parsing
-//static
-uint32_t ConfigParsingUtils::parseOutputFlagNames(char *name)
-{
- uint32_t flag = 0;
-
- // it is OK to cast name to non const here as we are not going to use it after
- // strtok() modifies it
- char *flagName = strtok(name, "|");
- while (flagName != NULL) {
- if (strlen(flagName) != 0) {
- flag |= ConfigParsingUtils::stringToEnum(sOutputFlagNameToEnumTable,
- ARRAY_SIZE(sOutputFlagNameToEnumTable),
- flagName);
- }
- flagName = strtok(NULL, "|");
- }
- //force direct flag if offload flag is set: offloading implies a direct output stream
- // and all common behaviors are driven by checking only the direct flag
- // this should normally be set appropriately in the policy configuration file
- if ((flag & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
- flag |= AUDIO_OUTPUT_FLAG_DIRECT;
- }
-
- return flag;
-}
-
-//static
-uint32_t ConfigParsingUtils::parseInputFlagNames(char *name)
-{
- uint32_t flag = 0;
-
- // it is OK to cast name to non const here as we are not going to use it after
- // strtok() modifies it
- char *flagName = strtok(name, "|");
- while (flagName != NULL) {
- if (strlen(flagName) != 0) {
- flag |= stringToEnum(sInputFlagNameToEnumTable,
- ARRAY_SIZE(sInputFlagNameToEnumTable),
- flagName);
- }
- flagName = strtok(NULL, "|");
- }
- return flag;
-}
-
-//static
-audio_devices_t ConfigParsingUtils::parseDeviceNames(char *name)
-{
- uint32_t device = 0;
-
- char *devName = strtok(name, "|");
- while (devName != NULL) {
- if (strlen(devName) != 0) {
- device |= stringToEnum(sDeviceNameToEnumTable,
- ARRAY_SIZE(sDeviceNameToEnumTable),
- devName);
- }
- devName = strtok(NULL, "|");
- }
- return device;
-}
-
-}; // namespace android
diff --git a/services/audiopolicy/managerdefault/Gains.cpp b/services/audiopolicy/managerdefault/Gains.cpp
deleted file mode 100644
index 4aca26d..0000000
--- a/services/audiopolicy/managerdefault/Gains.cpp
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
- * 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 "AudioPolicyManager.h"
-
-#include <math.h>
-
-namespace android {
-
-const VolumeCurvePoint
-ApmGains::sDefaultVolumeCurve[ApmGains::VOLCNT] = {
- {1, -49.5f}, {33, -33.5f}, {66, -17.0f}, {100, 0.0f}
-};
-
-
-const VolumeCurvePoint
-ApmGains::sDefaultMediaVolumeCurve[ApmGains::VOLCNT] = {
- {1, -58.0f}, {20, -40.0f}, {60, -17.0f}, {100, 0.0f}
-};
-
-const VolumeCurvePoint
-ApmGains::sExtMediaSystemVolumeCurve[ApmGains::VOLCNT] = {
- {1, -58.0f}, {20, -40.0f}, {60, -21.0f}, {100, -10.0f}
-};
-
-const VolumeCurvePoint
-ApmGains::sSpeakerMediaVolumeCurve[ApmGains::VOLCNT] = {
- {1, -56.0f}, {20, -34.0f}, {60, -11.0f}, {100, 0.0f}
-};
-
-const VolumeCurvePoint
-ApmGains::sSpeakerMediaVolumeCurveDrc[ApmGains::VOLCNT] = {
- {1, -55.0f}, {20, -43.0f}, {86, -12.0f}, {100, 0.0f}
-};
-
-const VolumeCurvePoint
-ApmGains::sSpeakerSonificationVolumeCurve[ApmGains::VOLCNT] = {
- {1, -29.7f}, {33, -20.1f}, {66, -10.2f}, {100, 0.0f}
-};
-
-const VolumeCurvePoint
-ApmGains::sSpeakerSonificationVolumeCurveDrc[ApmGains::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
-ApmGains::sDefaultSystemVolumeCurve[ApmGains::VOLCNT] = {
- {1, -24.0f}, {33, -18.0f}, {66, -12.0f}, {100, -6.0f}
-};
-
-const VolumeCurvePoint
-ApmGains::sDefaultSystemVolumeCurveDrc[ApmGains::VOLCNT] = {
- {1, -34.0f}, {33, -24.0f}, {66, -15.0f}, {100, -6.0f}
-};
-
-const VolumeCurvePoint
-ApmGains::sHeadsetSystemVolumeCurve[ApmGains::VOLCNT] = {
- {1, -30.0f}, {33, -26.0f}, {66, -22.0f}, {100, -18.0f}
-};
-
-const VolumeCurvePoint
-ApmGains::sDefaultVoiceVolumeCurve[ApmGains::VOLCNT] = {
- {0, -42.0f}, {33, -28.0f}, {66, -14.0f}, {100, 0.0f}
-};
-
-const VolumeCurvePoint
-ApmGains::sSpeakerVoiceVolumeCurve[ApmGains::VOLCNT] = {
- {0, -24.0f}, {33, -16.0f}, {66, -8.0f}, {100, 0.0f}
-};
-
-const VolumeCurvePoint
-ApmGains::sLinearVolumeCurve[ApmGains::VOLCNT] = {
- {0, -96.0f}, {33, -68.0f}, {66, -34.0f}, {100, 0.0f}
-};
-
-const VolumeCurvePoint
-ApmGains::sSilentVolumeCurve[ApmGains::VOLCNT] = {
- {0, -96.0f}, {1, -96.0f}, {2, -96.0f}, {100, -96.0f}
-};
-
-const VolumeCurvePoint
-ApmGains::sFullScaleVolumeCurve[ApmGains::VOLCNT] = {
- {0, 0.0f}, {1, 0.0f}, {2, 0.0f}, {100, 0.0f}
-};
-
-const VolumeCurvePoint *ApmGains::sVolumeProfiles[AUDIO_STREAM_CNT]
- [ApmGains::DEVICE_CATEGORY_CNT] = {
- { // AUDIO_STREAM_VOICE_CALL
- ApmGains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET
- ApmGains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER
- ApmGains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_EARPIECE
- ApmGains::sDefaultMediaVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
- },
- { // AUDIO_STREAM_SYSTEM
- ApmGains::sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET
- ApmGains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER
- ApmGains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_EARPIECE
- ApmGains::sExtMediaSystemVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
- },
- { // AUDIO_STREAM_RING
- ApmGains::sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
- ApmGains::sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER
- ApmGains::sDefaultVolumeCurve, // DEVICE_CATEGORY_EARPIECE
- ApmGains::sExtMediaSystemVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
- },
- { // AUDIO_STREAM_MUSIC
- ApmGains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET
- ApmGains::sSpeakerMediaVolumeCurve, // DEVICE_CATEGORY_SPEAKER
- ApmGains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_EARPIECE
- ApmGains::sDefaultMediaVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
- },
- { // AUDIO_STREAM_ALARM
- ApmGains::sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
- ApmGains::sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER
- ApmGains::sDefaultVolumeCurve, // DEVICE_CATEGORY_EARPIECE
- ApmGains::sExtMediaSystemVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
- },
- { // AUDIO_STREAM_NOTIFICATION
- ApmGains::sDefaultVolumeCurve, // DEVICE_CATEGORY_HEADSET
- ApmGains::sSpeakerSonificationVolumeCurve, // DEVICE_CATEGORY_SPEAKER
- ApmGains::sDefaultVolumeCurve, // DEVICE_CATEGORY_EARPIECE
- ApmGains::sExtMediaSystemVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
- },
- { // AUDIO_STREAM_BLUETOOTH_SCO
- ApmGains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET
- ApmGains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER
- ApmGains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_EARPIECE
- ApmGains::sDefaultMediaVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
- },
- { // AUDIO_STREAM_ENFORCED_AUDIBLE
- ApmGains::sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET
- ApmGains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER
- ApmGains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_EARPIECE
- ApmGains::sExtMediaSystemVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
- },
- { // AUDIO_STREAM_DTMF
- ApmGains::sHeadsetSystemVolumeCurve, // DEVICE_CATEGORY_HEADSET
- ApmGains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_SPEAKER
- ApmGains::sDefaultSystemVolumeCurve, // DEVICE_CATEGORY_EARPIECE
- ApmGains::sExtMediaSystemVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
- },
- { // AUDIO_STREAM_TTS
- // "Transmitted Through Speaker": always silent except on DEVICE_CATEGORY_SPEAKER
- ApmGains::sSilentVolumeCurve, // DEVICE_CATEGORY_HEADSET
- ApmGains::sLinearVolumeCurve, // DEVICE_CATEGORY_SPEAKER
- ApmGains::sSilentVolumeCurve, // DEVICE_CATEGORY_EARPIECE
- ApmGains::sSilentVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
- },
- { // AUDIO_STREAM_ACCESSIBILITY
- ApmGains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET
- ApmGains::sSpeakerMediaVolumeCurve, // DEVICE_CATEGORY_SPEAKER
- ApmGains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_EARPIECE
- ApmGains::sDefaultMediaVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
- },
- { // AUDIO_STREAM_REROUTING
- ApmGains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_HEADSET
- ApmGains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_SPEAKER
- ApmGains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_EARPIECE
- ApmGains::sFullScaleVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
- },
- { // AUDIO_STREAM_PATCH
- ApmGains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_HEADSET
- ApmGains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_SPEAKER
- ApmGains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_EARPIECE
- ApmGains::sFullScaleVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
- },
-};
-
-//static
-audio_devices_t ApmGains::getDeviceForVolume(audio_devices_t device)
-{
- if (device == AUDIO_DEVICE_NONE) {
- // this happens when forcing a route update and no track is active on an output.
- // In this case the returned category is not important.
- device = AUDIO_DEVICE_OUT_SPEAKER;
- } else if (popcount(device) > 1) {
- // Multiple device selection is either:
- // - speaker + one other device: give priority to speaker in this case.
- // - one A2DP device + another device: happens with duplicated output. In this case
- // retain the device on the A2DP output as the other must not correspond to an active
- // selection if not the speaker.
- // - HDMI-CEC system audio mode only output: give priority to available item in order.
- if (device & AUDIO_DEVICE_OUT_SPEAKER) {
- device = AUDIO_DEVICE_OUT_SPEAKER;
- } else if (device & AUDIO_DEVICE_OUT_HDMI_ARC) {
- device = AUDIO_DEVICE_OUT_HDMI_ARC;
- } else if (device & AUDIO_DEVICE_OUT_AUX_LINE) {
- device = AUDIO_DEVICE_OUT_AUX_LINE;
- } else if (device & AUDIO_DEVICE_OUT_SPDIF) {
- device = AUDIO_DEVICE_OUT_SPDIF;
- } else {
- device = (audio_devices_t)(device & AUDIO_DEVICE_OUT_ALL_A2DP);
- }
- }
-
- /*SPEAKER_SAFE is an alias of SPEAKER for purposes of volume control*/
- if (device == AUDIO_DEVICE_OUT_SPEAKER_SAFE)
- device = AUDIO_DEVICE_OUT_SPEAKER;
-
- ALOGW_IF(popcount(device) != 1,
- "getDeviceForVolume() invalid device combination: %08x",
- device);
-
- return device;
-}
-
-//static
-ApmGains::device_category ApmGains::getDeviceCategory(audio_devices_t device)
-{
- switch(getDeviceForVolume(device)) {
- case AUDIO_DEVICE_OUT_EARPIECE:
- return ApmGains::DEVICE_CATEGORY_EARPIECE;
- case AUDIO_DEVICE_OUT_WIRED_HEADSET:
- case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
- case AUDIO_DEVICE_OUT_BLUETOOTH_SCO:
- case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
- case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
- case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
- return ApmGains::DEVICE_CATEGORY_HEADSET;
- case AUDIO_DEVICE_OUT_LINE:
- case AUDIO_DEVICE_OUT_AUX_DIGITAL:
- /*USB? Remote submix?*/
- return ApmGains::DEVICE_CATEGORY_EXT_MEDIA;
- case AUDIO_DEVICE_OUT_SPEAKER:
- case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT:
- case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
- case AUDIO_DEVICE_OUT_USB_ACCESSORY:
- case AUDIO_DEVICE_OUT_USB_DEVICE:
- case AUDIO_DEVICE_OUT_REMOTE_SUBMIX:
- default:
- return ApmGains::DEVICE_CATEGORY_SPEAKER;
- }
-}
-
-//static
-float ApmGains::volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc,
- int indexInUi)
-{
- ApmGains::device_category deviceCategory = ApmGains::getDeviceCategory(device);
- const VolumeCurvePoint *curve = streamDesc.mVolumeCurve[deviceCategory];
-
- // the volume index in the UI is relative to the min and max volume indices for this stream type
- int nbSteps = 1 + curve[ApmGains::VOLMAX].mIndex -
- curve[ApmGains::VOLMIN].mIndex;
- int volIdx = (nbSteps * (indexInUi - streamDesc.mIndexMin)) /
- (streamDesc.mIndexMax - streamDesc.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[ApmGains::VOLMIN].mIndex) { // out of bounds
- return 0.0f;
- } else if (volIdx < curve[ApmGains::VOLKNEE1].mIndex) {
- segment = 0;
- } else if (volIdx < curve[ApmGains::VOLKNEE2].mIndex) {
- segment = 1;
- } else if (volIdx <= curve[ApmGains::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;
-}
-
-
-
-AudioGain::AudioGain(int index, bool useInChannelMask)
-{
- mIndex = index;
- mUseInChannelMask = useInChannelMask;
- memset(&mGain, 0, sizeof(struct audio_gain));
-}
-
-void AudioGain::getDefaultConfig(struct audio_gain_config *config)
-{
- config->index = mIndex;
- config->mode = mGain.mode;
- config->channel_mask = mGain.channel_mask;
- if ((mGain.mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) {
- config->values[0] = mGain.default_value;
- } else {
- uint32_t numValues;
- if (mUseInChannelMask) {
- numValues = audio_channel_count_from_in_mask(mGain.channel_mask);
- } else {
- numValues = audio_channel_count_from_out_mask(mGain.channel_mask);
- }
- for (size_t i = 0; i < numValues; i++) {
- config->values[i] = mGain.default_value;
- }
- }
- if ((mGain.mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) {
- config->ramp_duration_ms = mGain.min_ramp_ms;
- }
-}
-
-status_t AudioGain::checkConfig(const struct audio_gain_config *config)
-{
- if ((config->mode & ~mGain.mode) != 0) {
- return BAD_VALUE;
- }
- if ((config->mode & AUDIO_GAIN_MODE_JOINT) == AUDIO_GAIN_MODE_JOINT) {
- if ((config->values[0] < mGain.min_value) ||
- (config->values[0] > mGain.max_value)) {
- return BAD_VALUE;
- }
- } else {
- if ((config->channel_mask & ~mGain.channel_mask) != 0) {
- return BAD_VALUE;
- }
- uint32_t numValues;
- if (mUseInChannelMask) {
- numValues = audio_channel_count_from_in_mask(config->channel_mask);
- } else {
- numValues = audio_channel_count_from_out_mask(config->channel_mask);
- }
- for (size_t i = 0; i < numValues; i++) {
- if ((config->values[i] < mGain.min_value) ||
- (config->values[i] > mGain.max_value)) {
- return BAD_VALUE;
- }
- }
- }
- if ((config->mode & AUDIO_GAIN_MODE_RAMP) == AUDIO_GAIN_MODE_RAMP) {
- if ((config->ramp_duration_ms < mGain.min_ramp_ms) ||
- (config->ramp_duration_ms > mGain.max_ramp_ms)) {
- return BAD_VALUE;
- }
- }
- return NO_ERROR;
-}
-
-void AudioGain::dump(int fd, int spaces, int index) const
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
- snprintf(buffer, SIZE, "%*sGain %d:\n", spaces, "", index+1);
- result.append(buffer);
- snprintf(buffer, SIZE, "%*s- mode: %08x\n", spaces, "", mGain.mode);
- result.append(buffer);
- snprintf(buffer, SIZE, "%*s- channel_mask: %08x\n", spaces, "", mGain.channel_mask);
- result.append(buffer);
- snprintf(buffer, SIZE, "%*s- min_value: %d mB\n", spaces, "", mGain.min_value);
- result.append(buffer);
- snprintf(buffer, SIZE, "%*s- max_value: %d mB\n", spaces, "", mGain.max_value);
- result.append(buffer);
- snprintf(buffer, SIZE, "%*s- default_value: %d mB\n", spaces, "", mGain.default_value);
- result.append(buffer);
- snprintf(buffer, SIZE, "%*s- step_value: %d mB\n", spaces, "", mGain.step_value);
- result.append(buffer);
- snprintf(buffer, SIZE, "%*s- min_ramp_ms: %d ms\n", spaces, "", mGain.min_ramp_ms);
- result.append(buffer);
- snprintf(buffer, SIZE, "%*s- max_ramp_ms: %d ms\n", spaces, "", mGain.max_ramp_ms);
- result.append(buffer);
-
- write(fd, result.string(), result.size());
-}
-
-
-// --- StreamDescriptor class implementation
-
-StreamDescriptor::StreamDescriptor()
- : mIndexMin(0), mIndexMax(1), mCanBeMuted(true)
-{
- mIndexCur.add(AUDIO_DEVICE_OUT_DEFAULT, 0);
-}
-
-int StreamDescriptor::getVolumeIndex(audio_devices_t device)
-{
- device = ApmGains::getDeviceForVolume(device);
- // there is always a valid entry for AUDIO_DEVICE_OUT_DEFAULT
- if (mIndexCur.indexOfKey(device) < 0) {
- device = AUDIO_DEVICE_OUT_DEFAULT;
- }
- return mIndexCur.valueFor(device);
-}
-
-void StreamDescriptor::dump(int fd)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
- snprintf(buffer, SIZE, "%s %02d %02d ",
- mCanBeMuted ? "true " : "false", mIndexMin, mIndexMax);
- result.append(buffer);
- for (size_t i = 0; i < mIndexCur.size(); i++) {
- snprintf(buffer, SIZE, "%04x : %02d, ",
- mIndexCur.keyAt(i),
- mIndexCur.valueAt(i));
- result.append(buffer);
- }
- result.append("\n");
-
- write(fd, result.string(), result.size());
-}
-
-}; // namespace android
diff --git a/services/audiopolicy/managerdefault/Gains.h b/services/audiopolicy/managerdefault/Gains.h
deleted file mode 100644
index b4ab129..0000000
--- a/services/audiopolicy/managerdefault/Gains.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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.
- */
-
-namespace android {
-
-class VolumeCurvePoint
-{
-public:
- int mIndex;
- float mDBAttenuation;
-};
-
-class StreamDescriptor;
-
-class ApmGains
-{
-public :
- // 4 points to define the volume attenuation curve, each characterized by the volume
- // index (from 0 to 100) at which they apply, and the attenuation in dB at that index.
- // we use 100 steps to avoid rounding errors when computing the volume in volIndexToAmpl()
- enum { VOLMIN = 0, VOLKNEE1 = 1, VOLKNEE2 = 2, VOLMAX = 3, VOLCNT = 4};
-
- // device categories used for volume curve management.
- enum device_category {
- DEVICE_CATEGORY_HEADSET,
- DEVICE_CATEGORY_SPEAKER,
- DEVICE_CATEGORY_EARPIECE,
- DEVICE_CATEGORY_EXT_MEDIA,
- DEVICE_CATEGORY_CNT
- };
-
- // returns the category the device belongs to with regard to volume curve management
- static ApmGains::device_category getDeviceCategory(audio_devices_t device);
-
- // extract one device relevant for volume control from multiple device selection
- static audio_devices_t getDeviceForVolume(audio_devices_t device);
-
- static float volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc,
- int indexInUi);
-
- // default volume curve
- static const VolumeCurvePoint sDefaultVolumeCurve[ApmGains::VOLCNT];
- // default volume curve for media strategy
- static const VolumeCurvePoint sDefaultMediaVolumeCurve[ApmGains::VOLCNT];
- // volume curve for non-media audio on ext media outputs (HDMI, Line, etc)
- static const VolumeCurvePoint sExtMediaSystemVolumeCurve[ApmGains::VOLCNT];
- // volume curve for media strategy on speakers
- static const VolumeCurvePoint sSpeakerMediaVolumeCurve[ApmGains::VOLCNT];
- static const VolumeCurvePoint sSpeakerMediaVolumeCurveDrc[ApmGains::VOLCNT];
- // volume curve for sonification strategy on speakers
- static const VolumeCurvePoint sSpeakerSonificationVolumeCurve[ApmGains::VOLCNT];
- static const VolumeCurvePoint sSpeakerSonificationVolumeCurveDrc[ApmGains::VOLCNT];
- static const VolumeCurvePoint sDefaultSystemVolumeCurve[ApmGains::VOLCNT];
- static const VolumeCurvePoint sDefaultSystemVolumeCurveDrc[ApmGains::VOLCNT];
- static const VolumeCurvePoint sHeadsetSystemVolumeCurve[ApmGains::VOLCNT];
- static const VolumeCurvePoint sDefaultVoiceVolumeCurve[ApmGains::VOLCNT];
- static const VolumeCurvePoint sSpeakerVoiceVolumeCurve[ApmGains::VOLCNT];
- static const VolumeCurvePoint sLinearVolumeCurve[ApmGains::VOLCNT];
- static const VolumeCurvePoint sSilentVolumeCurve[ApmGains::VOLCNT];
- static const VolumeCurvePoint sFullScaleVolumeCurve[ApmGains::VOLCNT];
- // default volume curves per stream and device category. See initializeVolumeCurves()
- static const VolumeCurvePoint *sVolumeProfiles[AUDIO_STREAM_CNT][ApmGains::DEVICE_CATEGORY_CNT];
-};
-
-
-class AudioGain: public RefBase
-{
-public:
- AudioGain(int index, bool useInChannelMask);
- virtual ~AudioGain() {}
-
- void dump(int fd, int spaces, int index) const;
-
- void getDefaultConfig(struct audio_gain_config *config);
- status_t checkConfig(const struct audio_gain_config *config);
- int mIndex;
- struct audio_gain mGain;
- bool mUseInChannelMask;
-};
-
-
-// stream descriptor used for volume control
-class StreamDescriptor
-{
-public:
- StreamDescriptor();
-
- int getVolumeIndex(audio_devices_t device);
- void dump(int fd);
-
- int mIndexMin; // min volume index
- int mIndexMax; // max volume index
- KeyedVector<audio_devices_t, int> mIndexCur; // current volume index per device
- bool mCanBeMuted; // true is the stream can be muted
-
- const VolumeCurvePoint *mVolumeCurve[ApmGains::DEVICE_CATEGORY_CNT];
-};
-
-}; // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index eb9116d..00f188f 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -532,7 +532,7 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
mLock.unlock();
svc.clear();
mLock.lock();
- if (!exitPending() && mAudioCommands.isEmpty()) {
+ if (!exitPending() && (mAudioCommands.isEmpty() || waitTime != INT64_MAX)) {
// release delayed commands wake lock
release_wake_lock(mName.string());
ALOGV("AudioCommandThread() going to sleep");