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

Commit d10b735c authored by Andy Hung's avatar Andy Hung Committed by Android (Google) Code Review
Browse files

Merge changes I7835e753,I5fe4d3e7

* changes:
  AudioPolicyManager: abort when client is removed while active
  AudioOutputDescriptor: improve refcount logging
parents 5e0659c8 39efb7a1
Loading
Loading
Loading
Loading
+3 −1
Original line number Original line Diff line number Diff line
@@ -73,6 +73,7 @@ endif # ifeq ($(USE_CONFIGURABLE_AUDIO_POLICY), 1)
LOCAL_C_INCLUDES += \
LOCAL_C_INCLUDES += \
    frameworks/av/services/audiopolicy/common/include \
    frameworks/av/services/audiopolicy/common/include \
    frameworks/av/services/audiopolicy/engine/interface \
    frameworks/av/services/audiopolicy/engine/interface \
    $(call include-path-for, audio-utils) \


LOCAL_STATIC_LIBRARIES := \
LOCAL_STATIC_LIBRARIES := \
    libaudiopolicycomponents
    libaudiopolicycomponents
@@ -109,7 +110,8 @@ LOCAL_STATIC_LIBRARIES := \


LOCAL_C_INCLUDES += \
LOCAL_C_INCLUDES += \
    frameworks/av/services/audiopolicy/common/include \
    frameworks/av/services/audiopolicy/common/include \
    frameworks/av/services/audiopolicy/engine/interface
    frameworks/av/services/audiopolicy/engine/interface \
    $(call include-path-for, audio-utils) \


LOCAL_CFLAGS := -Wall -Werror
LOCAL_CFLAGS := -Wall -Werror


+9 −11
Original line number Original line Diff line number Diff line
@@ -33,6 +33,7 @@ class AudioPolicyClientInterface;
// descriptor for audio inputs. Used to maintain current configuration of each opened audio input
// descriptor for audio inputs. Used to maintain current configuration of each opened audio input
// and keep track of the usage of this input.
// and keep track of the usage of this input.
class AudioInputDescriptor: public AudioPortConfig, public AudioIODescriptorInterface
class AudioInputDescriptor: public AudioPortConfig, public AudioIODescriptorInterface
    , public ClientMapHandler<RecordClientDescriptor>
{
{
public:
public:
    explicit AudioInputDescriptor(const sp<IOProfile>& profile,
    explicit AudioInputDescriptor(const sp<IOProfile>& profile,
@@ -42,9 +43,9 @@ public:


    status_t    dump(int fd);
    status_t    dump(int fd);


    audio_io_handle_t             mIoHandle;       // input handle
    audio_io_handle_t   mIoHandle = AUDIO_IO_HANDLE_NONE; // input handle
    audio_devices_t               mDevice;         // current device this input is routed to
    audio_devices_t     mDevice = AUDIO_DEVICE_NONE;  // current device this input is routed to
    AudioMix                      *mPolicyMix;     // non NULL when used by a dynamic policy
    AudioMix            *mPolicyMix = nullptr;        // non NULL when used by a dynamic policy
    const sp<IOProfile> mProfile;                     // I/O profile this output derives from
    const sp<IOProfile> mProfile;                     // I/O profile this output derives from


    virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
    virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
@@ -82,7 +83,6 @@ public:
    void stop();
    void stop();
    void close();
    void close();


    RecordClientMap& clientsMap() { return mClients; }
    RecordClientVector getClientsForSession(audio_session_t session);
    RecordClientVector getClientsForSession(audio_session_t session);
    RecordClientVector clientsList(bool activeOnly = false,
    RecordClientVector clientsList(bool activeOnly = false,
        audio_source_t source = AUDIO_SOURCE_DEFAULT, bool preferredDeviceOnly = false) const;
        audio_source_t source = AUDIO_SOURCE_DEFAULT, bool preferredDeviceOnly = false) const;
@@ -91,8 +91,8 @@ public:


    void updateClientRecordingConfiguration(int event, const sp<RecordClientDescriptor>& client);
    void updateClientRecordingConfiguration(int event, const sp<RecordClientDescriptor>& client);


    audio_patch_handle_t          mPatchHandle;
    audio_patch_handle_t mPatchHandle = AUDIO_PATCH_HANDLE_NONE;
    audio_port_handle_t           mId;
    audio_port_handle_t  mId = AUDIO_PORT_HANDLE_NONE;
    // Because a preemptible capture session can preempt another one, we end up in an endless loop
    // 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,
    // situation were each session is allowed to restart after being preempted,
    // thus preempting the other one which restarts and so on.
    // thus preempting the other one which restarts and so on.
@@ -100,10 +100,8 @@ public:
    // a particular input started and prevent preemption of this active input by this session.
    // a particular input started and prevent preemption of this active input by this session.
    // We also inherit sessions from the preempted input to avoid a 3 way preemption loop etc...
    // We also inherit sessions from the preempted input to avoid a 3 way preemption loop etc...
    SortedVector<audio_session_t> mPreemptedSessions;
    SortedVector<audio_session_t> mPreemptedSessions;
    AudioPolicyClientInterface *mClientInterface;
    AudioPolicyClientInterface * const mClientInterface;
    int32_t mGlobalActiveCount;  // non-client-specific activity ref count
    int32_t mGlobalActiveCount = 0;  // non-client-specific activity ref count

    RecordClientMap mClients;
};
};


class AudioInputCollection :
class AudioInputCollection :
+53 −13
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
#pragma once
#pragma once


#include <sys/types.h>
#include <sys/types.h>

#include <utils/Errors.h>
#include <utils/Errors.h>
#include <utils/Timers.h>
#include <utils/Timers.h>
#include <utils/KeyedVector.h>
#include <utils/KeyedVector.h>
@@ -36,6 +37,7 @@ class DeviceDescriptor;
// descriptor for audio outputs. Used to maintain current configuration of each opened audio output
// descriptor for audio outputs. Used to maintain current configuration of each opened audio output
// and keep track of the usage of this output by each audio stream type.
// and keep track of the usage of this output by each audio stream type.
class AudioOutputDescriptor: public AudioPortConfig, public AudioIODescriptorInterface
class AudioOutputDescriptor: public AudioPortConfig, public AudioIODescriptorInterface
    , public ClientMapHandler<TrackClientDescriptor>
{
{
public:
public:
    AudioOutputDescriptor(const sp<AudioPort>& port,
    AudioOutputDescriptor(const sp<AudioPort>& port,
@@ -59,9 +61,21 @@ public:
                           audio_devices_t device,
                           audio_devices_t device,
                           uint32_t delayMs,
                           uint32_t delayMs,
                           bool force);
                           bool force);
    virtual void changeStreamActiveCount(audio_stream_type_t stream, int delta);

    /**
     * Changes the stream active count and mActiveClients only.
     * This does not change the client->active() state or the output descriptor's
     * global active count.
     */
    virtual void changeStreamActiveCount(const sp<TrackClientDescriptor>& client, int delta);
            uint32_t streamActiveCount(audio_stream_type_t stream) const
            uint32_t streamActiveCount(audio_stream_type_t stream) const
                            { return mActiveCount[stream]; }
                            { return mActiveCount[stream]; }

    /**
     * Changes the client->active() state and the output descriptor's global active count,
     * along with the stream active count and mActiveClients.
     * The client must be previously added by the base class addClient().
     */
            void setClientActive(const sp<TrackClientDescriptor>& client, bool active);
            void setClientActive(const sp<TrackClientDescriptor>& client, bool active);


    bool isActive(uint32_t inPastMs = 0) const;
    bool isActive(uint32_t inPastMs = 0) const;
@@ -81,26 +95,51 @@ public:
    audio_patch_handle_t getPatchHandle() const override;
    audio_patch_handle_t getPatchHandle() const override;
    void setPatchHandle(audio_patch_handle_t handle) override;
    void setPatchHandle(audio_patch_handle_t handle) override;


    TrackClientMap& clientsMap() { return mClients; }
    TrackClientVector clientsList(bool activeOnly = false,
    TrackClientVector clientsList(bool activeOnly = false,
        routing_strategy strategy = STRATEGY_NONE, bool preferredDeviceOnly = false) const;
        routing_strategy strategy = STRATEGY_NONE, bool preferredDeviceOnly = false) const;


    sp<AudioPort> mPort;
    // override ClientMapHandler to abort when removing a client when active.
    audio_devices_t mDevice;                   // current device this output is routed to
    void removeClient(audio_port_handle_t portId) override {
        auto client = getClient(portId);
        LOG_ALWAYS_FATAL_IF(client.get() == nullptr,
                "%s(%d): nonexistent client portId %d", __func__, mId, portId);
        // it is possible that when a client is removed, we could remove its
        // associated active count by calling changeStreamActiveCount(),
        // but that would be hiding a problem, so we log fatal instead.
        auto it2 = mActiveClients.find(client);
        LOG_ALWAYS_FATAL_IF(it2 != mActiveClients.end(),
                "%s(%d) removing client portId %d which is active (count %zu)",
                __func__, mId, portId, it2->second);
        ClientMapHandler<TrackClientDescriptor>::removeClient(portId);
    }

    using ActiveClientMap = std::map<sp<TrackClientDescriptor>, size_t /* count */>;
    // required for duplicating thread
    const ActiveClientMap& getActiveClients() const {
        return mActiveClients;
    }

    audio_devices_t mDevice = AUDIO_DEVICE_NONE; // current device this output is routed to
    nsecs_t mStopTime[AUDIO_STREAM_CNT];
    nsecs_t mStopTime[AUDIO_STREAM_CNT];
    float mCurVolume[AUDIO_STREAM_CNT];   // current stream volume in dB
    int mMuteCount[AUDIO_STREAM_CNT];            // mute request counter
    int mMuteCount[AUDIO_STREAM_CNT];            // mute request counter
    bool mStrategyMutedByDevice[NUM_STRATEGIES]; // strategies muted because of incompatible
    bool mStrategyMutedByDevice[NUM_STRATEGIES]; // strategies muted because of incompatible
                                        // device selection. See checkDeviceMuteStrategies()
                                        // device selection. See checkDeviceMuteStrategies()
    AudioPolicyClientInterface *mClientInterface;
    AudioMix *mPolicyMix = nullptr;              // non NULL when used by a dynamic policy
    AudioMix *mPolicyMix;             // non NULL when used by a dynamic policy


protected:
protected:
    const sp<AudioPort> mPort;
    AudioPolicyClientInterface * const mClientInterface;
    float mCurVolume[AUDIO_STREAM_CNT];   // current stream volume in dB
    uint32_t mActiveCount[AUDIO_STREAM_CNT]; // number of streams of each type active on this output
    uint32_t mActiveCount[AUDIO_STREAM_CNT]; // number of streams of each type active on this output
    uint32_t mGlobalActiveCount;  // non-client-specific active count
    uint32_t mGlobalActiveCount = 0;  // non-client-specific active count
    audio_patch_handle_t mPatchHandle;
    audio_patch_handle_t mPatchHandle = AUDIO_PATCH_HANDLE_NONE;
    audio_port_handle_t mId;
    audio_port_handle_t mId = AUDIO_PORT_HANDLE_NONE;
    TrackClientMap mClients;

    // The ActiveClientMap shows the clients that contribute to the streams counts
    // and may include upstream clients from a duplicating thread.
    // Compare with the ClientMap (mClients) which are external AudioTrack clients of the
    // output descriptor (and do not count internal PatchTracks).
    ActiveClientMap mActiveClients;
};
};


// Audio output driven by a software mixer in audio flinger.
// Audio output driven by a software mixer in audio flinger.
@@ -121,7 +160,8 @@ public:
    virtual bool isFixedVolume(audio_devices_t device);
    virtual bool isFixedVolume(audio_devices_t device);
    virtual sp<AudioOutputDescriptor> subOutput1() { return mOutput1; }
    virtual sp<AudioOutputDescriptor> subOutput1() { return mOutput1; }
    virtual sp<AudioOutputDescriptor> subOutput2() { return mOutput2; }
    virtual sp<AudioOutputDescriptor> subOutput2() { return mOutput2; }
    virtual void changeStreamActiveCount(audio_stream_type_t stream, int delta);
            void changeStreamActiveCount(
                    const sp<TrackClientDescriptor>& client, int delta) override;
    virtual bool setVolume(float volume,
    virtual bool setVolume(float volume,
                           audio_stream_type_t stream,
                           audio_stream_type_t stream,
                           audio_devices_t device,
                           audio_devices_t device,
+83 −2
Original line number Original line Diff line number Diff line
@@ -47,6 +47,7 @@ public:


    status_t dump(int fd, int spaces, int index);
    status_t dump(int fd, int spaces, int index);
    virtual status_t dump(String8& dst, int spaces, int index);
    virtual status_t dump(String8& dst, int spaces, int index);
    virtual std::string toShortString() const;


    audio_port_handle_t portId() const { return mPortId; }
    audio_port_handle_t portId() const { return mPortId; }
    uid_t uid() const { return mUid; }
    uid_t uid() const { return mUid; }
@@ -90,6 +91,7 @@ public:


    using ClientDescriptor::dump;
    using ClientDescriptor::dump;
    status_t dump(String8& dst, int spaces, int index) override;
    status_t dump(String8& dst, int spaces, int index) override;
    std::string toShortString() const override;


    audio_output_flags_t flags() const { return mFlags; }
    audio_output_flags_t flags() const { return mFlags; }
    audio_stream_type_t stream() const { return mStream; }
    audio_stream_type_t stream() const { return mStream; }
@@ -161,8 +163,87 @@ public:
};
};


typedef std::vector< sp<TrackClientDescriptor> > TrackClientVector;
typedef std::vector< sp<TrackClientDescriptor> > TrackClientVector;
typedef std::map< audio_port_handle_t, sp<TrackClientDescriptor> > TrackClientMap;
typedef std::vector< sp<RecordClientDescriptor> > RecordClientVector;
typedef std::vector< sp<RecordClientDescriptor> > RecordClientVector;
typedef std::map< audio_port_handle_t, sp<RecordClientDescriptor> > RecordClientMap;

// A Map that associates a portId with a client (type T)
// which is either TrackClientDescriptor or RecordClientDescriptor.

template<typename T>
class ClientMapHandler {
public:
    virtual ~ClientMapHandler() = default;

    // Track client management
    void addClient(const sp<T> &client) {
        const audio_port_handle_t portId = client->portId();
        LOG_ALWAYS_FATAL_IF(!mClients.emplace(portId, client).second,
                "%s(%d): attempting to add client that already exists", __func__, portId);
    }
    sp<T> getClient(audio_port_handle_t portId) const {
        auto it = mClients.find(portId);
        if (it == mClients.end()) return nullptr;
        return it->second;
    }
    virtual void removeClient(audio_port_handle_t portId) {
        LOG_ALWAYS_FATAL_IF(mClients.erase(portId) == 0,
                "%s(%d): client does not exist", __func__, portId);
    }
    size_t getClientCount() const {
        return mClients.size();
    }
    String8 dump() const {
        String8 result;
        size_t index = 0;
        for (const auto& client: getClientIterable()) {
            client->dump(result, 2, index++);
        }
        return result;
    }

    // helper types
    using ClientMap = std::map<audio_port_handle_t, sp<T>>;
    using ClientMapIterator = typename ClientMap::const_iterator;  // ClientMap is const qualified
    class ClientIterable {
    public:
        explicit ClientIterable(const ClientMapHandler<T> &ref) : mClientMapHandler(ref) { }

        class iterator {
        public:
            // traits
            using iterator_category = std::forward_iterator_tag;
            using value_type = sp<T>;
            using difference_type = ptrdiff_t;
            using pointer = const sp<T>*;    // Note: const
            using reference = const sp<T>&;  // Note: const

            // implementation
            explicit iterator(const ClientMapIterator &it) : mIt(it) { }
            iterator& operator++()    /* prefix */     { ++mIt; return *this; }
            reference operator* () const               { return mIt->second; }
            reference operator->() const               { return mIt->second; } // as if sp<>
            difference_type operator-(const iterator& rhs) {return mIt - rhs.mIt; }
            bool operator==(const iterator& rhs) const { return mIt == rhs.mIt; }
            bool operator!=(const iterator& rhs) const { return mIt != rhs.mIt; }
        private:
            ClientMapIterator mIt;
        };

        iterator begin() const { return iterator{mClientMapHandler.mClients.begin()}; }
        iterator end() const { return iterator{mClientMapHandler.mClients.end()}; }

    private:
        const ClientMapHandler<T>& mClientMapHandler; // iterating does not modify map.
    };

    // return an iterable object that can be used in a range-based-for to enumerate clients.
    // this iterable does not allow modification, it should be used as a temporary.
    ClientIterable getClientIterable() const {
        return ClientIterable{*this};
    }

private:
    // ClientMap maps a portId to a client descriptor (both uniquely identify each other).
    ClientMap mClients;
};


} // namespace android
} // namespace android
+39 −54
Original line number Original line Diff line number Diff line
@@ -29,10 +29,8 @@ namespace android {


AudioInputDescriptor::AudioInputDescriptor(const sp<IOProfile>& profile,
AudioInputDescriptor::AudioInputDescriptor(const sp<IOProfile>& profile,
                                           AudioPolicyClientInterface *clientInterface)
                                           AudioPolicyClientInterface *clientInterface)
    : mIoHandle(0),
    : mProfile(profile)
      mDevice(AUDIO_DEVICE_NONE), mPolicyMix(NULL),
    ,  mClientInterface(clientInterface)
      mProfile(profile), mPatchHandle(AUDIO_PATCH_HANDLE_NONE), mId(0),
      mClientInterface(clientInterface), mGlobalActiveCount(0)
{
{
    if (profile != NULL) {
    if (profile != NULL) {
        profile->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
        profile->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
@@ -115,12 +113,12 @@ void AudioInputDescriptor::clearPreemptedSessions()


bool AudioInputDescriptor::isSourceActive(audio_source_t source) const
bool AudioInputDescriptor::isSourceActive(audio_source_t source) const
{
{
    for (const auto &client : mClients) {
    for (const auto &client : getClientIterable()) {
        if (client.second->active() &&
        if (client->active() &&
            ((client.second->source() == source) ||
            ((client->source() == source) ||
                ((source == AUDIO_SOURCE_VOICE_RECOGNITION) &&
                ((source == AUDIO_SOURCE_VOICE_RECOGNITION) &&
                    (client.second->source() == AUDIO_SOURCE_HOTWORD) &&
                    (client->source() == AUDIO_SOURCE_HOTWORD) &&
                    client.second->isSoundTrigger()))) {
                    client->isSoundTrigger()))) {
            return true;
            return true;
        }
        }
    }
    }
@@ -132,14 +130,14 @@ audio_source_t AudioInputDescriptor::getHighestPrioritySource(bool activeOnly) c
    audio_source_t source = AUDIO_SOURCE_DEFAULT;
    audio_source_t source = AUDIO_SOURCE_DEFAULT;
    int32_t priority = -1;
    int32_t priority = -1;


    for (const auto &client : mClients) {
    for (const auto &client : getClientIterable()) {
        if (activeOnly && !client.second->active() ) {
        if (activeOnly && !client->active() ) {
            continue;
            continue;
        }
        }
        int32_t curPriority = source_priority(client.second->source());
        int32_t curPriority = source_priority(client->source());
        if (curPriority > priority) {
        if (curPriority > priority) {
            priority = curPriority;
            priority = curPriority;
            source = client.second->source();
            source = client->source();
        }
        }
    }
    }
    return source;
    return source;
@@ -148,10 +146,10 @@ audio_source_t AudioInputDescriptor::getHighestPrioritySource(bool activeOnly) c
bool AudioInputDescriptor::isSoundTrigger() const {
bool AudioInputDescriptor::isSoundTrigger() const {
    // sound trigger and non sound trigger clients are not mixed on a given input
    // sound trigger and non sound trigger clients are not mixed on a given input
    // so check only first client
    // so check only first client
    if (mClients.size() == 0) {
    if (getClientCount() == 0) {
        return false;
        return false;
    }
    }
    return mClients.cbegin()->second->isSoundTrigger();
    return getClientIterable().begin()->isSoundTrigger();
}
}


audio_patch_handle_t AudioInputDescriptor::getPatchHandle() const
audio_patch_handle_t AudioInputDescriptor::getPatchHandle() const
@@ -162,9 +160,9 @@ audio_patch_handle_t AudioInputDescriptor::getPatchHandle() const
void AudioInputDescriptor::setPatchHandle(audio_patch_handle_t handle)
void AudioInputDescriptor::setPatchHandle(audio_patch_handle_t handle)
{
{
    mPatchHandle = handle;
    mPatchHandle = handle;
    for (const auto &client : mClients) {
    for (const auto &client : getClientIterable()) {
        if (client.second->active()) {
        if (client->active()) {
            updateClientRecordingConfiguration(RECORD_CONFIG_EVENT_START, client.second);
            updateClientRecordingConfiguration(RECORD_CONFIG_EVENT_START, client);
        }
        }
    }
    }
}
}
@@ -265,8 +263,9 @@ void AudioInputDescriptor::close()


void AudioInputDescriptor::setClientActive(const sp<RecordClientDescriptor>& client, bool active)
void AudioInputDescriptor::setClientActive(const sp<RecordClientDescriptor>& client, bool active)
{
{
    if (mClients.find(client->portId()) == mClients.end()
    LOG_ALWAYS_FATAL_IF(getClient(client->portId()) == nullptr,
         || active == client->active()) {
        "%s(%d) does not exist on input descriptor", __func__, client->portId());
    if (active == client->active()) {
        return;
        return;
    }
    }


@@ -276,7 +275,8 @@ void AudioInputDescriptor::setClientActive(const sp<RecordClientDescriptor>& cli
        ALOGW("%s invalid deactivation with globalRefCount %d", __FUNCTION__, mGlobalActiveCount);
        ALOGW("%s invalid deactivation with globalRefCount %d", __FUNCTION__, mGlobalActiveCount);
        mGlobalActiveCount = 1;
        mGlobalActiveCount = 1;
    }
    }
    mGlobalActiveCount += active ? 1 : -1;
    const int delta = active ? 1 : -1;
    mGlobalActiveCount += delta;


    if ((oldGlobalActiveCount == 0) && (mGlobalActiveCount > 0)) {
    if ((oldGlobalActiveCount == 0) && (mGlobalActiveCount > 0)) {
        if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
        if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
@@ -314,9 +314,9 @@ RecordClientVector AudioInputDescriptor::getClientsForSession(
    audio_session_t session)
    audio_session_t session)
{
{
    RecordClientVector clients;
    RecordClientVector clients;
    for (const auto &client : mClients) {
    for (const auto &client : getClientIterable()) {
        if (client.second->session() == session) {
        if (client->session() == session) {
            clients.push_back(client.second);
            clients.push_back(client);
        }
        }
    }
    }
    return clients;
    return clients;
@@ -326,11 +326,11 @@ RecordClientVector AudioInputDescriptor::clientsList(bool activeOnly, audio_sour
                                                     bool preferredDeviceOnly) const
                                                     bool preferredDeviceOnly) const
{
{
    RecordClientVector clients;
    RecordClientVector clients;
    for (const auto &client : mClients) {
    for (const auto &client : getClientIterable()) {
        if ((!activeOnly || client.second->active())
        if ((!activeOnly || client->active())
            && (source == AUDIO_SOURCE_DEFAULT || source == client.second->source())
            && (source == AUDIO_SOURCE_DEFAULT || source == client->source())
            && (!preferredDeviceOnly || client.second->hasPreferredDevice())) {
            && (!preferredDeviceOnly || client->hasPreferredDevice())) {
            clients.push_back(client.second);
            clients.push_back(client);
        }
        }
    }
    }
    return clients;
    return clients;
@@ -338,28 +338,15 @@ RecordClientVector AudioInputDescriptor::clientsList(bool activeOnly, audio_sour


status_t AudioInputDescriptor::dump(int fd)
status_t AudioInputDescriptor::dump(int fd)
{
{
    const size_t SIZE = 256;
    char buffer[SIZE];
    String8 result;
    String8 result;


    snprintf(buffer, SIZE, " ID: %d\n", getId());
    result.appendFormat(" ID: %d\n", getId());
    result.append(buffer);
    result.appendFormat(" Sampling rate: %d\n", mSamplingRate);
    snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
    result.appendFormat(" Format: %d\n", mFormat);
    result.append(buffer);
    result.appendFormat(" Channels: %08x\n", mChannelMask);
    snprintf(buffer, SIZE, " Format: %d\n", mFormat);
    result.appendFormat(" Devices %08x\n", mDevice);
    result.append(buffer);
    result.append(" AudioRecord Clients:\n");
    snprintf(buffer, SIZE, " Channels: %08x\n", mChannelMask);
    result.append(ClientMapHandler<RecordClientDescriptor>::dump());
    result.append(buffer);
    snprintf(buffer, SIZE, " Devices %08x\n", mDevice);
    result.append(buffer);

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

    size_t index = 0;
    result = " AudioRecord clients:\n";
    for (const auto& client: mClients) {
        client.second->dump(result, 2, index++);
    }
    result.append("\n");
    result.append("\n");
    write(fd, result.string(), result.size());
    write(fd, result.string(), result.size());
    return NO_ERROR;
    return NO_ERROR;
@@ -427,12 +414,10 @@ sp<AudioInputDescriptor> AudioInputCollection::getInputForClient(audio_port_hand
{
{
    for (size_t i = 0; i < size(); i++) {
    for (size_t i = 0; i < size(); i++) {
        sp<AudioInputDescriptor> inputDesc = valueAt(i);
        sp<AudioInputDescriptor> inputDesc = valueAt(i);
        for (const auto& client : inputDesc->clientsMap()) {
        if (inputDesc->getClient(portId) != nullptr) {
            if (client.second->portId() == portId) {
            return inputDesc;
            return inputDesc;
        }
        }
    }
    }
    }
    return 0;
    return 0;
}
}


Loading