Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8f42ea1f authored by Eric Laurent's avatar Eric Laurent
Browse files

audio policy: remove AudioSession class

Now that clients are tracked individually, tracking by
audio session is no needed anymore.
Modify management of client activity, preempted sound trigger
sessions and silenced uids to rely on RecordClientDescriptor
instead of AudioSession.

Test: CTS test for AudioRecord
Test: manual capture audio tests for all use cases

Change-Id: Ieef3e05daea98aec9320412393f912bd6bd7e046
parent 97ac871c
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ LOCAL_SRC_FILES:= \
    src/SoundTriggerSession.cpp \
    src/VolumeCurve.cpp \
    src/TypeConverter.cpp \
    src/AudioSession.cpp \
    src/ClientDescriptor.cpp

LOCAL_SHARED_LIBRARIES := \
+12 −21
Original line number Diff line number Diff line
@@ -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 @@ public:
                                  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 @@ public:
    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,10 +75,10 @@ public:
                  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();

@@ -96,12 +89,10 @@ public:

 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.
@@ -110,7 +101,7 @@ public:
    // 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;
};
+0 −96
Original line number Diff line number Diff line
/*
 * 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
+7 −2
Original line number Diff line number Diff line
@@ -107,9 +107,9 @@ public:
    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;
@@ -117,10 +117,15 @@ public:

    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
+57 −89
Original line number Diff line number Diff line
@@ -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 @@ AudioInputDescriptor::AudioInputDescriptor(const sp<IOProfile>& profile,
    : 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 @@ audio_module_handle_t AudioInputDescriptor::getModuleHandle() const
    return mProfile->getModuleHandle();
}

uint32_t AudioInputDescriptor::getOpenRefCount() const
{
    return mSessions.getOpenCount();
}

audio_port_handle_t AudioInputDescriptor::getId() const
{
    return mId;
@@ -118,57 +113,45 @@ void AudioInputDescriptor::clearPreemptedSessions()
    mPreemptedSessions.clear();
}

bool AudioInputDescriptor::isActive() const {
    return mSessions.hasActiveSession();
}

bool AudioInputDescriptor::isSourceActive(audio_source_t source) const
{
    return mSessions.isSourceActive(source);
}

audio_source_t AudioInputDescriptor::getHighestPrioritySource(bool activeOnly) const
{

    return mSessions.getHighestPrioritySource(activeOnly);
    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;
        }

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);
    return false;
}

AudioSessionCollection AudioInputDescriptor::getAudioSessions(bool activeOnly) const
audio_source_t AudioInputDescriptor::getHighestPrioritySource(bool activeOnly) const
{
    if (activeOnly) {
        return mSessions.getActiveSessions();
    } else {
        return mSessions;
    audio_source_t source = AUDIO_SOURCE_DEFAULT;
    int32_t priority = -1;

    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();
        }

size_t AudioInputDescriptor::getAudioSessionCount(bool activeOnly) const
{
    if (activeOnly) {
        return mSessions.getActiveSessionCount();
    } else {
        return mSessions.size();
    }
    return source;
}

status_t AudioInputDescriptor::addAudioSession(audio_session_t session,
                         const sp<AudioSession>& audioSession) {
    return mSessions.addSession(session, audioSession);
bool AudioInputDescriptor::isSoundTrigger() const {
    // 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;
    }

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 @@ audio_patch_handle_t AudioInputDescriptor::getPatchHandle() const
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::open(const audio_config_t *config,

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 @@ void AudioInputDescriptor::close()
        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::close()
    }
}

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 @@ void AudioInputDescriptor::changeRefCount(audio_session_t session, int delta)
        }
    }

    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);
    }

    audioSession->changeActiveCount(delta);
    client->setActive(active);

    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,
@@ -385,8 +355,6 @@ status_t AudioInputDescriptor::dump(int fd)

    write(fd, result.string(), result.size());

    mSessions.dump(fd, 1);

    size_t index = 0;
    result = " AudioRecord clients:\n";
    for (const auto& client: mClients) {
Loading