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

Commit 68631eba authored by Andy Hung's avatar Andy Hung
Browse files

AudioFlinger: Create PatchPanel callback

Test: atest AudioTrackTest AudioRecordTest
Test: Camera YouTube
Bug: 291319167
Merged-In: I3b851a1b1b50edd76305957c8b91521e0cb1d23d
Change-Id: I3b851a1b1b50edd76305957c8b91521e0cb1d23d
parent ab9c06ff
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -412,6 +412,7 @@ void AudioFlinger::onFirstRef()
        mAAudioHwBurstMinMicros = getAAudioHardwareBurstMinUsecFromSystemProperty();
        mAAudioHwBurstMinMicros = getAAudioHardwareBurstMinUsecFromSystemProperty();
    }
    }


    mPatchPanel = IAfPatchPanel::create(sp<IAfPatchPanelCallback>::fromExisting(this));
    mMelReporter = sp<MelReporter>::make(sp<IAfMelReporterCallback>::fromExisting(this));
    mMelReporter = sp<MelReporter>::make(sp<IAfMelReporterCallback>::fromExisting(this));
}
}


+40 −34
Original line number Original line Diff line number Diff line
@@ -166,10 +166,10 @@ class AudioFlinger
    , public IAfClientCallback
    , public IAfClientCallback
    , public IAfDeviceEffectManagerCallback
    , public IAfDeviceEffectManagerCallback
    , public IAfMelReporterCallback
    , public IAfMelReporterCallback
    , public IAfPatchPanelCallback
{
{
    friend class sp<AudioFlinger>;
    friend class sp<AudioFlinger>;
    // TODO(b/291319167) Create interface and remove friends.
    // TODO(b/291319167) Create interface and remove friends.
    friend class PatchPanel;
    // TODO(b/291012167) replace the Thread friends with an interface.
    // TODO(b/291012167) replace the Thread friends with an interface.
    friend class DirectOutputThread;
    friend class DirectOutputThread;
    friend class MixerThread;
    friend class MixerThread;
@@ -374,7 +374,7 @@ public:
    // ---- begin IAfDeviceEffectManagerCallback interface
    // ---- begin IAfDeviceEffectManagerCallback interface


    bool isAudioPolicyReady() const final { return mAudioPolicyReady.load(); }
    bool isAudioPolicyReady() const final { return mAudioPolicyReady.load(); }
    // below also used by IAfMelReporterCallback
    // below also used by IAfMelReporterCallback, IAfPatchPanelCallback
    const sp<PatchCommandThread>& getPatchCommandThread() final { return mPatchCommandThread; }
    const sp<PatchCommandThread>& getPatchCommandThread() final { return mPatchCommandThread; }
    status_t addEffectToHal(
    status_t addEffectToHal(
            const struct audio_port_config* device, const sp<EffectHalInterface>& effect) final;
            const struct audio_port_config* device, const sp<EffectHalInterface>& effect) final;
@@ -390,6 +390,41 @@ public:


    // ---- end of IAfMelReporterCallback interface
    // ---- end of IAfMelReporterCallback interface


    // ---- begin IAfPatchPanelCallback interface

    void closeThreadInternal_l(const sp<IAfPlaybackThread>& thread) final;
    void closeThreadInternal_l(const sp<IAfRecordThread>& thread) final;
    // return thread associated with primary hardware device, or NULL
    IAfPlaybackThread* primaryPlaybackThread_l() const final;
    IAfPlaybackThread* checkPlaybackThread_l(audio_io_handle_t output) const final;
    IAfRecordThread* checkRecordThread_l(audio_io_handle_t input) const final;
    IAfMmapThread* checkMmapThread_l(audio_io_handle_t io) const final;
    void lock() const final ACQUIRE(mLock) { mLock.lock(); }
    void unlock() const final RELEASE(mLock) { mLock.unlock(); }
    sp<IAfThreadBase> openInput_l(audio_module_handle_t module,
            audio_io_handle_t* input,
            audio_config_t* config,
            audio_devices_t device,
            const char* address,
            audio_source_t source,
            audio_input_flags_t flags,
            audio_devices_t outputDevice,
            const String8& outputDeviceAddress) final;
    sp<IAfThreadBase> openOutput_l(audio_module_handle_t module,
            audio_io_handle_t* output,
            audio_config_t* halConfig,
            audio_config_base_t* mixerConfig,
            audio_devices_t deviceType,
            const String8& address,
            audio_output_flags_t flags) final;
    const DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*>&
            getAudioHwDevs_l() const final { return mAudioHwDevs; }
    void updateDownStreamPatches_l(const struct audio_patch* patch,
            const std::set<audio_io_handle_t>& streams) final;
    void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices) final;

    // ---- end of IAfPatchPanelCallback interface

    /* List available audio ports and their attributes */
    /* List available audio ports and their attributes */
    status_t listAudioPorts(unsigned int* num_ports, struct audio_port* ports) const;
    status_t listAudioPorts(unsigned int* num_ports, struct audio_port* ports) const;


@@ -411,9 +446,6 @@ public:
        const sp<os::ExternalVibration>& externalVibration);
        const sp<os::ExternalVibration>& externalVibration);
    static void onExternalVibrationStop(const sp<os::ExternalVibration>& externalVibration);
    static void onExternalVibrationStop(const sp<os::ExternalVibration>& externalVibration);


    void updateDownStreamPatches_l(const struct audio_patch *patch,
                                   const std::set<audio_io_handle_t>& streams);

    std::optional<media::AudioVibratorInfo> getDefaultVibratorInfo_l();
    std::optional<media::AudioVibratorInfo> getDefaultVibratorInfo_l();


private:
private:
@@ -453,9 +485,6 @@ public:


    bool        btNrecIsOff() const { return mBtNrecIsOff.load(); }
    bool        btNrecIsOff() const { return mBtNrecIsOff.load(); }


    void             lock() ACQUIRE(mLock) { mLock.lock(); }
    void             unlock() RELEASE(mLock) { mLock.unlock(); }

private:
private:


               audio_mode_t getMode() const { return mMode; }
               audio_mode_t getMode() const { return mMode; }
@@ -627,29 +656,11 @@ private:
    }
    }


    IAfThreadBase* checkThread_l(audio_io_handle_t ioHandle) const;
    IAfThreadBase* checkThread_l(audio_io_handle_t ioHandle) const;
    IAfPlaybackThread* checkPlaybackThread_l(audio_io_handle_t output) const;
    IAfPlaybackThread* checkMixerThread_l(audio_io_handle_t output) const;
    IAfPlaybackThread* checkMixerThread_l(audio_io_handle_t output) const;
    IAfRecordThread* checkRecordThread_l(audio_io_handle_t input) const;

    IAfMmapThread* checkMmapThread_l(audio_io_handle_t io) const;
              sp<VolumeInterface> getVolumeInterface_l(audio_io_handle_t output) const;
              sp<VolumeInterface> getVolumeInterface_l(audio_io_handle_t output) const;
              std::vector<sp<VolumeInterface>> getAllVolumeInterfaces_l() const;
              std::vector<sp<VolumeInterface>> getAllVolumeInterfaces_l() const;


    sp<IAfThreadBase> openInput_l(audio_module_handle_t module,
                                           audio_io_handle_t *input,
                                           audio_config_t *config,
                                           audio_devices_t device,
                                           const char* address,
                                           audio_source_t source,
                                           audio_input_flags_t flags,
                                           audio_devices_t outputDevice,
                                           const String8& outputDeviceAddress);
    sp<IAfThreadBase> openOutput_l(audio_module_handle_t module,
                                          audio_io_handle_t *output,
                                          audio_config_t *halConfig,
                                          audio_config_base_t *mixerConfig,
                                          audio_devices_t deviceType,
                                          const String8& address,
                                          audio_output_flags_t flags);


    void closeOutputFinish(const sp<IAfPlaybackThread>& thread);
    void closeOutputFinish(const sp<IAfPlaybackThread>& thread);
    void closeInputFinish(const sp<IAfRecordThread>& thread);
    void closeInputFinish(const sp<IAfRecordThread>& thread);
@@ -674,14 +685,13 @@ private:
              //       Thus it may fail by returning an ID of the wrong sign,
              //       Thus it may fail by returning an ID of the wrong sign,
              //       or by returning a non-unique ID.
              //       or by returning a non-unique ID.
              // This is the internal API.  For the binder API see newAudioUniqueId().
              // This is the internal API.  For the binder API see newAudioUniqueId().
    // used by IAfDeviceEffectManagerCallback
    // used by IAfDeviceEffectManagerCallback, IAfPatchPanelCallback
    audio_unique_id_t nextUniqueId(audio_unique_id_use_t use) final;
    audio_unique_id_t nextUniqueId(audio_unique_id_use_t use) final;


              status_t moveEffectChain_l(audio_session_t sessionId,
              status_t moveEffectChain_l(audio_session_t sessionId,
            IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread);
            IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread);


              // return thread associated with primary hardware device, or NULL
              // return thread associated with primary hardware device, or NULL
              IAfPlaybackThread* primaryPlaybackThread_l() const;
              DeviceTypeSet primaryOutputDevice_l() const;
              DeviceTypeSet primaryOutputDevice_l() const;


              // return the playback thread with smallest HAL buffer size, and prefer fast
              // return the playback thread with smallest HAL buffer size, and prefer fast
@@ -725,7 +735,6 @@ private:
                std::vector< sp<IAfEffectModule> > purgeStaleEffects_l();
                std::vector< sp<IAfEffectModule> > purgeStaleEffects_l();


                void broadcastParametersToRecordThreads_l(const String8& keyValuePairs);
                void broadcastParametersToRecordThreads_l(const String8& keyValuePairs);
                void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices);
                void forwardParametersToDownstreamPatches_l(
                void forwardParametersToDownstreamPatches_l(
                        audio_io_handle_t upStream, const String8& keyValuePairs,
                        audio_io_handle_t upStream, const String8& keyValuePairs,
            const std::function<bool(const sp<IAfPlaybackThread>&)>& useThread = nullptr);
            const std::function<bool(const sp<IAfPlaybackThread>&)>& useThread = nullptr);
@@ -843,9 +852,7 @@ private:


    // for use from destructor
    // for use from destructor
    status_t    closeOutput_nonvirtual(audio_io_handle_t output);
    status_t    closeOutput_nonvirtual(audio_io_handle_t output);
    void closeThreadInternal_l(const sp<IAfPlaybackThread>& thread);
    status_t    closeInput_nonvirtual(audio_io_handle_t input);
    status_t    closeInput_nonvirtual(audio_io_handle_t input);
    void closeThreadInternal_l(const sp<IAfRecordThread>& thread);
    void setAudioHwSyncForSession_l(IAfPlaybackThread* thread, audio_session_t sessionId);
    void setAudioHwSyncForSession_l(IAfPlaybackThread* thread, audio_session_t sessionId);


    status_t    checkStreamType(audio_stream_type_t stream) const;
    status_t    checkStreamType(audio_stream_type_t stream) const;
@@ -872,8 +879,7 @@ private:


    nsecs_t mGlobalEffectEnableTime;  // when a global effect was last enabled
    nsecs_t mGlobalEffectEnableTime;  // when a global effect was last enabled


    // protected by mLock
    /* const */ sp<IAfPatchPanel> mPatchPanel;
    const sp<IAfPatchPanel> mPatchPanel = IAfPatchPanel::create(this);


public:
public:
    // TODO(b/291319167) access by getter.
    // TODO(b/291319167) access by getter.
+38 −1
Original line number Original line Diff line number Diff line
@@ -18,12 +18,14 @@


namespace android {
namespace android {


class IAfMmapThread;
class IAfPatchPanel;
class IAfPatchPanel;
class IAfPatchRecord;
class IAfPatchRecord;
class IAfPatchTrack;
class IAfPatchTrack;
class IAfPlaybackThread;
class IAfPlaybackThread;
class IAfRecordThread;
class IAfRecordThread;
class IAfThreadBase;
class IAfThreadBase;
class PatchCommandThread;


class SoftwarePatch {
class SoftwarePatch {
public:
public:
@@ -51,9 +53,44 @@ private:
    const audio_io_handle_t mRecordThreadHandle;
    const audio_io_handle_t mRecordThreadHandle;
};
};


class IAfPatchPanelCallback : public virtual RefBase {
public:
    virtual void closeThreadInternal_l(const sp<IAfPlaybackThread>& thread) = 0;
    virtual void closeThreadInternal_l(const sp<IAfRecordThread>& thread) = 0;
    virtual IAfPlaybackThread* primaryPlaybackThread_l() const = 0;
    virtual IAfPlaybackThread* checkPlaybackThread_l(audio_io_handle_t output) const = 0;
    virtual IAfRecordThread* checkRecordThread_l(audio_io_handle_t input) const = 0;
    virtual IAfMmapThread* checkMmapThread_l(audio_io_handle_t io) const = 0;
    virtual sp<IAfThreadBase> openInput_l(audio_module_handle_t module,
            audio_io_handle_t* input,
            audio_config_t* config,
            audio_devices_t device,
            const char* address,
            audio_source_t source,
            audio_input_flags_t flags,
            audio_devices_t outputDevice,
            const String8& outputDeviceAddress) = 0;
    virtual sp<IAfThreadBase> openOutput_l(audio_module_handle_t module,
            audio_io_handle_t* output,
            audio_config_t* halConfig,
            audio_config_base_t* mixerConfig,
            audio_devices_t deviceType,
            const String8& address,
            audio_output_flags_t flags) = 0;
    virtual void lock() const = 0;
    virtual void unlock() const = 0;
    virtual const DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*>&
            getAudioHwDevs_l() const = 0;
    virtual audio_unique_id_t nextUniqueId(audio_unique_id_use_t use) = 0;
    virtual const sp<PatchCommandThread>& getPatchCommandThread() = 0;
    virtual void updateDownStreamPatches_l(
            const struct audio_patch* patch, const std::set<audio_io_handle_t>& streams) = 0;
    virtual void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices) = 0;
};

class IAfPatchPanel : public virtual RefBase {
class IAfPatchPanel : public virtual RefBase {
public:
public:
    static sp<IAfPatchPanel> create(AudioFlinger* audioFlinger);
    static sp<IAfPatchPanel> create(const sp<IAfPatchPanelCallback>& afPatchPanelCallback);


    // Extraction of inner Endpoint and Patch classes would require interfaces
    // Extraction of inner Endpoint and Patch classes would require interfaces
    // (in the Endpoint case a templated interface) but that seems
    // (in the Endpoint case a templated interface) but that seems
+39 −36
Original line number Original line Diff line number Diff line
@@ -96,8 +96,8 @@ status_t AudioFlinger::listAudioPatches(
}
}


/* static */
/* static */
sp<IAfPatchPanel> IAfPatchPanel::create(AudioFlinger* audioFlinger) {
sp<IAfPatchPanel> IAfPatchPanel::create(const sp<IAfPatchPanelCallback>& afPatchPanelCallback) {
    return sp<PatchPanel>::make(audioFlinger);
    return sp<PatchPanel>::make(afPatchPanelCallback);
}
}


status_t SoftwarePatch::getLatencyMs_l(double* latencyMs) const {
status_t SoftwarePatch::getLatencyMs_l(double* latencyMs) const {
@@ -119,10 +119,10 @@ void PatchPanel::closeThreadInternal_l(const sp<IAfThreadBase>& thread) const
{
{
    if (const auto recordThread = thread->asIAfRecordThread();
    if (const auto recordThread = thread->asIAfRecordThread();
            recordThread) {
            recordThread) {
        mAudioFlinger.closeThreadInternal_l(recordThread);
        mAfPatchPanelCallback->closeThreadInternal_l(recordThread);
    } else if (const auto playbackThread = thread->asIAfPlaybackThread();
    } else if (const auto playbackThread = thread->asIAfPlaybackThread();
            playbackThread) {
            playbackThread) {
        mAudioFlinger.closeThreadInternal_l(playbackThread);
        mAfPatchPanelCallback->closeThreadInternal_l(playbackThread);
    } else {
    } else {
        LOG_ALWAYS_FATAL("%s: Endpoints only accept IAfPlayback and IAfRecord threads, "
        LOG_ALWAYS_FATAL("%s: Endpoints only accept IAfPlayback and IAfRecord threads, "
                "invalid thread, id: %d  type: %d",
                "invalid thread, id: %d  type: %d",
@@ -275,8 +275,8 @@ status_t PatchPanel::createAudioPatch(const struct audio_patch* patch,
                        status = INVALID_OPERATION;
                        status = INVALID_OPERATION;
                        goto exit;
                        goto exit;
                    }
                    }
                    const sp<IAfThreadBase> thread =
                    const sp<IAfThreadBase> thread = mAfPatchPanelCallback->checkPlaybackThread_l(
                            mAudioFlinger.checkPlaybackThread_l(patch->sources[1].ext.mix.handle);
                            patch->sources[1].ext.mix.handle);
                    if (thread == 0) {
                    if (thread == 0) {
                        ALOGW("%s() cannot get playback thread", __func__);
                        ALOGW("%s() cannot get playback thread", __func__);
                        status = INVALID_OPERATION;
                        status = INVALID_OPERATION;
@@ -302,7 +302,7 @@ status_t PatchPanel::createAudioPatch(const struct audio_patch* patch,
                    if (patch->sinks[0].config_mask & AUDIO_PORT_CONFIG_FLAGS) {
                    if (patch->sinks[0].config_mask & AUDIO_PORT_CONFIG_FLAGS) {
                        flags = patch->sinks[0].flags.output;
                        flags = patch->sinks[0].flags.output;
                    }
                    }
                    const sp<IAfThreadBase> thread = mAudioFlinger.openOutput_l(
                    const sp<IAfThreadBase> thread = mAfPatchPanelCallback->openOutput_l(
                                                            patch->sinks[0].ext.device.hw_module,
                                                            patch->sinks[0].ext.device.hw_module,
                                                            &output,
                                                            &output,
                                                            &config,
                                                            &config,
@@ -310,7 +310,7 @@ status_t PatchPanel::createAudioPatch(const struct audio_patch* patch,
                                                            outputDevice,
                                                            outputDevice,
                                                            outputDeviceAddress,
                                                            outputDeviceAddress,
                                                            flags);
                                                            flags);
                    ALOGV("mAudioFlinger.openOutput_l() returned %p", thread.get());
                    ALOGV("mAfPatchPanelCallback->openOutput_l() returned %p", thread.get());
                    if (thread == 0) {
                    if (thread == 0) {
                        status = NO_MEMORY;
                        status = NO_MEMORY;
                        goto exit;
                        goto exit;
@@ -349,7 +349,7 @@ status_t PatchPanel::createAudioPatch(const struct audio_patch* patch,
                                == AUDIO_STREAM_VOICE_CALL) {
                                == AUDIO_STREAM_VOICE_CALL) {
                    source = AUDIO_SOURCE_VOICE_COMMUNICATION;
                    source = AUDIO_SOURCE_VOICE_COMMUNICATION;
                }
                }
                const sp<IAfThreadBase> thread = mAudioFlinger.openInput_l(srcModule,
                const sp<IAfThreadBase> thread = mAfPatchPanelCallback->openInput_l(srcModule,
                                                                    &input,
                                                                    &input,
                                                                    &config,
                                                                    &config,
                                                                    device,
                                                                    device,
@@ -358,7 +358,7 @@ status_t PatchPanel::createAudioPatch(const struct audio_patch* patch,
                                                                    flags,
                                                                    flags,
                                                                    outputDevice,
                                                                    outputDevice,
                                                                    outputDeviceAddress);
                                                                    outputDeviceAddress);
                ALOGV("mAudioFlinger.openInput_l() returned %p inChannelMask %08x",
                ALOGV("mAfPatchPanelCallback->openInput_l() returned %p inChannelMask %08x",
                      thread.get(), config.channel_mask);
                      thread.get(), config.channel_mask);
                if (thread == 0) {
                if (thread == 0) {
                    status = NO_MEMORY;
                    status = NO_MEMORY;
@@ -374,10 +374,11 @@ status_t PatchPanel::createAudioPatch(const struct audio_patch* patch,
                }
                }
            } else {
            } else {
                if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) {
                if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) {
                    sp<IAfThreadBase> thread = mAudioFlinger.checkRecordThread_l(
                    sp<IAfThreadBase> thread = mAfPatchPanelCallback->checkRecordThread_l(
                                                              patch->sinks[0].ext.mix.handle);
                                                              patch->sinks[0].ext.mix.handle);
                    if (thread == 0) {
                    if (thread == 0) {
                        thread = mAudioFlinger.checkMmapThread_l(patch->sinks[0].ext.mix.handle);
                        thread = mAfPatchPanelCallback->checkMmapThread_l(
                                patch->sinks[0].ext.mix.handle);
                        if (thread == 0) {
                        if (thread == 0) {
                            ALOGW("%s() bad capture I/O handle %d",
                            ALOGW("%s() bad capture I/O handle %d",
                                    __func__, patch->sinks[0].ext.mix.handle);
                                    __func__, patch->sinks[0].ext.mix.handle);
@@ -385,9 +386,9 @@ status_t PatchPanel::createAudioPatch(const struct audio_patch* patch,
                            goto exit;
                            goto exit;
                        }
                        }
                    }
                    }
                    mAudioFlinger.unlock();
                    mAfPatchPanelCallback->unlock();
                    status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
                    status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
                    mAudioFlinger.lock();
                    mAfPatchPanelCallback->lock();
                    if (status == NO_ERROR) {
                    if (status == NO_ERROR) {
                        newPatch.setThread(thread);
                        newPatch.setThread(thread);
                    }
                    }
@@ -411,7 +412,7 @@ status_t PatchPanel::createAudioPatch(const struct audio_patch* patch,
        } break;
        } break;
        case AUDIO_PORT_TYPE_MIX: {
        case AUDIO_PORT_TYPE_MIX: {
            audio_module_handle_t srcModule =  patch->sources[0].ext.mix.hw_module;
            audio_module_handle_t srcModule =  patch->sources[0].ext.mix.hw_module;
            ssize_t index = mAudioFlinger.mAudioHwDevs.indexOfKey(srcModule);
            ssize_t index = mAfPatchPanelCallback->getAudioHwDevs_l().indexOfKey(srcModule);
            if (index < 0) {
            if (index < 0) {
                ALOGW("%s() bad src hw module %d", __func__, srcModule);
                ALOGW("%s() bad src hw module %d", __func__, srcModule);
                status = BAD_VALUE;
                status = BAD_VALUE;
@@ -437,10 +438,11 @@ status_t PatchPanel::createAudioPatch(const struct audio_patch* patch,
                device->applyAudioPortConfig(&patch->sinks[i]);
                device->applyAudioPortConfig(&patch->sinks[i]);
                devices.push_back(device);
                devices.push_back(device);
            }
            }
            sp<IAfThreadBase> thread =
            sp<IAfThreadBase> thread = mAfPatchPanelCallback->checkPlaybackThread_l(
                            mAudioFlinger.checkPlaybackThread_l(patch->sources[0].ext.mix.handle);
                    patch->sources[0].ext.mix.handle);
            if (thread == 0) {
            if (thread == 0) {
                thread = mAudioFlinger.checkMmapThread_l(patch->sources[0].ext.mix.handle);
                thread = mAfPatchPanelCallback->checkMmapThread_l(
                        patch->sources[0].ext.mix.handle);
                if (thread == 0) {
                if (thread == 0) {
                    ALOGW("%s() bad playback I/O handle %d",
                    ALOGW("%s() bad playback I/O handle %d",
                            __func__, patch->sources[0].ext.mix.handle);
                            __func__, patch->sources[0].ext.mix.handle);
@@ -448,13 +450,13 @@ status_t PatchPanel::createAudioPatch(const struct audio_patch* patch,
                    goto exit;
                    goto exit;
                }
                }
            }
            }
            if (thread == mAudioFlinger.primaryPlaybackThread_l()) {
            if (thread == mAfPatchPanelCallback->primaryPlaybackThread_l()) {
                mAudioFlinger.updateOutDevicesForRecordThreads_l(devices);
                mAfPatchPanelCallback->updateOutDevicesForRecordThreads_l(devices);
            }
            }


            mAudioFlinger.unlock();
            mAfPatchPanelCallback->unlock();
            status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
            status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
            mAudioFlinger.lock();
            mAfPatchPanelCallback->lock();
            if (status == NO_ERROR) {
            if (status == NO_ERROR) {
                newPatch.setThread(thread);
                newPatch.setThread(thread);
            }
            }
@@ -479,9 +481,10 @@ status_t PatchPanel::createAudioPatch(const struct audio_patch* patch,
exit:
exit:
    ALOGV("%s() status %d", __func__, status);
    ALOGV("%s() status %d", __func__, status);
    if (status == NO_ERROR) {
    if (status == NO_ERROR) {
        *handle = (audio_patch_handle_t) mAudioFlinger.nextUniqueId(AUDIO_UNIQUE_ID_USE_PATCH);
        *handle = static_cast<audio_patch_handle_t>(
                mAfPatchPanelCallback->nextUniqueId(AUDIO_UNIQUE_ID_USE_PATCH));
        newPatch.mHalHandle = halHandle;
        newPatch.mHalHandle = halHandle;
        mAudioFlinger.mPatchCommandThread->createAudioPatch(*handle, newPatch);
        mAfPatchPanelCallback->getPatchCommandThread()->createAudioPatch(*handle, newPatch);
        if (insertedModule != AUDIO_MODULE_HANDLE_NONE) {
        if (insertedModule != AUDIO_MODULE_HANDLE_NONE) {
            addSoftwarePatchToInsertedModules(insertedModule, *handle, &newPatch.mAudioPatch);
            addSoftwarePatchToInsertedModules(insertedModule, *handle, &newPatch.mAudioPatch);
        }
        }
@@ -793,18 +796,18 @@ status_t PatchPanel::releaseAudioPatch(audio_patch_handle_t handle)


            if (patch.sinks[0].type == AUDIO_PORT_TYPE_MIX) {
            if (patch.sinks[0].type == AUDIO_PORT_TYPE_MIX) {
                audio_io_handle_t ioHandle = patch.sinks[0].ext.mix.handle;
                audio_io_handle_t ioHandle = patch.sinks[0].ext.mix.handle;
                sp<IAfThreadBase> thread = mAudioFlinger.checkRecordThread_l(ioHandle);
                sp<IAfThreadBase> thread = mAfPatchPanelCallback->checkRecordThread_l(ioHandle);
                if (thread == 0) {
                if (thread == 0) {
                    thread = mAudioFlinger.checkMmapThread_l(ioHandle);
                    thread = mAfPatchPanelCallback->checkMmapThread_l(ioHandle);
                    if (thread == 0) {
                    if (thread == 0) {
                        ALOGW("%s() bad capture I/O handle %d", __func__, ioHandle);
                        ALOGW("%s() bad capture I/O handle %d", __func__, ioHandle);
                        status = BAD_VALUE;
                        status = BAD_VALUE;
                        break;
                        break;
                    }
                    }
                }
                }
                mAudioFlinger.unlock();
                mAfPatchPanelCallback->unlock();
                status = thread->sendReleaseAudioPatchConfigEvent(removedPatch.mHalHandle);
                status = thread->sendReleaseAudioPatchConfigEvent(removedPatch.mHalHandle);
                mAudioFlinger.lock();
                mAfPatchPanelCallback->lock();
            } else {
            } else {
                status = hwDevice->releaseAudioPatch(removedPatch.mHalHandle);
                status = hwDevice->releaseAudioPatch(removedPatch.mHalHandle);
            }
            }
@@ -816,18 +819,18 @@ status_t PatchPanel::releaseAudioPatch(audio_patch_handle_t handle)
                break;
                break;
            }
            }
            audio_io_handle_t ioHandle = src.ext.mix.handle;
            audio_io_handle_t ioHandle = src.ext.mix.handle;
            sp<IAfThreadBase> thread = mAudioFlinger.checkPlaybackThread_l(ioHandle);
            sp<IAfThreadBase> thread = mAfPatchPanelCallback->checkPlaybackThread_l(ioHandle);
            if (thread == 0) {
            if (thread == 0) {
                thread = mAudioFlinger.checkMmapThread_l(ioHandle);
                thread = mAfPatchPanelCallback->checkMmapThread_l(ioHandle);
                if (thread == 0) {
                if (thread == 0) {
                    ALOGW("%s() bad playback I/O handle %d", __func__, ioHandle);
                    ALOGW("%s() bad playback I/O handle %d", __func__, ioHandle);
                    status = BAD_VALUE;
                    status = BAD_VALUE;
                    break;
                    break;
                }
                }
            }
            }
            mAudioFlinger.unlock();
            mAfPatchPanelCallback->unlock();
            status = thread->sendReleaseAudioPatchConfigEvent(removedPatch.mHalHandle);
            status = thread->sendReleaseAudioPatchConfigEvent(removedPatch.mHalHandle);
            mAudioFlinger.lock();
            mAfPatchPanelCallback->lock();
        } break;
        } break;
        default:
        default:
            status = BAD_VALUE;
            status = BAD_VALUE;
@@ -840,7 +843,7 @@ status_t PatchPanel::releaseAudioPatch(audio_patch_handle_t handle)
void PatchPanel::erasePatch(audio_patch_handle_t handle) {
void PatchPanel::erasePatch(audio_patch_handle_t handle) {
    mPatches.erase(handle);
    mPatches.erase(handle);
    removeSoftwarePatchFromInsertedModules(handle);
    removeSoftwarePatchFromInsertedModules(handle);
    mAudioFlinger.mPatchCommandThread->releaseAudioPatch(handle);
    mAfPatchPanelCallback->getPatchCommandThread()->releaseAudioPatch(handle);
}
}


/* List connected audio ports and they attributes */
/* List connected audio ports and they attributes */
@@ -904,12 +907,12 @@ void PatchPanel::notifyStreamClosed(audio_io_handle_t stream)
AudioHwDevice* PatchPanel::findAudioHwDeviceByModule(audio_module_handle_t module)
AudioHwDevice* PatchPanel::findAudioHwDeviceByModule(audio_module_handle_t module)
{
{
    if (module == AUDIO_MODULE_HANDLE_NONE) return nullptr;
    if (module == AUDIO_MODULE_HANDLE_NONE) return nullptr;
    ssize_t index = mAudioFlinger.mAudioHwDevs.indexOfKey(module);
    ssize_t index = mAfPatchPanelCallback->getAudioHwDevs_l().indexOfKey(module);
    if (index < 0) {
    if (index < 0) {
        ALOGW("%s() bad hw module %d", __func__, module);
        ALOGW("%s() bad hw module %d", __func__, module);
        return nullptr;
        return nullptr;
    }
    }
    return mAudioFlinger.mAudioHwDevs.valueAt(index);
    return mAfPatchPanelCallback->getAudioHwDevs_l().valueAt(index);
}
}


sp<DeviceHalInterface> PatchPanel::findHwDeviceByModule(audio_module_handle_t module)
sp<DeviceHalInterface> PatchPanel::findHwDeviceByModule(audio_module_handle_t module)
@@ -924,7 +927,7 @@ void PatchPanel::addSoftwarePatchToInsertedModules(
{
{
    mInsertedModules[module].sw_patches.insert(handle);
    mInsertedModules[module].sw_patches.insert(handle);
    if (!mInsertedModules[module].streams.empty()) {
    if (!mInsertedModules[module].streams.empty()) {
        mAudioFlinger.updateDownStreamPatches_l(patch, mInsertedModules[module].streams);
        mAfPatchPanelCallback->updateDownStreamPatches_l(patch, mInsertedModules[module].streams);
    }
    }
}
}


+3 −2
Original line number Original line Diff line number Diff line
@@ -21,7 +21,8 @@ namespace android {


class PatchPanel : public IAfPatchPanel {
class PatchPanel : public IAfPatchPanel {
public:
public:
    explicit PatchPanel(AudioFlinger* audioFlinger) : mAudioFlinger(*audioFlinger) {}
    explicit PatchPanel(const sp<IAfPatchPanelCallback>& afPatchPanelCallback)
        : mAfPatchPanelCallback(afPatchPanelCallback) {}


    /* List connected audio ports and their attributes */
    /* List connected audio ports and their attributes */
    status_t listAudioPorts(unsigned int *num_ports,
    status_t listAudioPorts(unsigned int *num_ports,
@@ -71,7 +72,7 @@ private:
    void removeSoftwarePatchFromInsertedModules(audio_patch_handle_t handle);
    void removeSoftwarePatchFromInsertedModules(audio_patch_handle_t handle);
    void erasePatch(audio_patch_handle_t handle);
    void erasePatch(audio_patch_handle_t handle);


    AudioFlinger &mAudioFlinger;
    const sp<IAfPatchPanelCallback> mAfPatchPanelCallback;
    std::map<audio_patch_handle_t, Patch> mPatches;
    std::map<audio_patch_handle_t, Patch> mPatches;


    // This map allows going from a thread to "downstream" software patches
    // This map allows going from a thread to "downstream" software patches