Merge "MediaPlayer2: remove unused code setMetadataFilter and getMetadata"
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index b5f61e7..ac8901c 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1850,6 +1850,7 @@
{
dumpBase(fd, args);
+ dprintf(fd, " Master mute: %s\n", mMasterMute ? "on" : "off");
dprintf(fd, " Normal frame count: %zu\n", mNormalFrameCount);
dprintf(fd, " Last write occurred (msecs): %llu\n",
(unsigned long long) ns2ms(systemTime() - mLastWriteTime));
diff --git a/services/audiopolicy/common/include/RoutingStrategy.h b/services/audiopolicy/common/include/RoutingStrategy.h
index d38967e..f8a1cd6 100644
--- a/services/audiopolicy/common/include/RoutingStrategy.h
+++ b/services/audiopolicy/common/include/RoutingStrategy.h
@@ -23,6 +23,7 @@
#define SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY 5000
enum routing_strategy {
+ STRATEGY_NONE = -1,
STRATEGY_MEDIA,
STRATEGY_PHONE,
STRATEGY_SONIFICATION,
diff --git a/services/audiopolicy/common/managerdefinitions/Android.mk b/services/audiopolicy/common/managerdefinitions/Android.mk
index 9b8f095..bacb780 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.mk
+++ b/services/audiopolicy/common/managerdefinitions/Android.mk
@@ -17,10 +17,8 @@
src/AudioCollections.cpp \
src/EffectDescriptor.cpp \
src/SoundTriggerSession.cpp \
- src/SessionRoute.cpp \
src/VolumeCurve.cpp \
src/TypeConverter.cpp \
- src/AudioSession.cpp \
src/ClientDescriptor.cpp
LOCAL_SHARED_LIBRARIES := \
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index 44662e5..72d5a8c 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -16,19 +16,19 @@
#pragma once
-#include "AudioIODescriptorInterface.h"
-#include "AudioPort.h"
-#include "AudioSession.h"
-#include "ClientDescriptor.h"
-#include <utils/Errors.h>
#include <system/audio.h>
+#include <utils/Errors.h>
#include <utils/SortedVector.h>
#include <utils/KeyedVector.h>
+#include "AudioIODescriptorInterface.h"
+#include "AudioPort.h"
+#include "ClientDescriptor.h"
namespace android {
class IOProfile;
class AudioMix;
+class AudioPolicyClientInterface;
// descriptor for audio inputs. Used to maintain current configuration of each opened audio input
// and keep track of the usage of this input.
@@ -39,7 +39,6 @@
AudioPolicyClientInterface *clientInterface);
audio_port_handle_t getId() const;
audio_module_handle_t getModuleHandle() const;
- uint32_t getOpenRefCount() const;
status_t dump(int fd);
@@ -56,19 +55,13 @@
SortedVector<audio_session_t> getPreemptedSessions() const;
bool hasPreemptedSession(audio_session_t session) const;
void clearPreemptedSessions();
- bool isActive() const;
+ bool isActive() const { return mGlobalActiveCount > 0; }
bool isSourceActive(audio_source_t source) const;
audio_source_t inputSource(bool activeOnly = false) const;
bool isSoundTrigger() const;
- status_t addAudioSession(audio_session_t session,
- const sp<AudioSession>& audioSession);
- status_t removeAudioSession(audio_session_t session);
- sp<AudioSession> getAudioSession(audio_session_t session) const;
- AudioSessionCollection getAudioSessions(bool activeOnly) const;
- size_t getAudioSessionCount(bool activeOnly) const;
audio_source_t getHighestPrioritySource(bool activeOnly) const;
- void changeRefCount(audio_session_t session, int delta);
-
+ void setClientActive(const sp<RecordClientDescriptor>& client, bool active);
+ int32_t activeCount() { return mGlobalActiveCount; }
// implementation of AudioIODescriptorInterface
audio_config_base_t getConfig() const override;
@@ -82,24 +75,24 @@
audio_input_flags_t flags,
audio_io_handle_t *input);
// Called when a stream is about to be started.
- // Note: called after changeRefCount(session, 1)
+ // Note: called after setClientActive(client, true)
status_t start();
// Called after a stream is stopped
- // Note: called after changeRefCount(session, -1)
+ // Note: called after setClientActive(client, false)
void stop();
void close();
- RecordClientMap& clients() { return mClients; }
+ RecordClientMap& clientsMap() { return mClients; }
RecordClientVector getClientsForSession(audio_session_t session);
+ RecordClientVector clientsList(bool activeOnly = false,
+ audio_source_t source = AUDIO_SOURCE_DEFAULT, bool preferredDeviceOnly = false) const;
private:
- void updateSessionRecordingConfiguration(int event, const sp<AudioSession>& audioSession);
+ void updateClientRecordingConfiguration(int event, const sp<RecordClientDescriptor>& client);
audio_patch_handle_t mPatchHandle;
audio_port_handle_t mId;
- // audio sessions attached to this input
- AudioSessionCollection mSessions;
// Because a preemptible capture session can preempt another one, we end up in an endless loop
// situation were each session is allowed to restart after being preempted,
// thus preempting the other one which restarts and so on.
@@ -108,7 +101,7 @@
// We also inherit sessions from the preempted input to avoid a 3 way preemption loop etc...
SortedVector<audio_session_t> mPreemptedSessions;
AudioPolicyClientInterface *mClientInterface;
- uint32_t mGlobalRefCount; // non-session-specific ref count
+ int32_t mGlobalActiveCount; // non-client-specific activity ref count
RecordClientMap mClients;
};
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index ff0201a..27b1c93 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -59,7 +59,10 @@
audio_devices_t device,
uint32_t delayMs,
bool force);
- virtual void changeRefCount(audio_stream_type_t stream, int delta);
+ virtual void changeStreamActiveCount(audio_stream_type_t stream, int delta);
+ uint32_t streamActiveCount(audio_stream_type_t stream) const
+ { return mActiveCount[stream]; }
+ void setClientActive(const sp<TrackClientDescriptor>& client, bool active);
bool isActive(uint32_t inPastMs = 0) const;
bool isStreamActive(audio_stream_type_t stream,
@@ -78,19 +81,23 @@
audio_patch_handle_t getPatchHandle() const override;
void setPatchHandle(audio_patch_handle_t handle) override;
- TrackClientMap& clients() { return mClients; }
+ TrackClientMap& clientsMap() { return mClients; }
+ TrackClientVector clientsList(bool activeOnly = false,
+ routing_strategy strategy = STRATEGY_NONE, bool preferredDeviceOnly = false) const;
sp<AudioPort> mPort;
audio_devices_t mDevice; // current device this output is routed to
- uint32_t mRefCount[AUDIO_STREAM_CNT]; // number of streams of each type using this output
nsecs_t mStopTime[AUDIO_STREAM_CNT];
float mCurVolume[AUDIO_STREAM_CNT]; // current stream volume in dB
int mMuteCount[AUDIO_STREAM_CNT]; // mute request counter
bool mStrategyMutedByDevice[NUM_STRATEGIES]; // strategies muted because of incompatible
// device selection. See checkDeviceMuteStrategies()
AudioPolicyClientInterface *mClientInterface;
+ AudioMix *mPolicyMix; // non NULL when used by a dynamic policy
protected:
+ uint32_t mActiveCount[AUDIO_STREAM_CNT]; // number of streams of each type active on this output
+ uint32_t mGlobalActiveCount; // non-client-specific active count
audio_patch_handle_t mPatchHandle;
audio_port_handle_t mId;
TrackClientMap mClients;
@@ -114,7 +121,7 @@
virtual bool isFixedVolume(audio_devices_t device);
virtual sp<AudioOutputDescriptor> subOutput1() { return mOutput1; }
virtual sp<AudioOutputDescriptor> subOutput2() { return mOutput2; }
- virtual void changeRefCount(audio_stream_type_t stream, int delta);
+ virtual void changeStreamActiveCount(audio_stream_type_t stream, int delta);
virtual bool setVolume(float volume,
audio_stream_type_t stream,
audio_devices_t device,
@@ -132,10 +139,10 @@
audio_output_flags_t flags,
audio_io_handle_t *output);
// Called when a stream is about to be started
- // Note: called before changeRefCount(1);
+ // Note: called before setClientActive(true);
status_t start();
// Called after a stream is stopped.
- // Note: called after changeRefCount(-1);
+ // Note: called after setClientActive(false);
void stop();
void close();
status_t openDuplicating(const sp<SwAudioOutputDescriptor>& output1,
@@ -146,12 +153,10 @@
audio_io_handle_t mIoHandle; // output handle
uint32_t mLatency; //
audio_output_flags_t mFlags; //
- AudioMix *mPolicyMix; // non NULL when used by a dynamic policy
sp<SwAudioOutputDescriptor> mOutput1; // used by duplicated outputs: first output
sp<SwAudioOutputDescriptor> mOutput2; // used by duplicated outputs: second output
uint32_t mDirectOpenCount; // number of clients using this output (direct outputs only)
audio_session_t mDirectClientSession; // session id of the direct output client
- uint32_t mGlobalRefCount; // non-stream-specific ref count
};
// Audio output driven by an input device directly.
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index f861b95..78e7ec9 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -28,7 +28,6 @@
#include <AudioPolicyMix.h>
#include <EffectDescriptor.h>
#include <SoundTriggerSession.h>
-#include <SessionRoute.h>
namespace android {
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioSession.h b/services/audiopolicy/common/managerdefinitions/include/AudioSession.h
deleted file mode 100644
index 1636d3a..0000000
--- a/services/audiopolicy/common/managerdefinitions/include/AudioSession.h
+++ /dev/null
@@ -1,96 +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.
- */
-
-#pragma once
-
-#include <system/audio.h>
-#include <utils/Errors.h>
-#include <utils/RefBase.h>
-#include <utils/Errors.h>
-#include <utils/KeyedVector.h>
-#include <media/AudioPolicy.h>
-#include <media/IAudioPolicyServiceClient.h>
-#include "AudioIODescriptorInterface.h"
-
-namespace android {
-
-class AudioPolicyClientInterface;
-
-class AudioSession : public RefBase
-{
-public:
- AudioSession(audio_session_t session,
- audio_source_t inputSource,
- audio_format_t format,
- uint32_t sampleRate,
- audio_channel_mask_t channelMask,
- audio_input_flags_t flags,
- uid_t uid,
- bool isSoundTrigger);
-
- status_t dump(int fd, int spaces, int index) const;
-
- audio_session_t session() const { return mRecordClientInfo.session; }
- audio_source_t inputSource()const { return mRecordClientInfo.source; }
- audio_format_t format() const { return mConfig.format; }
- uint32_t sampleRate() const { return mConfig.sample_rate; }
- audio_channel_mask_t channelMask() const { return mConfig.channel_mask; }
- audio_config_base config() const { return mConfig; }
- record_client_info_t recordClientInfo() const { return mRecordClientInfo; }
- audio_input_flags_t flags() const { return mFlags; }
- uid_t uid() const { return mRecordClientInfo.uid; }
- void setUid(uid_t uid) { mRecordClientInfo.uid = uid; }
- bool matches(const sp<AudioSession> &other) const;
- bool isSoundTrigger() const { return mIsSoundTrigger; }
- void setSilenced(bool silenced) { mSilenced = silenced; }
- bool isSilenced() const { return mSilenced; }
- uint32_t openCount() const { return mOpenCount; } ;
- uint32_t activeCount() const { return mActiveCount; } ;
-
- uint32_t changeOpenCount(int delta);
- uint32_t changeActiveCount(int delta);
-
-private:
- record_client_info_t mRecordClientInfo;
- const struct audio_config_base mConfig;
- const audio_input_flags_t mFlags;
- bool mIsSoundTrigger;
- bool mSilenced;
- uint32_t mOpenCount;
- uint32_t mActiveCount;
-};
-
-class AudioSessionCollection :
- public DefaultKeyedVector<audio_session_t, sp<AudioSession> >
-{
-public:
- status_t addSession(audio_session_t session,
- const sp<AudioSession>& audioSession);
-
- status_t removeSession(audio_session_t session);
-
- uint32_t getOpenCount() const;
-
- AudioSessionCollection getActiveSessions() const;
- size_t getActiveSessionCount() const;
- bool hasActiveSession() const;
- bool isSourceActive(audio_source_t source) const;
- audio_source_t getHighestPrioritySource(bool activeOnly) const;
-
- status_t dump(int fd, int spaces) const;
-};
-
-} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
index 9efe57f..1a3300d 100644
--- a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
@@ -27,6 +27,7 @@
#include <utils/RefBase.h>
#include <utils/String8.h>
#include "AudioPatch.h"
+#include "RoutingStrategy.h"
namespace android {
@@ -53,8 +54,14 @@
audio_attributes_t attributes() const { return mAttributes; }
audio_config_base_t config() const { return mConfig; }
audio_port_handle_t preferredDeviceId() const { return mPreferredDeviceId; };
+ void setPreferredDeviceId(audio_port_handle_t preferredDeviceId) {
+ mPreferredDeviceId = preferredDeviceId;
+ };
void setActive(bool active) { mActive = active; }
bool active() const { return mActive; }
+ bool hasPreferredDevice(bool activeOnly = false) const {
+ return mPreferredDeviceId != AUDIO_PORT_HANDLE_NONE && (!activeOnly || mActive);
+ }
private:
const audio_port_handle_t mPortId; // unique Id for this client
@@ -62,7 +69,7 @@
const audio_session_t mSessionId; // audio session ID
const audio_attributes_t mAttributes; // usage...
const audio_config_base_t mConfig;
- const audio_port_handle_t mPreferredDeviceId; // selected input device port ID
+ audio_port_handle_t mPreferredDeviceId; // selected input device port ID
bool mActive;
protected:
@@ -75,10 +82,10 @@
public:
TrackClientDescriptor(audio_port_handle_t portId, uid_t uid, audio_session_t sessionId,
audio_attributes_t attributes, audio_config_base_t config,
- audio_port_handle_t preferredDeviceId,
- audio_stream_type_t stream, audio_output_flags_t flags) :
+ audio_port_handle_t preferredDeviceId, audio_stream_type_t stream,
+ routing_strategy strategy, audio_output_flags_t flags) :
ClientDescriptor(portId, uid, sessionId, attributes, config, preferredDeviceId),
- mStream(stream), mFlags(flags) {}
+ mStream(stream), mStrategy(strategy), mFlags(flags) {}
~TrackClientDescriptor() override = default;
using ClientDescriptor::dump;
@@ -86,9 +93,11 @@
audio_output_flags_t flags() const { return mFlags; }
audio_stream_type_t stream() const { return mStream; }
+ routing_strategy strategy() const { return mStrategy; }
private:
const audio_stream_type_t mStream;
+ const routing_strategy mStrategy;
const audio_output_flags_t mFlags;
};
@@ -98,9 +107,9 @@
RecordClientDescriptor(audio_port_handle_t portId, uid_t uid, audio_session_t sessionId,
audio_attributes_t attributes, audio_config_base_t config,
audio_port_handle_t preferredDeviceId,
- audio_source_t source, audio_input_flags_t flags) :
+ audio_source_t source, audio_input_flags_t flags, bool isSoundTrigger) :
ClientDescriptor(portId, uid, sessionId, attributes, config, preferredDeviceId),
- mSource(source), mFlags(flags) {}
+ mSource(source), mFlags(flags), mIsSoundTrigger(isSoundTrigger), mSilenced(false) {}
~RecordClientDescriptor() override = default;
using ClientDescriptor::dump;
@@ -108,10 +117,15 @@
audio_source_t source() const { return mSource; }
audio_input_flags_t flags() const { return mFlags; }
+ bool isSoundTrigger() const { return mIsSoundTrigger; }
+ void setSilenced(bool silenced) { mSilenced = silenced; }
+ bool isSilenced() const { return mSilenced; }
private:
const audio_source_t mSource;
const audio_input_flags_t mFlags;
+ const bool mIsSoundTrigger;
+ bool mSilenced;
};
class SourceClientDescriptor: public TrackClientDescriptor
@@ -119,7 +133,7 @@
public:
SourceClientDescriptor(audio_port_handle_t portId, uid_t uid, audio_attributes_t attributes,
const sp<AudioPatch>& patchDesc, const sp<DeviceDescriptor>& srcDevice,
- audio_stream_type_t stream);
+ audio_stream_type_t stream, routing_strategy strategy);
~SourceClientDescriptor() override = default;
sp<AudioPatch> patchDesc() const { return mPatchDesc; }
diff --git a/services/audiopolicy/common/managerdefinitions/include/SessionRoute.h b/services/audiopolicy/common/managerdefinitions/include/SessionRoute.h
deleted file mode 100644
index 32b4440..0000000
--- a/services/audiopolicy/common/managerdefinitions/include/SessionRoute.h
+++ /dev/null
@@ -1,120 +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.
- */
-
-#pragma once
-
-#include <system/audio.h>
-#include <utils/KeyedVector.h>
-#include <utils/RefBase.h>
-#include <utils/Errors.h>
-
-namespace android {
-
-class DeviceDescriptor;
-class DeviceVector;
-
-class SessionRoute : public RefBase
-{
-public:
- // For Input (Source) routes, use STREAM_TYPE_NA ("NA" = "not applicable)for the
- // streamType argument
- static const audio_stream_type_t STREAM_TYPE_NA = AUDIO_STREAM_DEFAULT;
-
- // For Output (Sink) routes, use SOURCE_TYPE_NA ("NA" = "not applicable") for the
- // source argument
-
- static const audio_source_t SOURCE_TYPE_NA = AUDIO_SOURCE_DEFAULT;
-
- SessionRoute(audio_session_t session,
- audio_stream_type_t streamType,
- audio_source_t source,
- sp<DeviceDescriptor> deviceDescriptor,
- uid_t uid)
- : mUid(uid),
- mSession(session),
- mDeviceDescriptor(deviceDescriptor),
- mRefCount(0),
- mActivityCount(0),
- mChanged(false),
- mStreamType(streamType),
- mSource(source)
- {}
-
- void log(const char* prefix);
-
- bool isActiveOrChanged() {
- return (mDeviceDescriptor != 0) && (mChanged || (mActivityCount > 0));
- }
-
- uid_t mUid;
- audio_session_t mSession;
- sp<DeviceDescriptor> mDeviceDescriptor;
-
- // "reference" counting
- int mRefCount; // +/- on references
- int mActivityCount; // +/- on start/stop
- bool mChanged;
- // for outputs
- const audio_stream_type_t mStreamType;
- // for inputs
- const audio_source_t mSource;
-};
-
-class SessionRouteMap: public KeyedVector<audio_session_t, sp<SessionRoute> >
-{
-public:
- // These constants identify the SessionRoutMap as holding EITHER input routes,
- // or output routes. An error will occur if an attempt is made to add a SessionRoute
- // object with mStreamType == STREAM_TYPE_NA (i.e. an input SessionRoute) to a
- // SessionRoutMap that is marked for output (i.e. mMapType == SESSION_ROUTE_MAP_OUTPUT)
- // and similarly for output SessionRoutes and Input SessionRouteMaps.
- typedef enum
- {
- MAPTYPE_INPUT = 0,
- MAPTYPE_OUTPUT = 1
- } session_route_map_type_t;
-
- explicit SessionRouteMap(session_route_map_type_t mapType) :
- mMapType(mapType)
- {}
-
- bool hasRoute(audio_session_t session);
-
- void removeRoute(audio_session_t session);
-
- int incRouteActivity(audio_session_t session);
- int decRouteActivity(audio_session_t session);
- bool getAndClearRouteChanged(audio_session_t session); // also clears the changed flag
- void log(const char* caption);
- audio_devices_t getActiveDeviceForStream(audio_stream_type_t streamType,
- const DeviceVector& availableDevices);
- // Specify an Output(Sink) route by passing SessionRoute::SOURCE_TYPE_NA in the
- // source argument.
- // Specify an Input(Source) rout by passing SessionRoute::AUDIO_STREAM_DEFAULT
- // in the streamType argument.
- void addRoute(audio_session_t session,
- audio_stream_type_t streamType,
- audio_source_t source,
- const sp<DeviceDescriptor>& deviceDescriptor,
- uid_t uid);
-
-private:
- // Used to mark a SessionRoute as for either inputs (mMapType == kSessionRouteMap_Input)
- // or outputs (mMapType == kSessionRouteMap_Output)
- const session_route_map_type_t mMapType;
-};
-
-} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index 2770e74..e25b0fe 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -17,13 +17,13 @@
#define LOG_TAG "APM::AudioInputDescriptor"
//#define LOG_NDEBUG 0
+#include <media/AudioPolicy.h>
+#include <policy.h>
#include <AudioPolicyInterface.h>
#include "AudioInputDescriptor.h"
#include "IOProfile.h"
#include "AudioGain.h"
#include "HwModule.h"
-#include <media/AudioPolicy.h>
-#include <policy.h>
namespace android {
@@ -32,7 +32,7 @@
: mIoHandle(0),
mDevice(AUDIO_DEVICE_NONE), mPolicyMix(NULL),
mProfile(profile), mPatchHandle(AUDIO_PATCH_HANDLE_NONE), mId(0),
- mClientInterface(clientInterface), mGlobalRefCount(0)
+ mClientInterface(clientInterface), mGlobalActiveCount(0)
{
if (profile != NULL) {
profile->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
@@ -50,11 +50,6 @@
return mProfile->getModuleHandle();
}
-uint32_t AudioInputDescriptor::getOpenRefCount() const
-{
- return mSessions.getOpenCount();
-}
-
audio_port_handle_t AudioInputDescriptor::getId() const
{
return mId;
@@ -118,57 +113,45 @@
mPreemptedSessions.clear();
}
-bool AudioInputDescriptor::isActive() const {
- return mSessions.hasActiveSession();
-}
-
bool AudioInputDescriptor::isSourceActive(audio_source_t source) const
{
- return mSessions.isSourceActive(source);
+ for (const auto &client : mClients) {
+ if (client.second->active() &&
+ ((client.second->source() == source) ||
+ ((source == AUDIO_SOURCE_VOICE_RECOGNITION) &&
+ (client.second->source() == AUDIO_SOURCE_HOTWORD) &&
+ client.second->isSoundTrigger()))) {
+ return true;
+ }
+ }
+ return false;
}
audio_source_t AudioInputDescriptor::getHighestPrioritySource(bool activeOnly) const
{
+ audio_source_t source = AUDIO_SOURCE_DEFAULT;
+ int32_t priority = -1;
- return mSessions.getHighestPrioritySource(activeOnly);
+ for (const auto &client : mClients) {
+ if (activeOnly && !client.second->active() ) {
+ continue;
+ }
+ int32_t curPriority = source_priority(client.second->source());
+ if (curPriority > priority) {
+ priority = curPriority;
+ source = client.second->source();
+ }
+ }
+ return source;
}
bool AudioInputDescriptor::isSoundTrigger() const {
- // sound trigger and non sound trigger sessions are not mixed
- // on a given input
- return mSessions.valueAt(0)->isSoundTrigger();
-}
-
-sp<AudioSession> AudioInputDescriptor::getAudioSession(
- audio_session_t session) const {
- return mSessions.valueFor(session);
-}
-
-AudioSessionCollection AudioInputDescriptor::getAudioSessions(bool activeOnly) const
-{
- if (activeOnly) {
- return mSessions.getActiveSessions();
- } else {
- return mSessions;
+ // sound trigger and non sound trigger clients are not mixed on a given input
+ // so check only first client
+ if (mClients.size() == 0) {
+ return false;
}
-}
-
-size_t AudioInputDescriptor::getAudioSessionCount(bool activeOnly) const
-{
- if (activeOnly) {
- return mSessions.getActiveSessionCount();
- } else {
- return mSessions.size();
- }
-}
-
-status_t AudioInputDescriptor::addAudioSession(audio_session_t session,
- const sp<AudioSession>& audioSession) {
- return mSessions.addSession(session, audioSession);
-}
-
-status_t AudioInputDescriptor::removeAudioSession(audio_session_t session) {
- return mSessions.removeSession(session);
+ return mClients.cbegin()->second->isSoundTrigger();
}
audio_patch_handle_t AudioInputDescriptor::getPatchHandle() const
@@ -179,9 +162,9 @@
void AudioInputDescriptor::setPatchHandle(audio_patch_handle_t handle)
{
mPatchHandle = handle;
- for (size_t i = 0; i < mSessions.size(); i++) {
- if (mSessions[i]->activeCount() > 0) {
- updateSessionRecordingConfiguration(RECORD_CONFIG_EVENT_START, mSessions[i]);
+ for (const auto &client : mClients) {
+ if (client.second->active()) {
+ updateClientRecordingConfiguration(RECORD_CONFIG_EVENT_START, client.second);
}
}
}
@@ -243,7 +226,7 @@
status_t AudioInputDescriptor::start()
{
- if (getAudioSessionCount(true/*activeOnly*/) == 1) {
+ if (mGlobalActiveCount == 1) {
if (!mProfile->canStartNewIo()) {
ALOGI("%s mProfile->curActiveCount %d", __func__, mProfile->curActiveCount);
return INVALID_OPERATION;
@@ -270,7 +253,7 @@
LOG_ALWAYS_FATAL_IF(mProfile->curOpenCount < 1, "%s profile open count %u",
__FUNCTION__, mProfile->curOpenCount);
// do not call stop() here as stop() is supposed to be called after
- // changeRefCount(session, -1) and we don't know how many sessions
+ // setClientActive(client, false) and we don't know how many clients
// are still active at this time
if (isActive()) {
mProfile->curActiveCount--;
@@ -280,27 +263,28 @@
}
}
-void AudioInputDescriptor::changeRefCount(audio_session_t session, int delta)
+void AudioInputDescriptor::setClientActive(const sp<RecordClientDescriptor>& client, bool active)
{
- sp<AudioSession> audioSession = mSessions.valueFor(session);
- if (audioSession == 0) {
+ if (mClients.find(client->portId()) == mClients.end()
+ || active == client->active()) {
return;
}
- // handle session-independent ref count
- uint32_t oldGlobalRefCount = mGlobalRefCount;
- if ((delta + (int)mGlobalRefCount) < 0) {
- ALOGW("changeRefCount() invalid delta %d globalRefCount %d", delta, mGlobalRefCount);
- delta = -((int)mGlobalRefCount);
+
+ // Handle non-client-specific activity ref count
+ int32_t oldGlobalActiveCount = mGlobalActiveCount;
+ if (!active && mGlobalActiveCount < 1) {
+ ALOGW("%s invalid deactivation with globalRefCount %d", __FUNCTION__, mGlobalActiveCount);
+ mGlobalActiveCount = 1;
}
- mGlobalRefCount += delta;
- if ((oldGlobalRefCount == 0) && (mGlobalRefCount > 0)) {
+ mGlobalActiveCount += active ? 1 : -1;
+
+ if ((oldGlobalActiveCount == 0) && (mGlobalActiveCount > 0)) {
if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
{
mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress,
MIX_STATE_MIXING);
}
-
- } else if ((oldGlobalRefCount > 0) && (mGlobalRefCount == 0)) {
+ } else if ((oldGlobalActiveCount > 0) && (mGlobalActiveCount == 0)) {
if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
{
mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress,
@@ -308,32 +292,18 @@
}
}
- uint32_t oldActiveCount = audioSession->activeCount();
- if ((delta + (int)oldActiveCount) < 0) {
- ALOGW("changeRefCount() invalid delta %d for sesion %d active count %d",
- delta, session, oldActiveCount);
- delta = -((int)oldActiveCount);
- }
+ client->setActive(active);
- audioSession->changeActiveCount(delta);
-
- int event = RECORD_CONFIG_EVENT_NONE;
- if ((oldActiveCount == 0) && (audioSession->activeCount() > 0)) {
- event = RECORD_CONFIG_EVENT_START;
- } else if ((oldActiveCount > 0) && (audioSession->activeCount() == 0)) {
- event = RECORD_CONFIG_EVENT_STOP;
- }
- if (event != RECORD_CONFIG_EVENT_NONE) {
- updateSessionRecordingConfiguration(event, audioSession);
- }
+ int event = active ? RECORD_CONFIG_EVENT_START : RECORD_CONFIG_EVENT_STOP;
+ updateClientRecordingConfiguration(event, client);
}
-void AudioInputDescriptor::updateSessionRecordingConfiguration(
- int event, const sp<AudioSession>& audioSession) {
-
- const audio_config_base_t sessionConfig = audioSession->config();
- const record_client_info_t recordClientInfo = audioSession->recordClientInfo();
+void AudioInputDescriptor::updateClientRecordingConfiguration(
+ int event, const sp<RecordClientDescriptor>& client)
+{
+ const audio_config_base_t sessionConfig = client->config();
+ const record_client_info_t recordClientInfo{client->uid(), client->session(), client->source()};
const audio_config_base_t config = getConfig();
mClientInterface->onRecordingConfigurationUpdate(event,
&recordClientInfo, &sessionConfig,
@@ -352,6 +322,20 @@
return clients;
}
+RecordClientVector AudioInputDescriptor::clientsList(bool activeOnly, audio_source_t source,
+ bool preferredDeviceOnly) const
+{
+ RecordClientVector clients;
+ for (const auto &client : mClients) {
+ if ((!activeOnly || client.second->active())
+ && (source == AUDIO_SOURCE_DEFAULT || source == client.second->source())
+ && (!preferredDeviceOnly || client.second->hasPreferredDevice())) {
+ clients.push_back(client.second);
+ }
+ }
+ return clients;
+}
+
status_t AudioInputDescriptor::dump(int fd)
{
const size_t SIZE = 256;
@@ -371,8 +355,6 @@
write(fd, result.string(), result.size());
- mSessions.dump(fd, 1);
-
size_t index = 0;
result = " AudioRecord clients:\n";
for (const auto& client: mClients) {
@@ -446,7 +428,7 @@
{
for (size_t i = 0; i < size(); i++) {
sp<AudioInputDescriptor> inputDesc = valueAt(i);
- for (const auto& client : inputDesc->clients()) {
+ for (const auto& client : inputDesc->clientsMap()) {
if (client.second->portId() == portId) {
return inputDesc;
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 39fce4d..b6ff6ea 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -34,12 +34,12 @@
AudioOutputDescriptor::AudioOutputDescriptor(const sp<AudioPort>& port,
AudioPolicyClientInterface *clientInterface)
- : mPort(port), mDevice(AUDIO_DEVICE_NONE),
- mClientInterface(clientInterface), mPatchHandle(AUDIO_PATCH_HANDLE_NONE), mId(0)
+ : mPort(port), mDevice(AUDIO_DEVICE_NONE), mClientInterface(clientInterface),
+ mPolicyMix(NULL), mGlobalActiveCount(0), mPatchHandle(AUDIO_PATCH_HANDLE_NONE), mId(0)
{
// clear usage count for all stream types
for (int i = 0; i < AUDIO_STREAM_CNT; i++) {
- mRefCount[i] = 0;
+ mActiveCount[i] = 0;
mCurVolume[i] = -1.0;
mMuteCount[i] = 0;
mStopTime[i] = 0;
@@ -103,17 +103,51 @@
}
}
-void AudioOutputDescriptor::changeRefCount(audio_stream_type_t stream,
+void AudioOutputDescriptor::changeStreamActiveCount(audio_stream_type_t stream,
int delta)
{
- if ((delta + (int)mRefCount[stream]) < 0) {
- ALOGW("changeRefCount() invalid delta %d for stream %d, refCount %d",
- delta, stream, mRefCount[stream]);
- mRefCount[stream] = 0;
+ if ((delta + (int)mActiveCount[stream]) < 0) {
+ ALOGW("%s invalid delta %d for stream %d, active count %d",
+ __FUNCTION__, delta, stream, mActiveCount[stream]);
+ mActiveCount[stream] = 0;
return;
}
- mRefCount[stream] += delta;
- ALOGV("changeRefCount() stream %d, count %d", stream, mRefCount[stream]);
+ mActiveCount[stream] += delta;
+ ALOGV("%s stream %d, count %d", __FUNCTION__, stream, mActiveCount[stream]);
+}
+
+void AudioOutputDescriptor::setClientActive(const sp<TrackClientDescriptor>& client, bool active)
+{
+ if (mClients.find(client->portId()) == mClients.end()
+ || active == client->active()) {
+ return;
+ }
+
+ changeStreamActiveCount(client->stream(), active ? 1 : -1);
+
+ // Handle non-client-specific activity ref count
+ int32_t oldGlobalActiveCount = mGlobalActiveCount;
+ if (!active && mGlobalActiveCount < 1) {
+ ALOGW("%s invalid deactivation with globalRefCount %d", __FUNCTION__, mGlobalActiveCount);
+ mGlobalActiveCount = 1;
+ }
+ mGlobalActiveCount += active ? 1 : -1;
+
+ if ((oldGlobalActiveCount == 0) && (mGlobalActiveCount > 0)) {
+ if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
+ {
+ mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress,
+ MIX_STATE_MIXING);
+ }
+ } else if ((oldGlobalActiveCount > 0) && (mGlobalActiveCount == 0)) {
+ if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
+ {
+ mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress,
+ MIX_STATE_IDLE);
+ }
+ }
+
+ client->setActive(active);
}
bool AudioOutputDescriptor::isActive(uint32_t inPastMs) const
@@ -137,7 +171,7 @@
uint32_t inPastMs,
nsecs_t sysTime) const
{
- if (mRefCount[stream] != 0) {
+ if (mActiveCount[stream] != 0) {
return true;
}
if (inPastMs == 0) {
@@ -201,6 +235,20 @@
port->ext.mix.hw_module = getModuleHandle();
}
+TrackClientVector AudioOutputDescriptor::clientsList(bool activeOnly, routing_strategy strategy,
+ bool preferredDeviceOnly) const
+{
+ TrackClientVector clients;
+ for (const auto &client : mClients) {
+ if ((!activeOnly || client.second->active())
+ && (strategy == STRATEGY_NONE || strategy == client.second->strategy())
+ && (!preferredDeviceOnly || client.second->hasPreferredDevice())) {
+ clients.push_back(client.second);
+ }
+ }
+ return clients;
+}
+
status_t AudioOutputDescriptor::dump(int fd)
{
const size_t SIZE = 256;
@@ -217,11 +265,11 @@
result.append(buffer);
snprintf(buffer, SIZE, " Devices %08x\n", device());
result.append(buffer);
- snprintf(buffer, SIZE, " Stream volume refCount muteCount\n");
+ snprintf(buffer, SIZE, " Stream volume activeCount muteCount\n");
result.append(buffer);
for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) {
- snprintf(buffer, SIZE, " %02d %.03f %02d %02d\n",
- i, mCurVolume[i], mRefCount[i], mMuteCount[i]);
+ snprintf(buffer, SIZE, " %02d %.03f %02d %02d\n",
+ i, mCurVolume[i], streamActiveCount((audio_stream_type_t)i), mMuteCount[i]);
result.append(buffer);
}
@@ -247,9 +295,9 @@
AudioPolicyClientInterface *clientInterface)
: AudioOutputDescriptor(profile, clientInterface),
mProfile(profile), mIoHandle(AUDIO_IO_HANDLE_NONE), mLatency(0),
- mFlags((audio_output_flags_t)0), mPolicyMix(NULL),
+ mFlags((audio_output_flags_t)0),
mOutput1(0), mOutput2(0), mDirectOpenCount(0),
- mDirectClientSession(AUDIO_SESSION_NONE), mGlobalRefCount(0)
+ mDirectClientSession(AUDIO_SESSION_NONE)
{
if (profile != NULL) {
mFlags = (audio_output_flags_t)profile->getFlags();
@@ -313,41 +361,17 @@
}
}
-void SwAudioOutputDescriptor::changeRefCount(audio_stream_type_t stream,
+void SwAudioOutputDescriptor::changeStreamActiveCount(audio_stream_type_t stream,
int delta)
{
// forward usage count change to attached outputs
if (isDuplicated()) {
- mOutput1->changeRefCount(stream, delta);
- mOutput2->changeRefCount(stream, delta);
+ mOutput1->changeStreamActiveCount(stream, delta);
+ mOutput2->changeStreamActiveCount(stream, delta);
}
- AudioOutputDescriptor::changeRefCount(stream, delta);
-
- // handle stream-independent ref count
- uint32_t oldGlobalRefCount = mGlobalRefCount;
- if ((delta + (int)mGlobalRefCount) < 0) {
- ALOGW("changeRefCount() invalid delta %d globalRefCount %d", delta, mGlobalRefCount);
- mGlobalRefCount = 0;
- } else {
- mGlobalRefCount += delta;
- }
- if ((oldGlobalRefCount == 0) && (mGlobalRefCount > 0)) {
- if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
- {
- mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress,
- MIX_STATE_MIXING);
- }
-
- } else if ((oldGlobalRefCount > 0) && (mGlobalRefCount == 0)) {
- if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
- {
- mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress,
- MIX_STATE_IDLE);
- }
- }
+ AudioOutputDescriptor::changeStreamActiveCount(stream, delta);
}
-
bool SwAudioOutputDescriptor::isFixedVolume(audio_devices_t device)
{
// unit gain if rerouting to external policy
@@ -523,7 +547,7 @@
LOG_ALWAYS_FATAL_IF(mProfile->curOpenCount < 1, "%s profile open count %u",
__FUNCTION__, mProfile->curOpenCount);
- // do not call stop() here as stop() is supposed to be called after changeRefCount(-1)
+ // do not call stop() here as stop() is supposed to be called after setClientActive(false)
// and we don't know how many streams are still active at this time
if (isActive()) {
mProfile->curActiveCount--;
@@ -723,7 +747,7 @@
}
for (size_t i = 0; i < size(); i++) {
const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
- if (outputDesc->mRefCount[s] != 0) {
+ if (outputDesc->streamActiveCount((audio_stream_type_t)s)!= 0) {
return true;
}
}
@@ -742,7 +766,7 @@
{
for (size_t i = 0; i < size(); i++) {
sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
- for (const auto& client : outputDesc->clients()) {
+ for (const auto& client : outputDesc->clientsMap()) {
if (client.second->portId() == portId) {
return outputDesc;
}
@@ -788,7 +812,7 @@
}
for (size_t i = 0; i < size(); i++) {
const sp<HwAudioOutputDescriptor> outputDesc = valueAt(i);
- if (outputDesc->mRefCount[s] != 0) {
+ if (outputDesc->streamActiveCount((audio_stream_type_t)s) != 0) {
return true;
}
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp
deleted file mode 100644
index 5ea4c92..0000000
--- a/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp
+++ /dev/null
@@ -1,230 +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::AudioSession"
-//#define LOG_NDEBUG 0
-
-#include <AudioPolicyInterface.h>
-#include "policy.h"
-#include "AudioSession.h"
-#include "AudioGain.h"
-#include "TypeConverter.h"
-
-#include <log/log.h>
-#include <utils/String8.h>
-
-namespace android {
-
-AudioSession::AudioSession(audio_session_t session,
- audio_source_t inputSource,
- audio_format_t format,
- uint32_t sampleRate,
- audio_channel_mask_t channelMask,
- audio_input_flags_t flags,
- uid_t uid,
- bool isSoundTrigger) :
- mRecordClientInfo({ .uid = uid, .session = session, .source = inputSource}),
- mConfig({ .format = format, .sample_rate = sampleRate, .channel_mask = channelMask}),
- mFlags(flags), mIsSoundTrigger(isSoundTrigger),
- mOpenCount(1), mActiveCount(0)
-{
-}
-
-uint32_t AudioSession::changeOpenCount(int delta)
-{
- if ((delta + (int)mOpenCount) < 0) {
- ALOGW("%s invalid delta %d, open count %d",
- __FUNCTION__, delta, mOpenCount);
- mOpenCount = (uint32_t)(-delta);
- }
- mOpenCount += delta;
- ALOGV("%s open count %d", __FUNCTION__, mOpenCount);
- return mOpenCount;
-}
-
-uint32_t AudioSession::changeActiveCount(int delta)
-{
- if ((delta + (int)mActiveCount) < 0) {
- ALOGW("%s invalid delta %d, active count %d",
- __FUNCTION__, delta, mActiveCount);
- mActiveCount = (uint32_t)(-delta);
- }
- mActiveCount += delta;
- ALOGV("%s active count %d", __FUNCTION__, mActiveCount);
-
- return mActiveCount;
-}
-
-bool AudioSession::matches(const sp<AudioSession> &other) const
-{
- if (other->session() == mRecordClientInfo.session &&
- other->inputSource() == mRecordClientInfo.source &&
- other->format() == mConfig.format &&
- other->sampleRate() == mConfig.sample_rate &&
- other->channelMask() == mConfig.channel_mask &&
- other->flags() == mFlags &&
- other->uid() == mRecordClientInfo.uid) {
- return true;
- }
- return false;
-}
-
-status_t AudioSession::dump(int fd, int spaces, int index) const
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
- snprintf(buffer, SIZE, "%*sAudio session %d:\n", spaces, "", index+1);
- result.append(buffer);
- snprintf(buffer, SIZE, "%*s- session: %2d\n", spaces, "", mRecordClientInfo.session);
- result.append(buffer);
- snprintf(buffer, SIZE, "%*s- owner uid: %2d\n", spaces, "", mRecordClientInfo.uid);
- result.append(buffer);
- snprintf(buffer, SIZE, "%*s- input source: %d\n", spaces, "", mRecordClientInfo.source);
- result.append(buffer);
- snprintf(buffer, SIZE, "%*s- format: %08x\n", spaces, "", mConfig.format);
- result.append(buffer);
- snprintf(buffer, SIZE, "%*s- sample: %d\n", spaces, "", mConfig.sample_rate);
- result.append(buffer);
- snprintf(buffer, SIZE, "%*s- channel mask: %08x\n",
- spaces, "", mConfig.channel_mask);
- result.append(buffer);
- snprintf(buffer, SIZE, "%*s- is soundtrigger: %s\n",
- spaces, "", mIsSoundTrigger ? "true" : "false");
- result.append(buffer);
- snprintf(buffer, SIZE, "%*s- open count: %d\n", spaces, "", mOpenCount);
- result.append(buffer);
- snprintf(buffer, SIZE, "%*s- active count: %d\n", spaces, "", mActiveCount);
- result.append(buffer);
-
- write(fd, result.string(), result.size());
- return NO_ERROR;
-}
-
-status_t AudioSessionCollection::addSession(audio_session_t session,
- const sp<AudioSession>& audioSession)
-{
- ssize_t index = indexOfKey(session);
-
- if (index >= 0) {
- ALOGW("addSession() session %d already in", session);
- return ALREADY_EXISTS;
- }
- add(session, audioSession);
- ALOGV("addSession() session %d client %d source %d",
- session, audioSession->uid(), audioSession->inputSource());
- return NO_ERROR;
-}
-
-status_t AudioSessionCollection::removeSession(audio_session_t session)
-{
- ssize_t index = indexOfKey(session);
-
- if (index < 0) {
- ALOGW("removeSession() session %d not in", session);
- return ALREADY_EXISTS;
- }
- ALOGV("removeSession() session %d", session);
- removeItemsAt(index);
- return NO_ERROR;
-}
-
-uint32_t AudioSessionCollection::getOpenCount() const
-{
- uint32_t openCount = 0;
- for (size_t i = 0; i < size(); i++) {
- openCount += valueAt(i)->openCount();
- }
- return openCount;
-}
-
-AudioSessionCollection AudioSessionCollection::getActiveSessions() const
-{
- AudioSessionCollection activeSessions;
- for (size_t i = 0; i < size(); i++) {
- if (valueAt(i)->activeCount() != 0) {
- activeSessions.add(valueAt(i)->session(), valueAt(i));
- }
- }
- return activeSessions;
-}
-
-size_t AudioSessionCollection::getActiveSessionCount() const
-{
- size_t activeCount = 0;
- for (size_t i = 0; i < size(); i++) {
- if (valueAt(i)->activeCount() != 0) {
- activeCount++;
- }
- }
- return activeCount;
-}
-
-bool AudioSessionCollection::hasActiveSession() const
-{
- return getActiveSessionCount() != 0;
-}
-
-bool AudioSessionCollection::isSourceActive(audio_source_t source) const
-{
- for (size_t i = 0; i < size(); i++) {
- const sp<AudioSession> audioSession = valueAt(i);
- // AUDIO_SOURCE_HOTWORD is equivalent to AUDIO_SOURCE_VOICE_RECOGNITION only if it
- // corresponds to an active capture triggered by a hardware hotword recognition
- if (audioSession->activeCount() > 0 &&
- ((audioSession->inputSource() == source) ||
- ((source == AUDIO_SOURCE_VOICE_RECOGNITION) &&
- (audioSession->inputSource() == AUDIO_SOURCE_HOTWORD) &&
- audioSession->isSoundTrigger()))) {
- return true;
- }
- }
- return false;
-}
-
-audio_source_t AudioSessionCollection::getHighestPrioritySource(bool activeOnly) const
-{
- audio_source_t source = AUDIO_SOURCE_DEFAULT;
- int32_t priority = -1;
-
- for (size_t i = 0; i < size(); i++) {
- const sp<AudioSession> audioSession = valueAt(i);
- if (activeOnly && audioSession->activeCount() == 0) {
- continue;
- }
- int32_t curPriority = source_priority(audioSession->inputSource());
- if (curPriority > priority) {
- priority = curPriority;
- source = audioSession->inputSource();
- }
- }
- return source;
-}
-
-status_t AudioSessionCollection::dump(int fd, int spaces) const
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- snprintf(buffer, SIZE, "%*sAudio Sessions:\n", spaces, "");
- write(fd, buffer, strlen(buffer));
- for (size_t i = 0; i < size(); i++) {
- valueAt(i)->dump(fd, spaces + 2, i);
- }
- return NO_ERROR;
-}
-
-} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
index 5aca3cc..0d65a31 100644
--- a/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
@@ -76,9 +76,11 @@
SourceClientDescriptor::SourceClientDescriptor(audio_port_handle_t portId, uid_t uid,
audio_attributes_t attributes, const sp<AudioPatch>& patchDesc,
- const sp<DeviceDescriptor>& srcDevice, audio_stream_type_t stream) :
+ const sp<DeviceDescriptor>& srcDevice, audio_stream_type_t stream,
+ routing_strategy strategy) :
TrackClientDescriptor::TrackClientDescriptor(portId, uid, AUDIO_SESSION_NONE, attributes,
- AUDIO_CONFIG_BASE_INITIALIZER, AUDIO_PORT_HANDLE_NONE, stream, AUDIO_OUTPUT_FLAG_NONE),
+ AUDIO_CONFIG_BASE_INITIALIZER, AUDIO_PORT_HANDLE_NONE,
+ stream, strategy, AUDIO_OUTPUT_FLAG_NONE),
mPatchDesc(patchDesc), mSrcDevice(srcDevice)
{
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/SessionRoute.cpp b/services/audiopolicy/common/managerdefinitions/src/SessionRoute.cpp
deleted file mode 100644
index 440a4e7..0000000
--- a/services/audiopolicy/common/managerdefinitions/src/SessionRoute.cpp
+++ /dev/null
@@ -1,138 +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_SessionRoute"
-//#define LOG_NDEBUG 0
-
-#include "SessionRoute.h"
-#include "HwModule.h"
-#include "AudioGain.h"
-#include "DeviceDescriptor.h"
-#include <utils/Log.h>
-
-namespace android {
-
-// --- SessionRoute class implementation
-void SessionRoute::log(const char* prefix)
-{
- ALOGI("%s[SessionRoute strm:0x%X, src:%d, sess:0x%X, dev:0x%X refs:%d act:%d",
- prefix, mStreamType, mSource, mSession,
- mDeviceDescriptor != 0 ? mDeviceDescriptor->type() : AUDIO_DEVICE_NONE,
- mRefCount, mActivityCount);
-}
-
-// --- SessionRouteMap class implementation
-bool SessionRouteMap::hasRoute(audio_session_t session)
-{
- return indexOfKey(session) >= 0 && valueFor(session)->mDeviceDescriptor != 0;
-}
-
-bool SessionRouteMap::getAndClearRouteChanged(audio_session_t session)
-{
- if (indexOfKey(session) >= 0) {
- if (valueFor(session)->mChanged) {
- valueFor(session)->mChanged = false;
- return true;
- }
- }
- return false;
-}
-
-void SessionRouteMap::removeRoute(audio_session_t session)
-{
- sp<SessionRoute> route = indexOfKey(session) >= 0 ? valueFor(session) : 0;
- if (route != 0) {
- ALOG_ASSERT(route->mRefCount > 0);
- --route->mRefCount;
- if (route->mRefCount <= 0) {
- removeItem(session);
- }
- }
-}
-
-int SessionRouteMap::incRouteActivity(audio_session_t session)
-{
- sp<SessionRoute> route = indexOfKey(session) >= 0 ? valueFor(session) : 0;
- return route != 0 ? ++(route->mActivityCount) : -1;
-}
-
-int SessionRouteMap::decRouteActivity(audio_session_t session)
-{
- sp<SessionRoute> route = indexOfKey(session) >= 0 ? valueFor(session) : 0;
- if (route != 0 && route->mActivityCount > 0) {
- return --(route->mActivityCount);
- } else {
- return -1;
- }
-}
-
-void SessionRouteMap::log(const char* caption)
-{
- ALOGI("%s ----", caption);
- for (size_t index = 0; index < size(); index++) {
- valueAt(index)->log(" ");
- }
-}
-
-void SessionRouteMap::addRoute(audio_session_t session,
- audio_stream_type_t streamType,
- audio_source_t source,
- const sp<DeviceDescriptor>& descriptor,
- uid_t uid)
-{
- if (mMapType == MAPTYPE_INPUT && streamType != SessionRoute::STREAM_TYPE_NA) {
- ALOGE("Adding Output Route to InputRouteMap");
- return;
- } else if (mMapType == MAPTYPE_OUTPUT && source != SessionRoute::SOURCE_TYPE_NA) {
- ALOGE("Adding Input Route to OutputRouteMap");
- return;
- }
-
- sp<SessionRoute> route = indexOfKey(session) >= 0 ? valueFor(session) : 0;
-
- if (route != 0) {
- if (descriptor != 0 || route->mDeviceDescriptor != 0) {
- route->mChanged = true;
- }
- route->mRefCount++;
- route->mDeviceDescriptor = descriptor;
- } else {
- route = new SessionRoute(session, streamType, source, descriptor, uid);
- route->mRefCount++;
- if (descriptor != 0) {
- route->mChanged = true;
- }
- add(session, route);
- }
-}
-
-audio_devices_t SessionRouteMap::getActiveDeviceForStream(audio_stream_type_t streamType,
- const DeviceVector& availableDevices)
-{
- for (size_t index = 0; index < size(); index++) {
- sp<SessionRoute> route = valueAt(index);
- if (streamType == route->mStreamType && route->isActiveOrChanged()
- && route->mDeviceDescriptor != 0) {
- audio_devices_t device = route->mDeviceDescriptor->type();
- if (!availableDevices.getDevicesFromTypeMask(device).isEmpty()) {
- return device;
- }
- }
- }
- return AUDIO_DEVICE_NONE;
-}
-
-} // namespace android
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index e4f3cf1..60bce9c 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -517,7 +517,7 @@
// symmetric to the one in startInput()
for (const auto& activeDesc : mInputs.getActiveInputs()) {
if (activeDesc->hasSameHwModuleAs(txSourceDeviceDesc)) {
- closeSessions(activeDesc, true /*activeOnly*/);
+ closeActiveClients(activeDesc);
}
}
}
@@ -788,9 +788,14 @@
DeviceVector outputDevices;
routing_strategy strategy;
audio_devices_t device;
- audio_port_handle_t requestedDeviceId = *selectedDeviceId;
+ const audio_port_handle_t requestedDeviceId = *selectedDeviceId;
audio_devices_t msdDevice = getMsdAudioOutDeviceTypes();
+ // The supplied portId must be AUDIO_PORT_HANDLE_NONE
+ if (*portId != AUDIO_PORT_HANDLE_NONE) {
+ return INVALID_OPERATION;
+ }
+
if (attr != NULL) {
if (!isValidAttributes(attr)) {
ALOGE("getOutputForAttr() invalid attributes: usage=%d content=%d flags=0x%x tags=[%s]",
@@ -808,19 +813,19 @@
}
ALOGV("getOutputForAttr() usage=%d, content=%d, tag=%s flags=%08x"
- " session %d selectedDeviceId %d",
- attributes.usage, attributes.content_type, attributes.tags, attributes.flags,
- session, *selectedDeviceId);
+ " session %d selectedDeviceId %d",
+ attributes.usage, attributes.content_type, attributes.tags, attributes.flags,
+ session, requestedDeviceId);
- // TODO: check for existing client for this port ID
- if (*portId == AUDIO_PORT_HANDLE_NONE) {
- *portId = AudioPort::getNextUniqueId();
- }
+ *stream = streamTypefromAttributesInt(&attributes);
+
+ strategy = getStrategyForAttr(&attributes);
// First check for explicit routing (eg. setPreferredDevice)
- sp<DeviceDescriptor> deviceDesc;
- if (*selectedDeviceId != AUDIO_PORT_HANDLE_NONE) {
- deviceDesc = mAvailableOutputDevices.getDeviceFromId(*selectedDeviceId);
+ if (requestedDeviceId != AUDIO_PORT_HANDLE_NONE) {
+ sp<DeviceDescriptor> deviceDesc =
+ mAvailableOutputDevices.getDeviceFromId(requestedDeviceId);
+ device = deviceDesc->type();
} else {
// If no explict route, is there a matching dynamic policy that applies?
sp<SwAudioOutputDescriptor> desc;
@@ -831,6 +836,10 @@
}
*stream = streamTypefromAttributesInt(&attributes);
*output = desc->mIoHandle;
+ AudioMix *mix = desc->mPolicyMix;
+ sp<DeviceDescriptor> deviceDesc =
+ mAvailableOutputDevices.getDevice(mix->mDeviceType, mix->mDeviceAddress);
+ *selectedDeviceId = deviceDesc != 0 ? deviceDesc->getId() : AUDIO_PORT_HANDLE_NONE;
ALOGV("getOutputForAttr() returns output %d", *output);
goto exit;
}
@@ -840,25 +849,9 @@
ALOGW("getOutputForAttr() no policy mix found for usage AUDIO_USAGE_VIRTUAL_SOURCE");
return BAD_VALUE;
}
+ device = getDeviceForStrategy(strategy, false /*fromCache*/);
}
- // Virtual sources must always be dynamicaly or explicitly routed
- if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE) {
- ALOGW("getOutputForAttr() no policy mix found for usage AUDIO_USAGE_VIRTUAL_SOURCE");
- return BAD_VALUE;
- }
-
- *stream = streamTypefromAttributesInt(&attributes);
-
- // TODO: Should this happen only if an explicit route is active?
- // the previous code structure meant that this would always happen which
- // would appear to result in adding a null deviceDesc when not using an
- // explicit route. Is that the intended and necessary behavior?
- mOutputRoutes.addRoute(session, *stream, SessionRoute::SOURCE_TYPE_NA, deviceDesc, uid);
-
- strategy = (routing_strategy) getStrategyForAttr(&attributes);
- device = getDeviceForStrategy(strategy, false /*fromCache*/);
-
if ((attributes.flags & AUDIO_FLAG_HW_AV_SYNC) != 0) {
*flags = (audio_output_flags_t)(*flags | AUDIO_OUTPUT_FLAG_HW_AV_SYNC);
}
@@ -871,9 +864,10 @@
*stream == AUDIO_STREAM_MUSIC &&
audio_is_linear_pcm(config->format) &&
isInCall()) {
- if (*selectedDeviceId != AUDIO_PORT_HANDLE_NONE) {
+ if (requestedDeviceId != AUDIO_PORT_HANDLE_NONE) {
*flags = (audio_output_flags_t)AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
} else {
+ // Get the devce type directly from the engine to bypass preferred route logic
device = mEngine->getDeviceForStrategy(strategy);
}
}
@@ -897,7 +891,6 @@
*output = getOutputForDevice(device, session, *stream, config, flags);
}
if (*output == AUDIO_IO_HANDLE_NONE) {
- mOutputRoutes.removeRoute(session);
return INVALID_OPERATION;
}
@@ -909,11 +902,15 @@
audio_config_base_t clientConfig = {.sample_rate = config->sample_rate,
.format = config->format,
.channel_mask = config->channel_mask };
+ *portId = AudioPort::getNextUniqueId();
+
sp<TrackClientDescriptor> clientDesc =
- new TrackClientDescriptor(*portId, uid, session,
- attributes, clientConfig, requestedDeviceId, *stream, *flags);
+ new TrackClientDescriptor(*portId, uid, session, attributes, clientConfig,
+ requestedDeviceId, *stream,
+ getStrategyForAttr(&attributes),
+ *flags);
sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(*output);
- outputDesc->clients().emplace(*portId, clientDesc);
+ outputDesc->clientsMap().emplace(*portId, clientDesc);
ALOGV(" getOutputForAttr() returns output %d selectedDeviceId %d for port ID %d",
*output, *selectedDeviceId, *portId);
@@ -1037,8 +1034,6 @@
}
return AUDIO_IO_HANDLE_NONE;
}
- outputDesc->mRefCount[stream] = 0;
- outputDesc->mStopTime[stream] = 0;
outputDesc->mDirectOpenCount = 1;
outputDesc->mDirectClientSession = session;
@@ -1325,60 +1320,23 @@
ALOGW("startOutput() no output for client %d", portId);
return BAD_VALUE;
}
- sp<TrackClientDescriptor> client = outputDesc->clients()[portId];
- audio_stream_type_t stream = client->stream();
- audio_session_t session = client->session();
+ sp<TrackClientDescriptor> client = outputDesc->clientsMap()[portId];
ALOGV("startOutput() output %d, stream %d, session %d",
- outputDesc->mIoHandle, stream, session);
+ outputDesc->mIoHandle, client->stream(), client->session());
status_t status = outputDesc->start();
if (status != NO_ERROR) {
return status;
}
- // Routing?
- mOutputRoutes.incRouteActivity(session);
-
- audio_devices_t newDevice;
- AudioMix *policyMix = NULL;
- const char *address = NULL;
- if (outputDesc->mPolicyMix != NULL) {
- policyMix = outputDesc->mPolicyMix;
- address = policyMix->mDeviceAddress.string();
- if ((policyMix->mRouteFlags & MIX_ROUTE_FLAG_RENDER) == MIX_ROUTE_FLAG_RENDER) {
- newDevice = policyMix->mDeviceType;
- } else {
- newDevice = AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
- }
- } else if (mOutputRoutes.getAndClearRouteChanged(session)) {
- newDevice = getNewOutputDevice(outputDesc, false /*fromCache*/);
- if (newDevice != outputDesc->device()) {
- checkStrategyRoute(getStrategy(stream), outputDesc->mIoHandle);
- }
- } else {
- newDevice = AUDIO_DEVICE_NONE;
- }
-
- uint32_t delayMs = 0;
-
- status = startSource(outputDesc, stream, newDevice, address, &delayMs);
+ uint32_t delayMs;
+ status = startSource(outputDesc, client, &delayMs);
if (status != NO_ERROR) {
- mOutputRoutes.decRouteActivity(session);
outputDesc->stop();
return status;
}
- // Automatically enable the remote submix input when output is started on a re routing mix
- // of type MIX_TYPE_RECORDERS
- if (audio_is_remote_submix_device(newDevice) && policyMix != NULL &&
- policyMix->mMixType == MIX_TYPE_RECORDERS) {
- setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
- AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- address,
- "remote-submix");
- }
-
if (delayMs != 0) {
usleep(delayMs * 1000);
}
@@ -1386,16 +1344,15 @@
return status;
}
-status_t AudioPolicyManager::startSource(const sp<AudioOutputDescriptor>& outputDesc,
- audio_stream_type_t stream,
- audio_devices_t device,
- const char *address,
- uint32_t *delayMs)
+status_t AudioPolicyManager::startSource(const sp<SwAudioOutputDescriptor>& outputDesc,
+ const sp<TrackClientDescriptor>& client,
+ uint32_t *delayMs)
{
// cannot start playback of STREAM_TTS if any other output is being used
uint32_t beaconMuteLatency = 0;
*delayMs = 0;
+ audio_stream_type_t stream = client->stream();
if (stream == AUDIO_STREAM_TTS) {
ALOGV("\t found BEACON stream");
if (!mTtsOutputAvailable && mOutputs.isAnyOutputActive(AUDIO_STREAM_TTS /*streamToIgnore*/)) {
@@ -1413,6 +1370,19 @@
bool force = !outputDesc->isActive() &&
(outputDesc->getPatchHandle() == AUDIO_PATCH_HANDLE_NONE);
+ audio_devices_t device = AUDIO_DEVICE_NONE;
+ AudioMix *policyMix = NULL;
+ const char *address = NULL;
+ if (outputDesc->mPolicyMix != NULL) {
+ policyMix = outputDesc->mPolicyMix;
+ address = policyMix->mDeviceAddress.string();
+ if ((policyMix->mRouteFlags & MIX_ROUTE_FLAG_RENDER) == MIX_ROUTE_FLAG_RENDER) {
+ device = policyMix->mDeviceType;
+ } else {
+ device = AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+ }
+ }
+
// requiresMuteCheck is false when we can bypass mute strategy.
// It covers a common case when there is no materially active audio
// and muting would result in unnecessary delay and dropped audio.
@@ -1422,13 +1392,20 @@
// increment usage count for this stream on the requested output:
// NOTE that the usage count is the same for duplicated output and hardware output which is
// necessary for a correct control of hardware output routing by startOutput() and stopOutput()
- outputDesc->changeRefCount(stream, 1);
+ outputDesc->setClientActive(client, true);
+
+ if (client->hasPreferredDevice(true)) {
+ device = getNewOutputDevice(outputDesc, false /*fromCache*/);
+ if (device != outputDesc->device()) {
+ checkStrategyRoute(getStrategy(stream), outputDesc->mIoHandle);
+ }
+ }
if (stream == AUDIO_STREAM_MUSIC) {
selectOutputForMusicEffects();
}
- if (outputDesc->mRefCount[stream] == 1 || device != AUDIO_DEVICE_NONE) {
+ if (outputDesc->streamActiveCount(stream) == 1 || device != AUDIO_DEVICE_NONE) {
// starting an output being rerouted?
if (device == AUDIO_DEVICE_NONE) {
device = getNewOutputDevice(outputDesc, false /*fromCache*/);
@@ -1514,6 +1491,16 @@
setStrategyMute(STRATEGY_SONIFICATION, true, outputDesc);
}
+ // Automatically enable the remote submix input when output is started on a re routing mix
+ // of type MIX_TYPE_RECORDERS
+ if (audio_is_remote_submix_device(device) && policyMix != NULL &&
+ policyMix->mMixType == MIX_TYPE_RECORDERS) {
+ setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ address,
+ "remote-submix");
+ }
+
return NO_ERROR;
}
@@ -1526,37 +1513,12 @@
ALOGW("stopOutput() no output for client %d", portId);
return BAD_VALUE;
}
- sp<TrackClientDescriptor> client = outputDesc->clients()[portId];
- audio_stream_type_t stream = client->stream();
- audio_session_t session = client->session();
+ sp<TrackClientDescriptor> client = outputDesc->clientsMap()[portId];
- ALOGV("stopOutput() output %d, stream %d, session %d", outputDesc->mIoHandle, stream, session);
+ ALOGV("stopOutput() output %d, stream %d, session %d",
+ outputDesc->mIoHandle, client->stream(), client->session());
- if (outputDesc->mRefCount[stream] == 1) {
- // Automatically disable the remote submix input when output is stopped on a
- // re routing mix of type MIX_TYPE_RECORDERS
- if (audio_is_remote_submix_device(outputDesc->mDevice) &&
- outputDesc->mPolicyMix != NULL &&
- outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) {
- setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
- AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- outputDesc->mPolicyMix->mDeviceAddress,
- "remote-submix");
- }
- }
-
- // Routing?
- bool forceDeviceUpdate = false;
- if (outputDesc->mRefCount[stream] > 0) {
- int activityCount = mOutputRoutes.decRouteActivity(session);
- forceDeviceUpdate = (mOutputRoutes.hasRoute(session) && (activityCount == 0));
-
- if (forceDeviceUpdate) {
- checkStrategyRoute(getStrategy(stream), AUDIO_IO_HANDLE_NONE);
- }
- }
-
- status_t status = stopSource(outputDesc, stream, forceDeviceUpdate);
+ status_t status = stopSource(outputDesc, client);
if (status == NO_ERROR ) {
outputDesc->stop();
@@ -1564,19 +1526,38 @@
return status;
}
-status_t AudioPolicyManager::stopSource(const sp<AudioOutputDescriptor>& outputDesc,
- audio_stream_type_t stream,
- bool forceDeviceUpdate)
+status_t AudioPolicyManager::stopSource(const sp<SwAudioOutputDescriptor>& outputDesc,
+ const sp<TrackClientDescriptor>& client)
{
// always handle stream stop, check which stream type is stopping
+ audio_stream_type_t stream = client->stream();
+
handleEventForBeacon(stream == AUDIO_STREAM_TTS ? STOPPING_BEACON : STOPPING_OUTPUT);
- if (outputDesc->mRefCount[stream] > 0) {
+ if (outputDesc->streamActiveCount(stream) > 0) {
+ if (outputDesc->streamActiveCount(stream) == 1) {
+ // Automatically disable the remote submix input when output is stopped on a
+ // re routing mix of type MIX_TYPE_RECORDERS
+ if (audio_is_remote_submix_device(outputDesc->mDevice) &&
+ outputDesc->mPolicyMix != NULL &&
+ outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) {
+ setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+ AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ outputDesc->mPolicyMix->mDeviceAddress,
+ "remote-submix");
+ }
+ }
+ bool forceDeviceUpdate = false;
+ if (client->hasPreferredDevice(true)) {
+ checkStrategyRoute(getStrategy(stream), AUDIO_IO_HANDLE_NONE);
+ forceDeviceUpdate = true;
+ }
+
// decrement usage count of this stream on the output
- outputDesc->changeRefCount(stream, -1);
+ outputDesc->setClientActive(client, false);
// store time at which the stream was stopped - see isStreamActive()
- if (outputDesc->mRefCount[stream] == 0 || forceDeviceUpdate) {
+ if (outputDesc->streamActiveCount(stream) == 0 || forceDeviceUpdate) {
outputDesc->mStopTime[stream] = systemTime();
audio_devices_t newDevice = getNewOutputDevice(outputDesc, false /*fromCache*/);
// delay the device switch by twice the latency because stopOutput() is executed when
@@ -1636,14 +1617,10 @@
ALOGW("releaseOutput() no output for client %d", portId);
return;
}
- sp<TrackClientDescriptor> client = outputDesc->clients()[portId];
- audio_session_t session = client->session();
+ sp<TrackClientDescriptor> client = outputDesc->clientsMap()[portId];
ALOGV("releaseOutput() %d", outputDesc->mIoHandle);
- // Routing
- mOutputRoutes.removeRoute(session);
-
if (outputDesc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) {
if (outputDesc->mDirectOpenCount <= 0) {
ALOGW("releaseOutput() invalid open count %d for output %d",
@@ -1655,7 +1632,7 @@
mpClientInterface->onAudioPortListUpdate();
}
}
- outputDesc->clients().erase(portId);
+ outputDesc->clientsMap().erase(portId);
}
@@ -1683,6 +1660,13 @@
sp<AudioInputDescriptor> inputDesc;
sp<RecordClientDescriptor> clientDesc;
audio_port_handle_t requestedDeviceId = *selectedDeviceId;
+ bool isSoundTrigger;
+ audio_devices_t device;
+
+ // The supplied portId must be AUDIO_PORT_HANDLE_NONE
+ if (*portId != AUDIO_PORT_HANDLE_NONE) {
+ return INVALID_OPERATION;
+ }
if (inputSource == AUDIO_SOURCE_DEFAULT) {
inputSource = AUDIO_SOURCE_MIC;
@@ -1693,7 +1677,6 @@
if (*selectedDeviceId != AUDIO_PORT_HANDLE_NONE) {
deviceDesc = mAvailableInputDevices.getDeviceFromId(*selectedDeviceId);
}
- mInputRoutes.addRoute(session, SessionRoute::STREAM_TYPE_NA, inputSource, deviceDesc, uid);
// special case for mmap capture: if an input IO handle is specified, we reuse this input if
// possible
@@ -1706,8 +1689,8 @@
goto error;
}
sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(index);
- sp<AudioSession> audioSession = inputDesc->getAudioSession(session);
- if (audioSession == 0) {
+ RecordClientVector clients = inputDesc->getClientsForSession(session);
+ if (clients.size() == 0) {
ALOGW("getInputForAttr() unknown session %d on input %d", session, *input);
status = BAD_VALUE;
goto error;
@@ -1716,28 +1699,27 @@
// The second call is for the first active client and sets the UID. Any further call
// corresponds to a new client and is only permitted from the same UID.
// If the first UID is silenced, allow a new UID connection and replace with new UID
- if (audioSession->openCount() == 1) {
- audioSession->setUid(uid);
- } else if (audioSession->uid() != uid) {
- if (!audioSession->isSilenced()) {
- ALOGW("getInputForAttr() bad uid %d for session %d uid %d",
- uid, session, audioSession->uid());
- status = INVALID_OPERATION;
- goto error;
+ if (clients.size() > 1) {
+ for (const auto& client : clients) {
+ // The client map is ordered by key values (portId) and portIds are allocated
+ // incrementaly. So the first client in this list is the one opened by audio flinger
+ // when the mmap stream is created and should be ignored as it does not correspond
+ // to an actual client
+ if (client == *clients.cbegin()) {
+ continue;
+ }
+ if (uid != client->uid() && !client->isSilenced()) {
+ ALOGW("getInputForAttr() bad uid %d for client %d uid %d",
+ uid, client->portId(), client->uid());
+ status = INVALID_OPERATION;
+ goto error;
+ }
}
- audioSession->setUid(uid);
- audioSession->setSilenced(false);
}
- audioSession->changeOpenCount(1);
*inputType = API_INPUT_LEGACY;
- if (*portId == AUDIO_PORT_HANDLE_NONE) {
- *portId = AudioPort::getNextUniqueId();
- }
- inputDevices = mAvailableInputDevices.getDevicesFromTypeMask(inputDesc->mDevice);
- *selectedDeviceId = inputDevices.size() > 0 ? inputDevices.itemAt(0)->getId()
- : AUDIO_PORT_HANDLE_NONE;
- ALOGI("%s reusing MMAP input %d for session %d", __FUNCTION__, *input, session);
+ device = inputDesc->mDevice;
+ ALOGI("%s reusing MMAP input %d for session %d", __FUNCTION__, *input, session);
goto exit;
}
@@ -1746,13 +1728,6 @@
halInputSource = inputSource;
- // TODO: check for existing client for this port ID
- if (*portId == AUDIO_PORT_HANDLE_NONE) {
- *portId = AudioPort::getNextUniqueId();
- }
-
- audio_devices_t device;
-
if (inputSource == AUDIO_SOURCE_REMOTE_SUBMIX &&
strncmp(attr->tags, "addr=", strlen("addr=")) == 0) {
status = mPolicyMixes.getInputMixForAttr(*attr, &policyMix);
@@ -1763,7 +1738,11 @@
device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
address = String8(attr->tags + strlen("addr="));
} else {
- device = getDeviceAndMixForInputSource(inputSource, &policyMix);
+ if (deviceDesc != 0) {
+ device = deviceDesc->type();
+ } else {
+ device = getDeviceAndMixForInputSource(inputSource, &policyMix);
+ }
if (device == AUDIO_DEVICE_NONE) {
ALOGW("getInputForAttr() could not find device for source %d", inputSource);
status = BAD_VALUE;
@@ -1792,7 +1771,7 @@
}
- *input = getInputForDevice(device, address, session, uid, inputSource,
+ *input = getInputForDevice(device, address, session, inputSource,
config, flags,
policyMix);
if (*input == AUDIO_IO_HANDLE_NONE) {
@@ -1800,15 +1779,21 @@
goto error;
}
+exit:
+
inputDevices = mAvailableInputDevices.getDevicesFromTypeMask(device);
*selectedDeviceId = inputDevices.size() > 0 ? inputDevices.itemAt(0)->getId()
- : AUDIO_PORT_HANDLE_NONE;
+ : AUDIO_PORT_HANDLE_NONE;
-exit:
+ isSoundTrigger = inputSource == AUDIO_SOURCE_HOTWORD &&
+ mSoundTriggerSessions.indexOfKey(session) > 0;
+ *portId = AudioPort::getNextUniqueId();
+
clientDesc = new RecordClientDescriptor(*portId, uid, session,
- *attr, *config, requestedDeviceId, inputSource, flags);
+ *attr, *config, requestedDeviceId,
+ inputSource,flags, isSoundTrigger);
inputDesc = mInputs.valueFor(*input);
- inputDesc->clients().emplace(*portId, clientDesc);
+ inputDesc->clientsMap().emplace(*portId, clientDesc);
ALOGV("getInputForAttr() returns input %d type %d selectedDeviceId %d for port ID %d",
*input, *inputType, *selectedDeviceId, *portId);
@@ -1816,7 +1801,6 @@
return NO_ERROR;
error:
- mInputRoutes.removeRoute(session);
return status;
}
@@ -1824,7 +1808,6 @@
audio_io_handle_t AudioPolicyManager::getInputForDevice(audio_devices_t device,
String8 address,
audio_session_t session,
- uid_t uid,
audio_source_t inputSource,
const audio_config_base_t *config,
audio_input_flags_t flags,
@@ -1886,15 +1869,6 @@
return input;
}
- sp<AudioSession> audioSession = new AudioSession(session,
- inputSource,
- config->format,
- samplingRate,
- config->channel_mask,
- flags,
- uid,
- isSoundTrigger);
-
if (!profile->canOpenNewIo()) {
return AUDIO_IO_HANDLE_NONE;
}
@@ -1930,7 +1904,6 @@
}
inputDesc->mPolicyMix = policyMix;
- inputDesc->addAudioSession(session, audioSession);
addInput(input, inputDesc);
mpClientInterface->onAudioPortListUpdate();
@@ -1946,39 +1919,6 @@
(source == AUDIO_SOURCE_FM_TUNER);
}
-bool AudioPolicyManager::isConcurentCaptureAllowed(const sp<AudioInputDescriptor>& inputDesc,
- const sp<AudioSession>& audioSession)
-{
- // Do not allow capture if an active voice call is using a software patch and
- // the call TX source device is on the same HW module.
- // FIXME: would be better to refine to only inputs whose profile connects to the
- // call TX device but this information is not in the audio patch
- if (mCallTxPatch != 0 &&
- inputDesc->getModuleHandle() == mCallTxPatch->mPatch.sources[0].ext.device.hw_module) {
- return false;
- }
-
- // starting concurrent capture is enabled if:
- // 1) capturing for re-routing
- // 2) capturing for HOTWORD source
- // 3) capturing for FM TUNER source
- // 3) All other active captures are either for re-routing or HOTWORD
-
- if (is_virtual_input_device(inputDesc->mDevice) ||
- isConcurrentSource(audioSession->inputSource())) {
- return true;
- }
-
- for (const auto& activeInput : mInputs.getActiveInputs()) {
- if (!isConcurrentSource(activeInput->inputSource(true)) &&
- !is_virtual_input_device(activeInput->mDevice)) {
- return false;
- }
- }
-
- return true;
-}
-
// FIXME: remove when concurrent capture is ready. This is a hack to work around bug b/63083537.
bool AudioPolicyManager::soundTriggerSupportsConcurrentCapture() {
if (!mHasComputedSoundTriggerSupportsConcurrentCapture) {
@@ -2024,22 +1964,21 @@
sp<AudioInputDescriptor> inputDesc = mInputs.getInputForClient(portId);
if (inputDesc == 0) {
- ALOGW("startInput() no input for client %d", portId);
+ ALOGW("%s no input for client %d", __FUNCTION__, portId);
return BAD_VALUE;
}
- sp<RecordClientDescriptor> client = inputDesc->clients()[portId];
- audio_session_t session = client->session();
audio_io_handle_t input = inputDesc->mIoHandle;
-
- ALOGV("AudioPolicyManager::startInput(input:%d, session:%d, silenced:%d, concurrency:%d)",
- input, session, silenced, *concurrency);
-
- sp<AudioSession> audioSession = inputDesc->getAudioSession(session);
- if (audioSession == 0) {
- ALOGW("startInput() unknown session %d on input %d", session, input);
- return BAD_VALUE;
+ sp<RecordClientDescriptor> client = inputDesc->clientsMap()[portId];
+ if (client->active()) {
+ ALOGW("%s input %d client %d already started", __FUNCTION__, input, client->portId());
+ return INVALID_OPERATION;
}
+ audio_session_t session = client->session();
+
+ ALOGV("%s input:%d, session:%d, silenced:%d, concurrency:%d)",
+ __FUNCTION__, input, session, silenced, *concurrency);
+
if (!is_virtual_input_device(inputDesc->mDevice)) {
if (mCallTxPatch != 0 &&
inputDesc->getModuleHandle() == mCallTxPatch->mPatch.sources[0].ext.device.hw_module) {
@@ -2055,47 +1994,48 @@
// favor of the new one - "There can be only one" TM
if (!silenced) {
for (const auto& activeDesc : activeInputs) {
- if ((audioSession->flags() & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0 &&
+ if ((activeDesc->getAudioPort()->getFlags() & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0 &&
activeDesc->getId() == inputDesc->getId()) {
continue;
}
- AudioSessionCollection activeSessions = activeDesc->getAudioSessions(
- true /*activeOnly*/);
- sp<AudioSession> activeSession = activeSessions.valueAt(0);
- if (activeSession->isSilenced()) {
- closeSession(activeDesc, activeSession);
- ALOGV("startInput() session %d stopping silenced session %d", session, activeSession->session());
- activeInputs = mInputs.getActiveInputs();
+ RecordClientVector activeClients = activeDesc->clientsList(true /*activeOnly*/);
+ for (const auto& activeClient : activeClients) {
+ if (activeClient->isSilenced()) {
+ closeClient(activeClient->portId());
+ ALOGV("%s client %d stopping silenced client %d", __FUNCTION__,
+ portId, activeClient->portId());
+ activeInputs = mInputs.getActiveInputs();
+ }
}
}
}
for (const auto& activeDesc : activeInputs) {
- if ((audioSession->flags() & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0 &&
+ if ((client->flags() & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0 &&
activeDesc->getId() == inputDesc->getId()) {
continue;
}
audio_source_t activeSource = activeDesc->inputSource(true);
- if (audioSession->inputSource() == AUDIO_SOURCE_HOTWORD) {
+ if (client->source() == AUDIO_SOURCE_HOTWORD) {
if (activeSource == AUDIO_SOURCE_HOTWORD) {
if (activeDesc->hasPreemptedSession(session)) {
- ALOGW("startInput(%d) failed for HOTWORD: "
- "other input %d already started for HOTWORD",
+ ALOGW("%s input %d failed for HOTWORD: "
+ "other input %d already started for HOTWORD", __FUNCTION__,
input, activeDesc->mIoHandle);
*concurrency |= API_INPUT_CONCURRENCY_HOTWORD;
return INVALID_OPERATION;
}
} else {
- ALOGV("startInput(%d) failed for HOTWORD: other input %d already started",
- input, activeDesc->mIoHandle);
+ ALOGV("%s input %d failed for HOTWORD: other input %d already started",
+ __FUNCTION__, input, activeDesc->mIoHandle);
*concurrency |= API_INPUT_CONCURRENCY_CAPTURE;
return INVALID_OPERATION;
}
} else {
if (activeSource != AUDIO_SOURCE_HOTWORD) {
- ALOGW("startInput(%d) failed: other input %d already started",
+ ALOGW("%s input %d failed: other input %d already started", __FUNCTION__,
input, activeDesc->mIoHandle);
*concurrency |= API_INPUT_CONCURRENCY_CAPTURE;
return INVALID_OPERATION;
@@ -2114,80 +2054,75 @@
if (allowConcurrentWithSoundTrigger && activeDesc->isSoundTrigger()) {
continue;
}
-
- audio_source_t activeSource = activeDesc->inputSource(true);
- if (activeSource == AUDIO_SOURCE_HOTWORD) {
- AudioSessionCollection activeSessions =
- activeDesc->getAudioSessions(true /*activeOnly*/);
- sp<AudioSession> activeSession = activeSessions[0];
+ RecordClientVector activeHotwordClients =
+ activeDesc->clientsList(true, AUDIO_SOURCE_HOTWORD);
+ if (activeHotwordClients.size() > 0) {
SortedVector<audio_session_t> sessions = activeDesc->getPreemptedSessions();
- *concurrency |= API_INPUT_CONCURRENCY_PREEMPT;
- sessions.add(activeSession->session());
+
+ for (const auto& activeClient : activeHotwordClients) {
+ *concurrency |= API_INPUT_CONCURRENCY_PREEMPT;
+ sessions.add(activeClient->session());
+ closeClient(activeClient->portId());
+ ALOGV("%s input %d for HOTWORD preempting HOTWORD input %d", __FUNCTION__,
+ input, activeDesc->mIoHandle);
+ }
+
inputDesc->setPreemptedSessions(sessions);
- closeSession(inputDesc, activeSession);
- ALOGV("startInput(%d) for HOTWORD preempting HOTWORD input %d",
- input, activeDesc->mIoHandle);
}
}
}
// Make sure we start with the correct silence state
- audioSession->setSilenced(silenced);
+ client->setSilenced(silenced);
// increment activity count before calling getNewInputDevice() below as only active sessions
// are considered for device selection
- inputDesc->changeRefCount(session, 1);
+ inputDesc->setClientActive(client, true);
- // Routing?
- mInputRoutes.incRouteActivity(session);
+ // indicate active capture to sound trigger service if starting capture from a mic on
+ // primary HW module
+ audio_devices_t device = getNewInputDevice(inputDesc);
+ setInputDevice(input, device, true /* force */);
- if (audioSession->activeCount() == 1 || mInputRoutes.getAndClearRouteChanged(session)) {
- // indicate active capture to sound trigger service if starting capture from a mic on
- // primary HW module
- audio_devices_t device = getNewInputDevice(inputDesc);
- setInputDevice(input, device, true /* force */);
+ status_t status = inputDesc->start();
+ if (status != NO_ERROR) {
+ inputDesc->setClientActive(client, false);
+ return status;
+ }
- status_t status = inputDesc->start();
- if (status != NO_ERROR) {
- mInputRoutes.decRouteActivity(session);
- inputDesc->changeRefCount(session, -1);
- return status;
+ if (inputDesc->activeCount() == 1) {
+ // if input maps to a dynamic policy with an activity listener, notify of state change
+ if ((inputDesc->mPolicyMix != NULL)
+ && ((inputDesc->mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
+ mpClientInterface->onDynamicPolicyMixStateUpdate(inputDesc->mPolicyMix->mDeviceAddress,
+ MIX_STATE_MIXING);
}
- if (inputDesc->getAudioSessionCount(true/*activeOnly*/) == 1) {
- // if input maps to a dynamic policy with an activity listener, notify of state change
- if ((inputDesc->mPolicyMix != NULL)
- && ((inputDesc->mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
- mpClientInterface->onDynamicPolicyMixStateUpdate(inputDesc->mPolicyMix->mDeviceAddress,
- MIX_STATE_MIXING);
- }
+ audio_devices_t primaryInputDevices = availablePrimaryInputDevices();
+ if (((device & primaryInputDevices & ~AUDIO_DEVICE_BIT_IN) != 0) &&
+ mInputs.activeInputsCountOnDevices(primaryInputDevices) == 1) {
+ SoundTrigger::setCaptureState(true);
+ }
- audio_devices_t primaryInputDevices = availablePrimaryInputDevices();
- if (((device & primaryInputDevices & ~AUDIO_DEVICE_BIT_IN) != 0) &&
- mInputs.activeInputsCountOnDevices(primaryInputDevices) == 1) {
- SoundTrigger::setCaptureState(true);
+ // automatically enable the remote submix output when input is started if not
+ // used by a policy mix of type MIX_TYPE_RECORDERS
+ // For remote submix (a virtual device), we open only one input per capture request.
+ if (audio_is_remote_submix_device(inputDesc->mDevice)) {
+ String8 address = String8("");
+ if (inputDesc->mPolicyMix == NULL) {
+ address = String8("0");
+ } else if (inputDesc->mPolicyMix->mMixType == MIX_TYPE_PLAYERS) {
+ address = inputDesc->mPolicyMix->mDeviceAddress;
}
-
- // automatically enable the remote submix output when input is started if not
- // used by a policy mix of type MIX_TYPE_RECORDERS
- // For remote submix (a virtual device), we open only one input per capture request.
- if (audio_is_remote_submix_device(inputDesc->mDevice)) {
- String8 address = String8("");
- if (inputDesc->mPolicyMix == NULL) {
- address = String8("0");
- } else if (inputDesc->mPolicyMix->mMixType == MIX_TYPE_PLAYERS) {
- address = inputDesc->mPolicyMix->mDeviceAddress;
- }
- if (address != "") {
- setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
- AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- address, "remote-submix");
- }
+ if (address != "") {
+ setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ address, "remote-submix");
}
}
}
- ALOGV("AudioPolicyManager::startInput() input source = %d", audioSession->inputSource());
+ ALOGV("%s input %d source = %d exit", __FUNCTION__, input, client->source());
return NO_ERROR;
}
@@ -2198,67 +2133,56 @@
sp<AudioInputDescriptor> inputDesc = mInputs.getInputForClient(portId);
if (inputDesc == 0) {
- ALOGW("stopInput() no input for client %d", portId);
+ ALOGW("%s no input for client %d", __FUNCTION__, portId);
return BAD_VALUE;
}
- sp<RecordClientDescriptor> client = inputDesc->clients()[portId];
- audio_session_t session = client->session();
audio_io_handle_t input = inputDesc->mIoHandle;
-
- ALOGV("stopInput() input %d", input);
-
- sp<AudioSession> audioSession = inputDesc->getAudioSession(session);
-
- if (audioSession->activeCount() == 0) {
- ALOGW("stopInput() input %d already stopped", input);
+ sp<RecordClientDescriptor> client = inputDesc->clientsMap()[portId];
+ if (!client->active()) {
+ ALOGW("%s input %d client %d already stopped", __FUNCTION__, input, client->portId());
return INVALID_OPERATION;
}
- inputDesc->changeRefCount(session, -1);
+ inputDesc->setClientActive(client, false);
- // Routing?
- mInputRoutes.decRouteActivity(session);
-
- if (audioSession->activeCount() == 0) {
- inputDesc->stop();
- if (inputDesc->isActive()) {
- setInputDevice(input, getNewInputDevice(inputDesc), false /* force */);
- } else {
- // if input maps to a dynamic policy with an activity listener, notify of state change
- if ((inputDesc->mPolicyMix != NULL)
- && ((inputDesc->mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
- mpClientInterface->onDynamicPolicyMixStateUpdate(inputDesc->mPolicyMix->mDeviceAddress,
- MIX_STATE_IDLE);
- }
-
- // automatically disable the remote submix output when input is stopped if not
- // used by a policy mix of type MIX_TYPE_RECORDERS
- if (audio_is_remote_submix_device(inputDesc->mDevice)) {
- String8 address = String8("");
- if (inputDesc->mPolicyMix == NULL) {
- address = String8("0");
- } else if (inputDesc->mPolicyMix->mMixType == MIX_TYPE_PLAYERS) {
- address = inputDesc->mPolicyMix->mDeviceAddress;
- }
- if (address != "") {
- setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
- AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- address, "remote-submix");
- }
- }
-
- audio_devices_t device = inputDesc->mDevice;
- resetInputDevice(input);
-
- // indicate inactive capture to sound trigger service if stopping capture from a mic on
- // primary HW module
- audio_devices_t primaryInputDevices = availablePrimaryInputDevices();
- if (((device & primaryInputDevices & ~AUDIO_DEVICE_BIT_IN) != 0) &&
- mInputs.activeInputsCountOnDevices(primaryInputDevices) == 0) {
- SoundTrigger::setCaptureState(false);
- }
- inputDesc->clearPreemptedSessions();
+ inputDesc->stop();
+ if (inputDesc->isActive()) {
+ setInputDevice(input, getNewInputDevice(inputDesc), false /* force */);
+ } else {
+ // if input maps to a dynamic policy with an activity listener, notify of state change
+ if ((inputDesc->mPolicyMix != NULL)
+ && ((inputDesc->mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
+ mpClientInterface->onDynamicPolicyMixStateUpdate(inputDesc->mPolicyMix->mDeviceAddress,
+ MIX_STATE_IDLE);
}
+
+ // automatically disable the remote submix output when input is stopped if not
+ // used by a policy mix of type MIX_TYPE_RECORDERS
+ if (audio_is_remote_submix_device(inputDesc->mDevice)) {
+ String8 address = String8("");
+ if (inputDesc->mPolicyMix == NULL) {
+ address = String8("0");
+ } else if (inputDesc->mPolicyMix->mMixType == MIX_TYPE_PLAYERS) {
+ address = inputDesc->mPolicyMix->mDeviceAddress;
+ }
+ if (address != "") {
+ setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+ AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ address, "remote-submix");
+ }
+ }
+
+ audio_devices_t device = inputDesc->mDevice;
+ resetInputDevice(input);
+
+ // indicate inactive capture to sound trigger service if stopping capture from a mic on
+ // primary HW module
+ audio_devices_t primaryInputDevices = availablePrimaryInputDevices();
+ if (((device & primaryInputDevices & ~AUDIO_DEVICE_BIT_IN) != 0) &&
+ mInputs.activeInputsCountOnDevices(primaryInputDevices) == 0) {
+ SoundTrigger::setCaptureState(false);
+ }
+ inputDesc->clearPreemptedSessions();
}
return NO_ERROR;
}
@@ -2269,64 +2193,40 @@
sp<AudioInputDescriptor> inputDesc = mInputs.getInputForClient(portId);
if (inputDesc == 0) {
- ALOGW("releaseInput() no input for client %d", portId);
+ ALOGW("%s no input for client %d", __FUNCTION__, portId);
return;
}
- sp<RecordClientDescriptor> client = inputDesc->clients()[portId];
- audio_session_t session = client->session();
+ sp<RecordClientDescriptor> client = inputDesc->clientsMap()[portId];
audio_io_handle_t input = inputDesc->mIoHandle;
- ALOGV("releaseInput() %d", input);
+ ALOGV("%s %d", __FUNCTION__, input);
- // Routing
- mInputRoutes.removeRoute(session);
+ inputDesc->clientsMap().erase(portId);
- sp<AudioSession> audioSession = inputDesc->getAudioSession(session);
- if (audioSession == 0) {
- ALOGW("releaseInput() unknown session %d on input %d", session, input);
- return;
- }
-
- if (audioSession->openCount() == 0) {
- ALOGW("releaseInput() invalid open count %d on session %d",
- audioSession->openCount(), session);
- return;
- }
-
- if (audioSession->changeOpenCount(-1) == 0) {
- inputDesc->removeAudioSession(session);
- }
-
- if (inputDesc->getOpenRefCount() > 0) {
- ALOGV("releaseInput() exit > 0");
+ if (inputDesc->clientsMap().size() > 0) {
+ ALOGV("%s %zu clients remaining", __FUNCTION__, inputDesc->clientsMap().size());
return;
}
closeInput(input);
- inputDesc->clients().erase(portId);
mpClientInterface->onAudioPortListUpdate();
- ALOGV("releaseInput() exit");
+ ALOGV("%s exit", __FUNCTION__);
}
-void AudioPolicyManager::closeSessions(const sp<AudioInputDescriptor>& input, bool activeOnly)
+void AudioPolicyManager::closeActiveClients(const sp<AudioInputDescriptor>& input)
{
- AudioSessionCollection sessions = input->getAudioSessions(activeOnly /*activeOnly*/);
- for (size_t i = 0; i < sessions.size(); i++) {
- closeSession(input, sessions[i]);
- }
-}
-
-void AudioPolicyManager::closeSession(const sp<AudioInputDescriptor>& input,
- const sp<AudioSession>& session)
-{
- RecordClientVector clients = input->getClientsForSession(session->session());
+ RecordClientVector clients = input->clientsList(true);
for (const auto& client : clients) {
- stopInput(client->portId());
- releaseInput(client->portId());
+ closeClient(client->portId());
}
}
+void AudioPolicyManager::closeClient(audio_port_handle_t portId)
+{
+ stopInput(portId);
+ releaseInput(portId);
+}
void AudioPolicyManager::closeAllInputs() {
bool patchRemoved = false;
@@ -2342,7 +2242,6 @@
}
inputDesc->close();
}
- mInputRoutes.clear();
mInputs.clear();
SoundTrigger::setCaptureState(false);
nextAudioPortGeneration();
@@ -2619,12 +2518,13 @@
sp<HwModule> rSubmixModule;
// examine each mix's route type
for (size_t i = 0; i < mixes.size(); i++) {
+ AudioMix mix = mixes[i];
// we only support MIX_ROUTE_FLAG_LOOP_BACK or MIX_ROUTE_FLAG_RENDER, not the combination
- if ((mixes[i].mRouteFlags & MIX_ROUTE_FLAG_ALL) == MIX_ROUTE_FLAG_ALL) {
+ if ((mix.mRouteFlags & MIX_ROUTE_FLAG_ALL) == MIX_ROUTE_FLAG_ALL) {
res = INVALID_OPERATION;
break;
}
- if ((mixes[i].mRouteFlags & MIX_ROUTE_FLAG_LOOP_BACK) == MIX_ROUTE_FLAG_LOOP_BACK) {
+ if ((mix.mRouteFlags & MIX_ROUTE_FLAG_LOOP_BACK) == MIX_ROUTE_FLAG_LOOP_BACK) {
ALOGV("registerPolicyMixes() mix %zu of %zu is LOOP_BACK", i, mixes.size());
if (rSubmixModule == 0) {
rSubmixModule = mHwModules.getModuleFromName(
@@ -2637,15 +2537,20 @@
}
}
- String8 address = mixes[i].mDeviceAddress;
+ String8 address = mix.mDeviceAddress;
+ if (mix.mMixType == MIX_TYPE_PLAYERS) {
+ mix.mDeviceType = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
+ } else {
+ mix.mDeviceType = AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+ }
- if (mPolicyMixes.registerMix(address, mixes[i], 0 /*output desc*/) != NO_ERROR) {
+ if (mPolicyMixes.registerMix(address, mix, 0 /*output desc*/) != NO_ERROR) {
ALOGE(" Error registering mix %zu for address %s", i, address.string());
res = INVALID_OPERATION;
break;
}
- audio_config_t outputConfig = mixes[i].mFormat;
- audio_config_t inputConfig = mixes[i].mFormat;
+ audio_config_t outputConfig = mix.mFormat;
+ audio_config_t inputConfig = mix.mFormat;
// NOTE: audio flinger mixer does not support mono output: configure remote submix HAL in
// stereo and let audio flinger do the channel conversion if needed.
outputConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
@@ -2655,7 +2560,7 @@
rSubmixModule->addInputProfile(address, &inputConfig,
AUDIO_DEVICE_IN_REMOTE_SUBMIX, address);
- if (mixes[i].mMixType == MIX_TYPE_PLAYERS) {
+ if (mix.mMixType == MIX_TYPE_PLAYERS) {
setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
address.string(), "remote-submix");
@@ -2664,9 +2569,9 @@
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
address.string(), "remote-submix");
}
- } else if ((mixes[i].mRouteFlags & MIX_ROUTE_FLAG_RENDER) == MIX_ROUTE_FLAG_RENDER) {
- String8 address = mixes[i].mDeviceAddress;
- audio_devices_t device = mixes[i].mDeviceType;
+ } else if ((mix.mRouteFlags & MIX_ROUTE_FLAG_RENDER) == MIX_ROUTE_FLAG_RENDER) {
+ String8 address = mix.mDeviceAddress;
+ audio_devices_t device = mix.mDeviceType;
ALOGV(" registerPolicyMixes() mix %zu of %zu is RENDER, dev=0x%X addr=%s",
i, mixes.size(), device, address.string());
@@ -2679,7 +2584,7 @@
&& (patch->mPatch.sinks[0].ext.device.type == device)
&& (strncmp(patch->mPatch.sinks[0].ext.device.address, address.string(),
AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0)) {
- if (mPolicyMixes.registerMix(address, mixes[i], desc) != NO_ERROR) {
+ if (mPolicyMixes.registerMix(address, mix, desc) != NO_ERROR) {
res = INVALID_OPERATION;
} else {
foundOutput = true;
@@ -3391,12 +3296,13 @@
{
// remove output routes associated with this uid
SortedVector<routing_strategy> affectedStrategies;
- for (ssize_t i = (ssize_t)mOutputRoutes.size() - 1; i >= 0; i--) {
- sp<SessionRoute> route = mOutputRoutes.valueAt(i);
- if (route->mUid == uid) {
- mOutputRoutes.removeItemsAt(i);
- if (route->mDeviceDescriptor != 0) {
- affectedStrategies.add(getStrategy(route->mStreamType));
+ for (size_t i = 0; i < mOutputs.size(); i++) {
+ sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
+ TrackClientMap clients = outputDesc->clientsMap();
+ for (const auto& client : clients) {
+ if (client.second->hasPreferredDevice() && client.second->uid() == uid) {
+ client.second->setPreferredDeviceId(AUDIO_PORT_HANDLE_NONE);
+ affectedStrategies.add(getStrategy(client.second->stream()));
}
}
}
@@ -3407,12 +3313,13 @@
// remove input routes associated with this uid
SortedVector<audio_source_t> affectedSources;
- for (ssize_t i = (ssize_t)mInputRoutes.size() - 1; i >= 0; i--) {
- sp<SessionRoute> route = mInputRoutes.valueAt(i);
- if (route->mUid == uid) {
- mInputRoutes.removeItemsAt(i);
- if (route->mDeviceDescriptor != 0) {
- affectedSources.add(route->mSource);
+ for (size_t i = 0; i < mInputs.size(); i++) {
+ sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(i);
+ RecordClientMap clients = inputDesc->clientsMap();
+ for (const auto& client : clients) {
+ if (client.second->hasPreferredDevice() && client.second->uid() == uid) {
+ client.second->setPreferredDeviceId(AUDIO_PORT_HANDLE_NONE);
+ affectedSources.add(client.second->source());
}
}
}
@@ -3486,7 +3393,8 @@
sp<SourceClientDescriptor> sourceDesc =
new SourceClientDescriptor(*portId, uid, *attributes, patchDesc, srcDeviceDesc,
- streamTypefromAttributesInt(attributes));
+ streamTypefromAttributesInt(attributes),
+ getStrategyForAttr(attributes));
status_t status = connectAudioSource(sourceDesc);
if (status == NO_ERROR) {
@@ -3503,7 +3411,7 @@
disconnectAudioSource(sourceDesc);
audio_attributes_t attributes = sourceDesc->attributes();
- routing_strategy strategy = (routing_strategy) getStrategyForAttr(&attributes);
+ routing_strategy strategy = getStrategyForAttr(&attributes);
audio_stream_type_t stream = sourceDesc->stream();
sp<DeviceDescriptor> srcDeviceDesc = sourceDesc->srcDevice();
@@ -3557,7 +3465,7 @@
return INVALID_OPERATION;
}
uint32_t delayMs = 0;
- status = startSource(outputDesc, stream, sinkDevice, NULL, &delayMs);
+ status = startSource(outputDesc, sourceDesc, &delayMs);
if (status != NO_ERROR) {
mpClientInterface->releaseAudioPatch(sourceDesc->patchDesc()->mAfPatchHandle, 0);
@@ -3909,11 +3817,10 @@
Vector<sp<AudioInputDescriptor> > activeInputs = mInputs.getActiveInputs();
for (size_t i = 0; i < activeInputs.size(); i++) {
sp<AudioInputDescriptor> activeDesc = activeInputs[i];
- AudioSessionCollection activeSessions = activeDesc->getAudioSessions(true);
- for (size_t j = 0; j < activeSessions.size(); j++) {
- sp<AudioSession> activeSession = activeSessions.valueAt(j);
- if (activeSession->uid() == uid) {
- activeSession->setSilenced(silenced);
+ RecordClientVector clients = activeDesc->clientsList(true /*activeOnly*/);
+ for (const auto& client : clients) {
+ if (uid == client->uid()) {
+ client->setSilenced(silenced);
}
}
}
@@ -3931,10 +3838,9 @@
}
removeAudioPatch(sourceDesc->patchDesc()->mHandle);
- audio_stream_type_t stream = sourceDesc->stream();
sp<SwAudioOutputDescriptor> swOutputDesc = sourceDesc->swOutput().promote();
if (swOutputDesc != 0) {
- status_t status = stopSource(swOutputDesc, stream, false);
+ status_t status = stopSource(swOutputDesc, sourceDesc);
if (status == NO_ERROR) {
swOutputDesc->stop();
}
@@ -3958,8 +3864,7 @@
for (size_t i = 0; i < mAudioSources.size(); i++) {
sp<SourceClientDescriptor> sourceDesc = mAudioSources.valueAt(i);
audio_attributes_t attributes = sourceDesc->attributes();
- routing_strategy sourceStrategy =
- (routing_strategy) getStrategyForAttr(&attributes);
+ routing_strategy sourceStrategy = getStrategyForAttr(&attributes);
sp<SwAudioOutputDescriptor> outputDesc = sourceDesc->swOutput().promote();
if (sourceStrategy == strategy && outputDesc != 0 && outputDesc->mIoHandle == output) {
source = sourceDesc;
@@ -4712,8 +4617,8 @@
// the other output.
bool wasActive = outputDesc2->isActive();
for (int j = 0; j < AUDIO_STREAM_CNT; j++) {
- int refCount = dupOutputDesc->mRefCount[j];
- outputDesc2->changeRefCount((audio_stream_type_t)j,-refCount);
+ int activeCount = dupOutputDesc->streamActiveCount((audio_stream_type_t)j);
+ outputDesc2->changeStreamActiveCount((audio_stream_type_t)j,-activeCount);
}
// stop() will be a no op if the output is still active but is needed in case all
// active streams refcounts where cleared above
@@ -4936,11 +4841,41 @@
}
}
+template <class IoDescriptor, class Filter>
+sp<DeviceDescriptor> AudioPolicyManager::findPreferredDevice(
+ IoDescriptor& desc, Filter filter, bool& active, const DeviceVector& devices)
+{
+ auto activeClients = desc->clientsList(true /*activeOnly*/);
+ auto activeClientsWithRoute =
+ desc->clientsList(true /*activeOnly*/, filter, true /*preferredDevice*/);
+ active = activeClients.size() > 0;
+ if (active && activeClients.size() == activeClientsWithRoute.size()) {
+ return devices.getDeviceFromId(activeClientsWithRoute[0]->preferredDeviceId());
+ }
+ return nullptr;
+}
+
+template <class IoCollection, class Filter>
+sp<DeviceDescriptor> AudioPolicyManager::findPreferredDevice(
+ IoCollection& ioCollection, Filter filter, const DeviceVector& devices)
+{
+ sp<DeviceDescriptor> device;
+ for (size_t i = 0; i < ioCollection.size(); i++) {
+ auto desc = ioCollection.valueAt(i);
+ bool active;
+ sp<DeviceDescriptor> curDevice = findPreferredDevice(desc, filter, active, devices);
+ if (active && curDevice == nullptr) {
+ return nullptr;
+ } else if (curDevice != nullptr) {
+ device = curDevice;
+ }
+ }
+ return device;
+}
+
audio_devices_t AudioPolicyManager::getNewOutputDevice(const sp<AudioOutputDescriptor>& outputDesc,
bool fromCache)
{
- audio_devices_t device = AUDIO_DEVICE_NONE;
-
ssize_t index = mAudioPatches.indexOfKey(outputDesc->getPatchHandle());
if (index >= 0) {
sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index);
@@ -4951,18 +4886,13 @@
}
}
- // Check if an explicit routing request exists for an active stream on this output and
- // use it in priority before any other rule
- for (int stream = 0; stream < AUDIO_STREAM_FOR_POLICY_CNT; stream++) {
- if (outputDesc->isStreamActive((audio_stream_type_t)stream)) {
- audio_devices_t forcedDevice =
- mOutputRoutes.getActiveDeviceForStream(
- (audio_stream_type_t)stream, mAvailableOutputDevices);
-
- if (forcedDevice != AUDIO_DEVICE_NONE) {
- return forcedDevice;
- }
- }
+ // Honor explicit routing requests only if no client using default routing is active on this
+ // input: a specific app can not force routing for other apps by setting a preferred device.
+ bool active; // unused
+ sp<DeviceDescriptor> deviceDesc =
+ findPreferredDevice(outputDesc, STRATEGY_NONE, active, mAvailableOutputDevices);
+ if (deviceDesc != nullptr) {
+ return deviceDesc->type();
}
// check the following by order of priority to request a routing change if necessary:
@@ -4988,6 +4918,7 @@
// FIXME: extend use of isStrategyActiveOnSameModule() to all strategies
// with a refined rule considering mutually exclusive devices (using same backend)
// as opposed to all streams on the same audio HAL module.
+ audio_devices_t device = AUDIO_DEVICE_NONE;
if (isStrategyActive(outputDesc, STRATEGY_ENFORCED_AUDIBLE) &&
mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) {
device = getDeviceForStrategy(STRATEGY_ENFORCED_AUDIBLE, fromCache);
@@ -5030,6 +4961,15 @@
}
}
+ // Honor explicit routing requests only if no client using default routing is active on this
+ // input: a specific app can not force routing for other apps by setting a preferred device.
+ bool active;
+ sp<DeviceDescriptor> deviceDesc =
+ findPreferredDevice(inputDesc, AUDIO_SOURCE_DEFAULT, active, mAvailableInputDevices);
+ if (deviceDesc != nullptr) {
+ return deviceDesc->type();
+ }
+
// If we are not in call and no client is active on this input, this methods returns
// AUDIO_DEVICE_NONE, causing the patch on the input stream to be released.
audio_source_t source = inputDesc->getHighestPrioritySource(true /*activeOnly*/);
@@ -5059,6 +4999,7 @@
if (stream < (audio_stream_type_t) 0 || stream >= AUDIO_STREAM_PUBLIC_CNT) {
return AUDIO_DEVICE_NONE;
}
+ audio_devices_t activeDevices = AUDIO_DEVICE_NONE;
audio_devices_t devices = AUDIO_DEVICE_NONE;
for (int curStream = 0; curStream < AUDIO_STREAM_FOR_POLICY_CNT; curStream++) {
if (!streamsMatchForvolume(stream, (audio_stream_type_t)curStream)) {
@@ -5067,15 +5008,20 @@
routing_strategy curStrategy = getStrategy((audio_stream_type_t)curStream);
audio_devices_t curDevices =
getDeviceForStrategy((routing_strategy)curStrategy, false /*fromCache*/);
+ devices |= curDevices;
for (audio_io_handle_t output : getOutputsForDevice(curDevices, mOutputs)) {
sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
if (outputDesc->isStreamActive((audio_stream_type_t)curStream)) {
- curDevices |= outputDesc->device();
+ activeDevices |= outputDesc->device();
}
}
- devices |= curDevices;
}
+ // Favor devices selected on active streams if any to report correct device in case of
+ // explicit device selection
+ if (activeDevices != AUDIO_DEVICE_NONE) {
+ devices = activeDevices;
+ }
/*Filter SPEAKER_SAFE out of results, as AudioService doesn't know about it
and doesn't really need to.*/
if (devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
@@ -5091,16 +5037,16 @@
return mEngine->getStrategyForStream(stream);
}
-uint32_t AudioPolicyManager::getStrategyForAttr(const audio_attributes_t *attr) {
+routing_strategy AudioPolicyManager::getStrategyForAttr(const audio_attributes_t *attr) {
// flags to strategy mapping
if ((attr->flags & AUDIO_FLAG_BEACON) == AUDIO_FLAG_BEACON) {
- return (uint32_t) STRATEGY_TRANSMITTED_THROUGH_SPEAKER;
+ return STRATEGY_TRANSMITTED_THROUGH_SPEAKER;
}
if ((attr->flags & AUDIO_FLAG_AUDIBILITY_ENFORCED) == AUDIO_FLAG_AUDIBILITY_ENFORCED) {
- return (uint32_t) STRATEGY_ENFORCED_AUDIBLE;
+ return STRATEGY_ENFORCED_AUDIBLE;
}
// usage to strategy mapping
- return static_cast<uint32_t>(mEngine->getStrategyForUsage(attr->usage));
+ return mEngine->getStrategyForUsage(attr->usage);
}
void AudioPolicyManager::handleNotificationRoutingForStream(audio_stream_type_t stream) {
@@ -5176,17 +5122,11 @@
audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strategy,
bool fromCache)
{
- // Check if an explicit routing request exists for a stream type corresponding to the
- // specified strategy and use it in priority over default routing rules.
- for (int stream = 0; stream < AUDIO_STREAM_FOR_POLICY_CNT; stream++) {
- if (getStrategy((audio_stream_type_t)stream) == strategy) {
- audio_devices_t forcedDevice =
- mOutputRoutes.getActiveDeviceForStream(
- (audio_stream_type_t)stream, mAvailableOutputDevices);
- if (forcedDevice != AUDIO_DEVICE_NONE) {
- return forcedDevice;
- }
- }
+ // Honor explicit routing requests only if all active clients have a preferred route in which
+ // case the last active client route is used
+ sp<DeviceDescriptor> deviceDesc = findPreferredDevice(mOutputs, strategy, mAvailableOutputDevices);
+ if (deviceDesc != nullptr) {
+ return deviceDesc->type();
}
if (fromCache) {
@@ -5530,6 +5470,15 @@
audio_devices_t AudioPolicyManager::getDeviceAndMixForInputSource(audio_source_t inputSource,
AudioMix **policyMix)
{
+ // Honor explicit routing requests only if all active clients have a preferred route in which
+ // case the last active client route is used
+ sp<DeviceDescriptor> deviceDesc =
+ findPreferredDevice(mInputs, inputSource, mAvailableInputDevices);
+ if (deviceDesc != nullptr) {
+ return deviceDesc->type();
+ }
+
+
audio_devices_t availableDeviceTypes = mAvailableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN;
audio_devices_t selectedDeviceFromMix =
mPolicyMixes.getDeviceAndMixForInputSource(inputSource, availableDeviceTypes, policyMix);
@@ -5542,20 +5491,7 @@
audio_devices_t AudioPolicyManager::getDeviceForInputSource(audio_source_t inputSource)
{
- // Routing
- // Scan the whole RouteMap to see if we have an explicit route:
- // if the input source in the RouteMap is the same as the argument above,
- // and activity count is non-zero and the device in the route descriptor is available
- // then select this device.
- for (size_t routeIndex = 0; routeIndex < mInputRoutes.size(); routeIndex++) {
- sp<SessionRoute> route = mInputRoutes.valueAt(routeIndex);
- if ((inputSource == route->mSource) && route->isActiveOrChanged() &&
- (mAvailableInputDevices.indexOf(route->mDeviceDescriptor) >= 0)) {
- return route->mDeviceDescriptor->type();
- }
- }
-
- return mEngine->getDeviceForInputSource(inputSource);
+ return mEngine->getDeviceForInputSource(inputSource);
}
float AudioPolicyManager::computeVolume(audio_stream_type_t stream,
@@ -5860,7 +5796,7 @@
}
for (int i = 0; i < (int)AUDIO_STREAM_FOR_POLICY_CNT; i++) {
if (((getStrategy((audio_stream_type_t)i) == strategy) ||
- (NUM_STRATEGIES == strategy)) &&
+ (STRATEGY_NONE == strategy)) &&
outputDesc->isStreamActive((audio_stream_type_t)i, inPastMs, sysTime)) {
return true;
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 9436767..6f4cce1 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -49,7 +49,6 @@
#include <AudioPolicyMix.h>
#include <EffectDescriptor.h>
#include <SoundTriggerSession.h>
-#include <SessionRoute.h>
#include <VolumeCurve.h>
namespace android {
@@ -156,7 +155,7 @@
// return the strategy corresponding to a given stream type
virtual uint32_t getStrategyForStream(audio_stream_type_t stream);
// return the strategy corresponding to the given audio attributes
- virtual uint32_t getStrategyForAttr(const audio_attributes_t *attr);
+ virtual routing_strategy getStrategyForAttr(const audio_attributes_t *attr);
// return the enabled output devices for the given stream type
virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream);
@@ -366,7 +365,7 @@
bool on,
const sp<AudioOutputDescriptor>& outputDesc,
int delayMs = 0,
- audio_devices_t device = (audio_devices_t)0);
+ audio_devices_t device = AUDIO_DEVICE_NONE);
// Mute or unmute the stream on the specified output
void setStreamMute(audio_stream_type_t stream,
@@ -422,6 +421,14 @@
// manages A2DP output suspend/restore according to phone state and BT SCO usage
void checkA2dpSuspend();
+ template <class IoDescriptor, class Filter>
+ sp<DeviceDescriptor> findPreferredDevice(IoDescriptor& desc, Filter filter,
+ bool& active, const DeviceVector& devices);
+
+ template <class IoCollection, class Filter>
+ sp<DeviceDescriptor> findPreferredDevice(IoCollection& ioCollection, Filter filter,
+ const DeviceVector& devices);
+
// 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..
@@ -508,16 +515,11 @@
sp<DeviceDescriptor> findDevice(
const DeviceVector& devices, audio_devices_t device) const;
- // if argument "device" is different from AUDIO_DEVICE_NONE, startSource() will force
- // the re-evaluation of the output device.
- status_t startSource(const sp<AudioOutputDescriptor>& outputDesc,
- audio_stream_type_t stream,
- audio_devices_t device,
- const char *address,
+ status_t startSource(const sp<SwAudioOutputDescriptor>& outputDesc,
+ const sp<TrackClientDescriptor>& client,
uint32_t *delayMs);
- status_t stopSource(const sp<AudioOutputDescriptor>& outputDesc,
- audio_stream_type_t stream,
- bool forceDeviceUpdate);
+ status_t stopSource(const sp<SwAudioOutputDescriptor>& outputDesc,
+ const sp<TrackClientDescriptor>& client);
void clearAudioPatches(uid_t uid);
void clearSessionRoutes(uid_t uid);
@@ -537,15 +539,11 @@
static bool isConcurrentSource(audio_source_t source);
- bool isConcurentCaptureAllowed(const sp<AudioInputDescriptor>& inputDesc,
- const sp<AudioSession>& audioSession);
-
static bool streamsMatchForvolume(audio_stream_type_t stream1,
audio_stream_type_t stream2);
- void closeSessions(const sp<AudioInputDescriptor>& input, bool activeOnly);
- void closeSession(const sp<AudioInputDescriptor>& input,
- const sp<AudioSession>& session);
+ void closeActiveClients(const sp<AudioInputDescriptor>& input);
+ void closeClient(audio_port_handle_t portId);
const uid_t mUidCached; // AID_AUDIOSERVER
AudioPolicyClientInterface *mpClientInterface; // audio policy client interface
@@ -561,9 +559,6 @@
DeviceVector mAvailableOutputDevices; // all available output devices
DeviceVector mAvailableInputDevices; // all available input devices
- SessionRouteMap mOutputRoutes = SessionRouteMap(SessionRouteMap::MAPTYPE_OUTPUT);
- SessionRouteMap mInputRoutes = SessionRouteMap(SessionRouteMap::MAPTYPE_INPUT);
-
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
@@ -668,7 +663,6 @@
audio_io_handle_t getInputForDevice(audio_devices_t device,
String8 address,
audio_session_t session,
- uid_t uid,
audio_source_t inputSource,
const audio_config_base_t *config,
audio_input_flags_t flags,