Merge "APM: support product strategy routing"
diff --git a/media/audioserver/Android.mk b/media/audioserver/Android.mk
index 6697cb5..e33804d 100644
--- a/media/audioserver/Android.mk
+++ b/media/audioserver/Android.mk
@@ -40,21 +40,6 @@
frameworks/av/media/libmedia \
external/sonic \
-# If AUDIOSERVER_MULTILIB in device.mk is non-empty then it is used to control
-# the LOCAL_MULTILIB for all audioserver exclusive libraries.
-# This is relevant for 64 bit architectures where either or both
-# 32 and 64 bit libraries may be built.
-#
-# AUDIOSERVER_MULTILIB may be set as follows:
-# 32 to build 32 bit audioserver libraries and 32 bit audioserver.
-# 64 to build 64 bit audioserver libraries and 64 bit audioserver.
-# both to build both 32 bit and 64 bit libraries,
-# and use primary target architecture (32 or 64) for audioserver.
-# first to build libraries and audioserver for the primary target architecture only.
-# <empty> to build both 32 and 64 bit libraries and primary target audioserver.
-
-LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
-
LOCAL_MODULE := audioserver
LOCAL_INIT_RC := audioserver.rc
diff --git a/media/codec2/vndk/platform/C2BqBuffer.cpp b/media/codec2/vndk/platform/C2BqBuffer.cpp
index 8304f74..62936f6 100644
--- a/media/codec2/vndk/platform/C2BqBuffer.cpp
+++ b/media/codec2/vndk/platform/C2BqBuffer.cpp
@@ -576,10 +576,11 @@
}
}
int migrated = 0;
+ // poolDatas dtor should not be called during lock is held.
+ std::shared_ptr<C2BufferQueueBlockPoolData>
+ poolDatas[NUM_BUFFER_SLOTS];
{
sp<GraphicBuffer> buffers[NUM_BUFFER_SLOTS];
- std::weak_ptr<C2BufferQueueBlockPoolData>
- poolDatas[NUM_BUFFER_SLOTS];
std::scoped_lock<std::mutex> lock(mMutex);
bool noInit = false;
for (int i = 0; i < NUM_BUFFER_SLOTS; ++i) {
diff --git a/media/libaudioclient/AudioEffect.cpp b/media/libaudioclient/AudioEffect.cpp
index 1cc5fe6..b3862be 100644
--- a/media/libaudioclient/AudioEffect.cpp
+++ b/media/libaudioclient/AudioEffect.cpp
@@ -171,7 +171,7 @@
ALOGV("set() %p OK effect: %s id: %d status %d enabled %d pid %d", this, mDescriptor.name, mId,
mStatus, mEnabled, mClientPid);
- if (mSessionId > AUDIO_SESSION_OUTPUT_MIX) {
+ if (!audio_is_global_session(mSessionId)) {
AudioSystem::acquireAudioSessionId(mSessionId, mClientPid);
}
@@ -184,7 +184,7 @@
ALOGV("Destructor %p", this);
if (mStatus == NO_ERROR || mStatus == ALREADY_EXISTS) {
- if (mSessionId > AUDIO_SESSION_OUTPUT_MIX) {
+ if (!audio_is_global_session(mSessionId)) {
AudioSystem::releaseAudioSessionId(mSessionId, mClientPid);
}
if (mIEffect != NULL) {
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index 51138c8..ab0cb63 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -341,6 +341,7 @@
EXPORT const char* AMEDIAFORMAT_KEY_LEVEL = "level";
EXPORT const char* AMEDIAFORMAT_KEY_LOCATION = "location";
EXPORT const char* AMEDIAFORMAT_KEY_LOOP = "loop";
+EXPORT const char* AMEDIAFORMAT_KEY_LOW_LATENCY = "low-latency";
EXPORT const char* AMEDIAFORMAT_KEY_LYRICIST = "lyricist";
EXPORT const char* AMEDIAFORMAT_KEY_MANUFACTURER = "manufacturer";
EXPORT const char* AMEDIAFORMAT_KEY_MAX_BIT_RATE = "max-bitrate";
diff --git a/media/ndk/include/media/NdkMediaFormat.h b/media/ndk/include/media/NdkMediaFormat.h
index 41c2378..ed77aac 100644
--- a/media/ndk/include/media/NdkMediaFormat.h
+++ b/media/ndk/include/media/NdkMediaFormat.h
@@ -294,6 +294,13 @@
#endif /* __ANDROID_API__ >= 29 */
+#if __ANDROID_API__ >= 30
+/**
+ * Available since API level 30.
+ */
+extern const char* AMEDIAFORMAT_KEY_LOW_LATENCY __INTRODUCED_IN(30);
+#endif /* __ANDROID_API__ >= 30 */
+
__END_DECLS
#endif // _NDK_MEDIA_FORMAT_H
diff --git a/media/ndk/libmediandk.map.txt b/media/ndk/libmediandk.map.txt
index 7531578..29f1da8 100644
--- a/media/ndk/libmediandk.map.txt
+++ b/media/ndk/libmediandk.map.txt
@@ -105,6 +105,7 @@
AMEDIAFORMAT_KEY_LEVEL; # var introduced=28
AMEDIAFORMAT_KEY_LOCATION; # var introduced=29
AMEDIAFORMAT_KEY_LOOP; # var introduced=29
+ AMEDIAFORMAT_KEY_LOW_LATENCY; # var introduced=30
AMEDIAFORMAT_KEY_LYRICIST; # var introduced=29
AMEDIAFORMAT_KEY_MANUFACTURER; # var introduced=29
AMEDIAFORMAT_KEY_MAX_BIT_RATE; # var introduced=29
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index b132782..a77311e 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -181,12 +181,19 @@
}
bool modifyDefaultAudioEffectsAllowed() {
+ return modifyDefaultAudioEffectsAllowed(
+ IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid());
+}
+
+bool modifyDefaultAudioEffectsAllowed(pid_t pid, uid_t uid) {
+ if (isAudioServerUid(IPCThreadState::self()->getCallingUid())) return true;
+
static const String16 sModifyDefaultAudioEffectsAllowed(
"android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS");
// IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
- bool ok = PermissionCache::checkCallingPermission(sModifyDefaultAudioEffectsAllowed);
-
- if (!ok) ALOGE("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS");
+ bool ok = PermissionCache::checkPermission(sModifyDefaultAudioEffectsAllowed, pid, uid);
+ ALOGE_IF(!ok, "%s(): android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS denied for uid %d",
+ __func__, uid);
return ok;
}
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index 9e852fd..e467058 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -87,6 +87,7 @@
bool modifyAudioRoutingAllowed();
bool modifyAudioRoutingAllowed(pid_t pid, uid_t uid);
bool modifyDefaultAudioEffectsAllowed();
+bool modifyDefaultAudioEffectsAllowed(pid_t pid, uid_t uid);
bool dumpAllowed();
bool modifyPhoneStateAllowed(pid_t pid, uid_t uid);
bool bypassInterruptionPolicyAllowed(pid_t pid, uid_t uid);
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 6ecb356..7b01690 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2969,7 +2969,7 @@
Mutex::Autolock _l(t->mLock);
for (size_t j = 0; j < t->mEffectChains.size(); j++) {
sp<EffectChain> ec = t->mEffectChains[j];
- if (ec->sessionId() > AUDIO_SESSION_OUTPUT_MIX) {
+ if (!audio_is_global_session(ec->sessionId())) {
chains.push(ec);
}
}
@@ -3371,6 +3371,13 @@
lStatus = BAD_VALUE;
goto Exit;
}
+ } else if (sessionId == AUDIO_SESSION_DEVICE) {
+ if (!modifyDefaultAudioEffectsAllowed(pid, callingUid)) {
+ ALOGE("%s: device effect permission denied for uid %d", __func__, callingUid);
+ lStatus = PERMISSION_DENIED;
+ goto Exit;
+ }
+ //TODO: add check on device ID when added to arguments
} else {
// general sessionId.
@@ -3406,7 +3413,7 @@
// check recording permission for visualizer
if ((memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) &&
// TODO: Do we need to start/stop op - i.e. is there recording being performed?
- !recordingAllowed(opPackageName, pid, IPCThreadState::self()->getCallingUid())) {
+ !recordingAllowed(opPackageName, pid, callingUid)) {
lStatus = PERMISSION_DENIED;
goto Exit;
}
@@ -3504,7 +3511,7 @@
sp<Client> client = registerPid(pid);
// create effect on selected output thread
- bool pinned = (sessionId > AUDIO_SESSION_OUTPUT_MIX) && isSessionAcquired_l(sessionId);
+ bool pinned = !audio_is_global_session(sessionId) && isSessionAcquired_l(sessionId);
handle = thread->createEffect_l(client, effectClient, priority, sessionId,
&desc, enabled, &lStatus, pinned);
if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 1355b1b..eda9887 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -637,7 +637,7 @@
mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
// Insert effect:
- // - in session AUDIO_SESSION_OUTPUT_MIX or AUDIO_SESSION_OUTPUT_STAGE,
+ // - in global sessions (e.g AUDIO_SESSION_OUTPUT_MIX),
// always overwrites output buffer: input buffer == output buffer
// - in other sessions:
// last effect in the chain accumulates in output buffer: input buffer != output buffer
@@ -2062,14 +2062,12 @@
ALOGW("process_l(): cannot promote mixer thread");
return;
}
- bool isGlobalSession = (mSessionId == AUDIO_SESSION_OUTPUT_MIX) ||
- (mSessionId == AUDIO_SESSION_OUTPUT_STAGE);
// never process effects when:
// - on an OFFLOAD thread
// - no more tracks are on the session and the effect tail has been rendered
bool doProcess = (thread->type() != ThreadBase::OFFLOAD)
&& (thread->type() != ThreadBase::MMAP);
- if (!isGlobalSession) {
+ if (!audio_is_global_session(mSessionId)) {
bool tracksOnSession = (trackCnt() != 0);
if (!tracksOnSession && mTailBufferCount == 0) {
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 357e432..e70c776 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1164,7 +1164,7 @@
// and applications not using global effects.
// Enabling post processing in AUDIO_SESSION_OUTPUT_STAGE session does not affect
// global effects
- if ((sessionId != AUDIO_SESSION_OUTPUT_MIX) && (sessionId != AUDIO_SESSION_OUTPUT_STAGE)) {
+ if (!audio_is_global_session(sessionId)) {
setEffectSuspended_l(NULL, enabled, AUDIO_SESSION_OUTPUT_MIX);
}
}
@@ -1179,8 +1179,9 @@
status_t AudioFlinger::RecordThread::checkEffectCompatibility_l(
const effect_descriptor_t *desc, audio_session_t sessionId)
{
- // No global effect sessions on record threads
- if (sessionId == AUDIO_SESSION_OUTPUT_MIX || sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
+ // No global output effect sessions on record threads
+ if (sessionId == AUDIO_SESSION_OUTPUT_MIX
+ || sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
ALOGW("checkEffectCompatibility_l(): global effect %s on record thread %s",
desc->name, mThreadName);
return BAD_VALUE;
@@ -1254,6 +1255,13 @@
" on output stage session", desc->name);
return BAD_VALUE;
}
+ } else if (sessionId == AUDIO_SESSION_DEVICE) {
+ // only post processing on output stage session
+ if ((desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_POST_PROC) {
+ ALOGW("checkEffectCompatibility_l(): non post processing effect %s not allowed"
+ " on device session", desc->name);
+ return BAD_VALUE;
+ }
} else {
// no restriction on effects applied on non fast tracks
if ((hasAudioSession_l(sessionId) & ThreadBase::FAST_SESSION) == 0) {
@@ -1295,7 +1303,7 @@
return BAD_VALUE;
}
#endif
- if ((sessionId == AUDIO_SESSION_OUTPUT_STAGE) || (sessionId == AUDIO_SESSION_OUTPUT_MIX)) {
+ if (audio_is_global_session(sessionId)) {
ALOGW("checkEffectCompatibility_l(): global effect %s on DUPLICATING"
" thread %s", desc->name, mThreadName);
return BAD_VALUE;
@@ -2051,6 +2059,7 @@
{ // scope for mLock
Mutex::Autolock _l(mLock);
for (audio_session_t session : {
+ AUDIO_SESSION_DEVICE,
AUDIO_SESSION_OUTPUT_STAGE,
AUDIO_SESSION_OUTPUT_MIX,
sessionId,
@@ -3103,7 +3112,7 @@
halOutBuffer = halInBuffer;
effect_buffer_t *buffer = reinterpret_cast<effect_buffer_t*>(halInBuffer->externalData());
ALOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
- if (session > AUDIO_SESSION_OUTPUT_MIX) {
+ if (!audio_is_global_session(session)) {
// Only one effect chain can be present in direct output thread and it uses
// the sink buffer as input
if (mType != DIRECT) {
@@ -3143,8 +3152,11 @@
chain->setThread(this);
chain->setInBuffer(halInBuffer);
chain->setOutBuffer(halOutBuffer);
- // Effect chain for session AUDIO_SESSION_OUTPUT_STAGE is inserted at end of effect
- // chains list in order to be processed last as it contains output stage effects.
+ // Effect chain for session AUDIO_SESSION_DEVICE is inserted at end of effect
+ // chains list in order to be processed last as it contains output device effects.
+ // Effect chain for session AUDIO_SESSION_OUTPUT_STAGE is inserted just before to apply post
+ // processing effects specific to an output stream before effects applied to all streams
+ // routed to a given device.
// Effect chain for session AUDIO_SESSION_OUTPUT_MIX is inserted before
// session AUDIO_SESSION_OUTPUT_STAGE to be processed
// after track specific effects and before output stage.
@@ -3154,7 +3166,8 @@
// chains list to be processed before output mix effects. Relative order between other
// sessions is not important.
static_assert(AUDIO_SESSION_OUTPUT_MIX == 0 &&
- AUDIO_SESSION_OUTPUT_STAGE < AUDIO_SESSION_OUTPUT_MIX,
+ AUDIO_SESSION_OUTPUT_STAGE < AUDIO_SESSION_OUTPUT_MIX &&
+ AUDIO_SESSION_DEVICE < AUDIO_SESSION_OUTPUT_STAGE,
"audio_session_t constants misdefined");
size_t size = mEffectChains.size();
size_t i = 0;
@@ -5741,7 +5754,7 @@
int64_t framesWritten = mBytesWritten / mFrameSize;
if (mStandby || !last ||
track->presentationComplete(framesWritten, audioHALFrames) ||
- track->isPaused()) {
+ track->isPaused() || mHwPaused) {
if (track->isStopping_2()) {
track->mState = TrackBase::STOPPED;
}
@@ -9099,8 +9112,8 @@
const effect_descriptor_t *desc, audio_session_t sessionId)
{
// No global effect sessions on mmap threads
- if (sessionId == AUDIO_SESSION_OUTPUT_MIX || sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
- ALOGW("checkEffectCompatibility_l(): global effect %s on record thread %s",
+ if (audio_is_global_session(sessionId)) {
+ ALOGW("checkEffectCompatibility_l(): global effect %s on MMAP thread %s",
desc->name, mThreadName);
return BAD_VALUE;
}
@@ -9122,7 +9135,6 @@
}
return NO_ERROR;
-
}
void AudioFlinger::MmapThread::checkInvalidTracks_l()
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 90aef3c..7f339dc
--- 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;
status_t setPreferredDeviceForStrategy(product_strategy_t strategy,
@@ -122,12 +127,13 @@
status_t restoreOriginVolumeCurve(audio_stream_type_t stream);
- private:
+private:
AudioPolicyManagerObserver *mApmObserver = nullptr;
ProductStrategyMap mProductStrategies;
ProductStrategyPreferredRoutingMap mProductStrategyPreferredDevices;
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..a3053a4
--- /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
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index 8be72a4..01efc7a 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..87b6aaf
--- /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
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 3aa3db5..b34928d
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -387,22 +387,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)
diff --git a/services/audiopolicy/manager/Android.mk b/services/audiopolicy/manager/Android.mk
index d6ca2f2..cae6cfa 100644
--- a/services/audiopolicy/manager/Android.mk
+++ b/services/audiopolicy/manager/Android.mk
@@ -23,8 +23,6 @@
LOCAL_CFLAGS := -Wall -Werror
-LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
-
LOCAL_MODULE:= libaudiopolicymanager
include $(BUILD_SHARED_LIBRARY)
diff --git a/services/audiopolicy/service/Android.mk b/services/audiopolicy/service/Android.mk
index c4f4c56..1144970 100644
--- a/services/audiopolicy/service/Android.mk
+++ b/services/audiopolicy/service/Android.mk
@@ -38,8 +38,6 @@
LOCAL_STATIC_LIBRARIES := \
libaudiopolicycomponents
-LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
-
LOCAL_MODULE:= libaudiopolicyservice
LOCAL_CFLAGS += -fvisibility=hidden