Introduce notion of active devices.
The list of active devices is populated by the Engine.
The active devices are selected with the following rules:
1) If all of the preferred devices for media are available then they
will all be used for the output.
2) If not, then the last connected removable device will be used.
3) If there are no removable devices then the default audio policy rule
will be used.
In this CL, we only add a function to query active devices. In a future
CL we will use this list when opening an output.
Test: dumpsys
Bug: 160352965
Change-Id: I12f9ed24e1404264ad7055f3a7c73b444b33ee1a
diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h
index 4510f63..3e42e2d 100644
--- a/services/audiopolicy/engine/common/include/EngineBase.h
+++ b/services/audiopolicy/engine/common/include/EngineBase.h
@@ -151,7 +151,23 @@
status_t getDevicesForRoleAndCapturePreset(audio_source_t audioSource,
device_role_t role, AudioDeviceTypeAddrVector &devices) const override;
+ DeviceVector getActiveMediaDevices(const DeviceVector& availableDevices) const override;
+
private:
+ /**
+ * Get media devices as the given role
+ *
+ * @param role the audio devices role
+ * @param availableDevices all available devices
+ * @param devices the DeviceVector to store devices as the given role
+ * @return NO_ERROR if all devices associated to the given role are present in available devices
+ * NAME_NO_FOUND if there is no strategy for media or there are no devices associate to
+ * the given role
+ * NOT_ENOUGH_DATA if not all devices as given role are present in available devices
+ */
+ status_t getMediaDevicesForRole(device_role_t role, const DeviceVector& availableDevices,
+ DeviceVector& devices) const;
+
AudioPolicyManagerObserver *mApmObserver = nullptr;
ProductStrategyMap mProductStrategies;
diff --git a/services/audiopolicy/engine/common/include/LastRemovableMediaDevices.h b/services/audiopolicy/engine/common/include/LastRemovableMediaDevices.h
index a3053a4..d7f8b1e 100644
--- a/services/audiopolicy/engine/common/include/LastRemovableMediaDevices.h
+++ b/services/audiopolicy/engine/common/include/LastRemovableMediaDevices.h
@@ -36,6 +36,8 @@
void setRemovableMediaDevices(sp<DeviceDescriptor> desc, audio_policy_dev_state_t state);
std::vector<audio_devices_t> getLastRemovableMediaDevices(
device_out_group_t group = GROUP_NONE) const;
+ sp<DeviceDescriptor> getLastRemovableMediaDevice(
+ const DeviceVector& excludedDevices, device_out_group_t group = GROUP_NONE) const;
private:
struct DeviceGroupDescriptor {
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index 8c7fb97..2137dd0 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -588,6 +588,45 @@
return NO_ERROR;
}
+status_t EngineBase::getMediaDevicesForRole(device_role_t role,
+ const DeviceVector& availableDevices, DeviceVector& devices) const
+{
+ product_strategy_t strategy = getProductStrategyByName("STRATEGY_MEDIA" /*name*/);
+ if (strategy == PRODUCT_STRATEGY_NONE) {
+ strategy = getProductStrategyForStream(AUDIO_STREAM_MUSIC);
+ }
+ if (strategy == PRODUCT_STRATEGY_NONE) {
+ return NAME_NOT_FOUND;
+ }
+ AudioDeviceTypeAddrVector deviceAddrVec;
+ status_t status = getDevicesForRoleAndStrategy(strategy, role, deviceAddrVec);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ devices = availableDevices.getDevicesFromDeviceTypeAddrVec(deviceAddrVec);
+ return deviceAddrVec.size() == devices.size() ? NO_ERROR : NOT_ENOUGH_DATA;
+}
+
+DeviceVector EngineBase::getActiveMediaDevices(const DeviceVector& availableDevices) const
+{
+ // The priority of active devices as follows:
+ // 1: the available preferred devices for media
+ // 2: the latest connected removable media device that is enabled
+ DeviceVector activeDevices;
+ if (getMediaDevicesForRole(
+ DEVICE_ROLE_PREFERRED, availableDevices, activeDevices) != NO_ERROR) {
+ activeDevices.clear();
+ DeviceVector disabledDevices;
+ getMediaDevicesForRole(DEVICE_ROLE_DISABLED, availableDevices, disabledDevices);
+ sp<DeviceDescriptor> device =
+ mLastRemovableMediaDevices.getLastRemovableMediaDevice(disabledDevices);
+ if (device != nullptr) {
+ activeDevices.add(device);
+ }
+ }
+ return activeDevices;
+}
+
void EngineBase::dump(String8 *dst) const
{
mProductStrategies.dump(dst, 2);
diff --git a/services/audiopolicy/engine/common/src/LastRemovableMediaDevices.cpp b/services/audiopolicy/engine/common/src/LastRemovableMediaDevices.cpp
index 96cc140..b3f8947 100644
--- a/services/audiopolicy/engine/common/src/LastRemovableMediaDevices.cpp
+++ b/services/audiopolicy/engine/common/src/LastRemovableMediaDevices.cpp
@@ -55,6 +55,17 @@
return ret;
}
+sp<DeviceDescriptor> LastRemovableMediaDevices::getLastRemovableMediaDevice(
+ const DeviceVector& excludedDevices, device_out_group_t group) const {
+ for (auto iter = mMediaDevices.begin(); iter != mMediaDevices.end(); ++iter) {
+ if ((group == GROUP_NONE || group == getDeviceOutGroup((iter->desc)->type())) &&
+ !excludedDevices.contains(iter->desc)) {
+ return iter->desc;
+ }
+ }
+ return nullptr;
+}
+
device_out_group_t LastRemovableMediaDevices::getDeviceOutGroup(audio_devices_t device) const
{
switch (device) {
diff --git a/services/audiopolicy/engine/interface/EngineInterface.h b/services/audiopolicy/engine/interface/EngineInterface.h
index f64608d..a9b536b 100644
--- a/services/audiopolicy/engine/interface/EngineInterface.h
+++ b/services/audiopolicy/engine/interface/EngineInterface.h
@@ -403,6 +403,12 @@
virtual status_t getDevicesForRoleAndCapturePreset(audio_source_t audioSource,
device_role_t role, AudioDeviceTypeAddrVector &devices) const = 0;
+ /**
+ * @brief getActiveMediaDevices returns which devices will most likely to be used for media
+ * @param availableDevices all available devices
+ * @return collection of active devices
+ */
+ virtual DeviceVector getActiveMediaDevices(const DeviceVector& availableDevices) const = 0;
virtual void dump(String8 *dst) const = 0;