Add last connected device concept
When connecting multiple audio devices,
Media and Sonification sounds comes out of the last connected device,
not a high-priority device.
Test: play music
Test: connect wired earphone // sound : wired earphone
Test: connect usb earphone // sound : usb earphone, not the wired earphone(high-priority)
Test: connect bluetooth headset // sound : bluetooth headset
Test: disconnect bluetooth headset // sound : usb earphone, not the wired earphone(high-priority)
Bug: 135749685
Change-Id: I579a04a04c97cc846b88e54fa83cdf3dad0b5cee
Signed-off-by: Baekgyeong Kim <baek.kim@samsung.com>
diff --git a/services/audiopolicy/engine/common/Android.bp b/services/audiopolicy/engine/common/Android.bp
old mode 100644
new mode 100755
index b87c71d..a1c69f2
--- a/services/audiopolicy/engine/common/Android.bp
+++ b/services/audiopolicy/engine/common/Android.bp
@@ -25,6 +25,7 @@
"src/ProductStrategy.cpp",
"src/VolumeCurve.cpp",
"src/VolumeGroup.cpp",
+ "src/LastRemovableMediaDevices.cpp",
],
cflags: [
"-Wall",
diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h
old mode 100644
new mode 100755
index fca9a60..4cf0b90
--- a/services/audiopolicy/engine/common/include/EngineBase.h
+++ b/services/audiopolicy/engine/common/include/EngineBase.h
@@ -20,6 +20,7 @@
#include <EngineInterface.h>
#include <ProductStrategy.h>
#include <VolumeGroup.h>
+#include <LastRemovableMediaDevices.h>
namespace android {
namespace audio_policy {
@@ -49,10 +50,8 @@
return mForceUse[usage];
}
android::status_t setDeviceConnectionState(const sp<DeviceDescriptor> /*devDesc*/,
- audio_policy_dev_state_t /*state*/) override
- {
- return NO_ERROR;
- }
+ audio_policy_dev_state_t /*state*/) override;
+
product_strategy_t getProductStrategyForAttributes(
const audio_attributes_t &attr) const override;
@@ -86,6 +85,12 @@
status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups) const override;
+ std::vector<audio_devices_t> getLastRemovableMediaDevices(
+ device_out_group_t group = GROUP_NONE) const
+ {
+ return mLastRemovableMediaDevices.getLastRemovableMediaDevices(group);
+ }
+
void dump(String8 *dst) const override;
@@ -115,11 +120,12 @@
status_t restoreOriginVolumeCurve(audio_stream_type_t stream);
- private:
+private:
AudioPolicyManagerObserver *mApmObserver = nullptr;
ProductStrategyMap mProductStrategies;
VolumeGroupMap mVolumeGroups;
+ LastRemovableMediaDevices mLastRemovableMediaDevices;
audio_mode_t mPhoneState = AUDIO_MODE_NORMAL; /**< current phone state. */
/** current forced use configuration. */
diff --git a/services/audiopolicy/engine/common/include/LastRemovableMediaDevices.h b/services/audiopolicy/engine/common/include/LastRemovableMediaDevices.h
new file mode 100755
index 0000000..88ac7a1
--- /dev/null
+++ b/services/audiopolicy/engine/common/include/LastRemovableMediaDevices.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#ifndef ANDROID_LAST_REMOVABLE_MEDIA_DEVICES_H
+#define ANDROID_LAST_REMOVABLE_MEDIA_DEVICES_H
+
+#include <vector>
+#include <HwModule.h>
+#include <system/audio_policy.h>
+
+namespace android {
+
+typedef enum {
+ GROUP_NONE = -1,
+ GROUP_WIRED,
+ GROUP_BT_A2DP,
+ NUM_GROUP
+} device_out_group_t;
+
+class LastRemovableMediaDevices
+{
+public:
+ 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;
+
+private:
+ struct DeviceGroupDescriptor {
+ sp<DeviceDescriptor> desc;
+ device_out_group_t group;
+ };
+ std::vector<DeviceGroupDescriptor> mMediaDevices;
+
+ device_out_group_t getDeviceOutGroup(audio_devices_t device) const;
+};
+
+} // namespace android
+
+#endif // ANDROID_LAST_REMOVABLE_MEDIA_DEVICES_H
\ No newline at end of file
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index 840eb34..45c43d8 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -63,6 +63,17 @@
return NO_ERROR;
}
+status_t EngineBase::setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
+ audio_policy_dev_state_t state)
+{
+ audio_devices_t deviceType = devDesc->type();
+ if ((deviceType != AUDIO_DEVICE_NONE) && audio_is_output_device(deviceType)) {
+ mLastRemovableMediaDevices.setRemovableMediaDevices(devDesc, state);
+ }
+
+ return NO_ERROR;
+}
+
product_strategy_t EngineBase::getProductStrategyForAttributes(const audio_attributes_t &attr) const
{
return mProductStrategies.getProductStrategyForAttributes(attr);
diff --git a/services/audiopolicy/engine/common/src/LastRemovableMediaDevices.cpp b/services/audiopolicy/engine/common/src/LastRemovableMediaDevices.cpp
new file mode 100755
index 0000000..0eb22ce
--- /dev/null
+++ b/services/audiopolicy/engine/common/src/LastRemovableMediaDevices.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2019 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/LastRemovableMediaDevices"
+//#define LOG_NDEBUG 0
+
+#include "LastRemovableMediaDevices.h"
+#include <log/log.h>
+
+namespace android {
+
+void LastRemovableMediaDevices::setRemovableMediaDevices(sp<DeviceDescriptor> desc,
+ audio_policy_dev_state_t state)
+{
+ if (desc == nullptr) {
+ return;
+ } else {
+ if ((state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) &&
+ (getDeviceOutGroup(desc->type()) != GROUP_NONE)) {
+ setRemovableMediaDevices(desc, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE);
+ mMediaDevices.insert(mMediaDevices.begin(), {desc, getDeviceOutGroup(desc->type())});
+ } else if (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
+ for (auto iter = mMediaDevices.begin(); iter != mMediaDevices.end(); ++iter) {
+ if ((iter->desc)->equals(desc)) {
+ mMediaDevices.erase(iter);
+ break;
+ }
+ }
+ }
+ }
+}
+
+std::vector<audio_devices_t> LastRemovableMediaDevices::getLastRemovableMediaDevices(
+ device_out_group_t group) const
+{
+ std::vector<audio_devices_t> ret;
+ for (auto iter = mMediaDevices.begin(); iter != mMediaDevices.end(); ++iter) {
+ if ((group == GROUP_NONE) || (group == getDeviceOutGroup((iter->desc)->type()))) {
+ ret.push_back((iter->desc)->type());
+ }
+ }
+ return ret;
+}
+
+device_out_group_t LastRemovableMediaDevices::getDeviceOutGroup(audio_devices_t device) const
+{
+ switch (device) {
+ case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
+ case AUDIO_DEVICE_OUT_LINE:
+ case AUDIO_DEVICE_OUT_WIRED_HEADSET:
+ case AUDIO_DEVICE_OUT_USB_HEADSET:
+ case AUDIO_DEVICE_OUT_USB_ACCESSORY:
+ case AUDIO_DEVICE_OUT_USB_DEVICE:
+ case AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET:
+ return GROUP_WIRED;
+ case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
+ case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
+ case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
+ return GROUP_BT_A2DP;
+ default:
+ return GROUP_NONE;
+ }
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index 0a88685..752ba92 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -176,7 +176,7 @@
return mPolicyParameterMgr->setAvailableInputDevices(
deviceTypesToBitMask(getApmObserver()->getAvailableInputDevices().types()));
}
- return BAD_TYPE;
+ return EngineBase::setDeviceConnectionState(devDesc, state);
}
status_t Engine::loadAudioPolicyEngineConfig()
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
old mode 100644
new mode 100755
index 9dc0d64..de7e7ce
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -386,22 +386,20 @@
devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID);
}
if ((devices2.isEmpty()) &&
- (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
- outputs.isA2dpSupported()) {
- devices2 = availableOutputDevices.getFirstDevicesFromTypes({
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES,
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER});
- }
- if ((devices2.isEmpty()) &&
(getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) == AUDIO_POLICY_FORCE_SPEAKER)) {
devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
}
- if (devices2.isEmpty()) {
- devices2 = availableOutputDevices.getFirstDevicesFromTypes({
- AUDIO_DEVICE_OUT_WIRED_HEADPHONE, AUDIO_DEVICE_OUT_LINE,
- AUDIO_DEVICE_OUT_WIRED_HEADSET, AUDIO_DEVICE_OUT_USB_HEADSET,
- AUDIO_DEVICE_OUT_USB_ACCESSORY, AUDIO_DEVICE_OUT_USB_DEVICE,
- AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET});
+ if (devices2.isEmpty() && (getLastRemovableMediaDevices().size() > 0)) {
+ if ((getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
+ outputs.isA2dpSupported()) {
+ // Get the last connected device of wired and bluetooth a2dp
+ devices2 = availableOutputDevices.getFirstDevicesFromTypes(
+ getLastRemovableMediaDevices());
+ } else {
+ // Get the last connected device of wired except bluetooth a2dp
+ devices2 = availableOutputDevices.getFirstDevicesFromTypes(
+ getLastRemovableMediaDevices(GROUP_WIRED));
+ }
}
if ((devices2.isEmpty()) && (strategy != STRATEGY_SONIFICATION)) {
// no sonification on aux digital (e.g. HDMI)