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

Commit 282ca695 authored by Eric Laurent's avatar Eric Laurent Committed by android-build-merger
Browse files

Fix various AAudio device selection issues

am: ad2e7b90

Change-Id: I3a76814efe2806e6f192d90807067dd27965913c
parents eafdc523 ad2e7b90
Loading
Loading
Loading
Loading
+55 −25
Original line number Diff line number Diff line
@@ -120,7 +120,7 @@ AudioRecord::~AudioRecord()
        }
        // No lock here: worst case we remove a NULL callback which will be a nop
        if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) {
            AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput);
            AudioSystem::removeAudioDeviceCallback(this, mInput);
        }
        IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this);
        mAudioRecord.clear();
@@ -499,19 +499,26 @@ audio_port_handle_t AudioRecord::getInputDevice() {
    return mSelectedDeviceId;
}

audio_port_handle_t AudioRecord::getRoutedDeviceId() {
    AutoMutex lock(mLock);
    if (mInput == AUDIO_IO_HANDLE_NONE) {
        return AUDIO_PORT_HANDLE_NONE;
// must be called with mLock held
void AudioRecord::updateRoutedDeviceId_l()
{
    // if the record is inactive, do not update actual device as the input stream maybe routed
    // from a device not relevant to this client because of other active use cases.
    if (!mActive) {
        return;
    }
    // if the input stream does not have an active audio patch, use either the device initially
    // selected by audio policy manager or the last routed device
    if (mInput != AUDIO_IO_HANDLE_NONE) {
        audio_port_handle_t deviceId = AudioSystem::getDeviceIdForIo(mInput);
    if (deviceId == AUDIO_PORT_HANDLE_NONE) {
        deviceId = mRoutedDeviceId;
    }
        if (deviceId != AUDIO_PORT_HANDLE_NONE) {
            mRoutedDeviceId = deviceId;
    return deviceId;
        }
     }
}

audio_port_handle_t AudioRecord::getRoutedDeviceId() {
    AutoMutex lock(mLock);
    updateRoutedDeviceId_l();
    return mRoutedDeviceId;
}

// -------------------------------------------------------------------------
@@ -537,9 +544,6 @@ status_t AudioRecord::openRecord_l(const Modulo<uint32_t> &epoch, const String16
        return NO_INIT;
    }

    if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) {
        AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput);
    }
    audio_io_handle_t input;

    // mFlags (not mOrigFlags) is modified depending on whether fast request is accepted.
@@ -744,6 +748,15 @@ status_t AudioRecord::openRecord_l(const Modulo<uint32_t> &epoch, const String16
    }
    mNotificationFramesAct = (uint32_t) notificationFrames;


    //mInput != input includes the case where mInput == AUDIO_IO_HANDLE_NONE for first creation
    if (mDeviceCallback != 0 && mInput != input) {
        if (mInput != AUDIO_IO_HANDLE_NONE) {
            AudioSystem::removeAudioDeviceCallback(this, mInput);
        }
        AudioSystem::addAudioDeviceCallback(this, input);
    }

    // We retain a copy of the I/O handle, but don't own the reference
    mInput = input;
    mRefreshRemaining = true;
@@ -763,10 +776,6 @@ status_t AudioRecord::openRecord_l(const Modulo<uint32_t> &epoch, const String16
    mDeathNotifier = new DeathNotifier(this);
    IInterface::asBinder(mAudioRecord)->linkToDeath(mDeathNotifier, this);

    if (mDeviceCallback != 0) {
        AudioSystem::addAudioDeviceCallback(mDeviceCallback, mInput);
    }

    return NO_ERROR;

    // End of retry loop.
@@ -1238,7 +1247,7 @@ status_t AudioRecord::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCa
        return BAD_VALUE;
    }
    AutoMutex lock(mLock);
    if (mDeviceCallback == callback) {
    if (mDeviceCallback.unsafe_get() == callback.get()) {
        ALOGW("%s adding same callback!", __FUNCTION__);
        return INVALID_OPERATION;
    }
@@ -1246,9 +1255,9 @@ status_t AudioRecord::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCa
    if (mInput != AUDIO_IO_HANDLE_NONE) {
        if (mDeviceCallback != 0) {
            ALOGW("%s callback already present!", __FUNCTION__);
            AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput);
            AudioSystem::removeAudioDeviceCallback(this, mInput);
        }
        status = AudioSystem::addAudioDeviceCallback(callback, mInput);
        status = AudioSystem::addAudioDeviceCallback(this, mInput);
    }
    mDeviceCallback = callback;
    return status;
@@ -1262,17 +1271,38 @@ status_t AudioRecord::removeAudioDeviceCallback(
        return BAD_VALUE;
    }
    AutoMutex lock(mLock);
    if (mDeviceCallback != callback) {
    if (mDeviceCallback.unsafe_get() != callback.get()) {
        ALOGW("%s removing different callback!", __FUNCTION__);
        return INVALID_OPERATION;
    }
    mDeviceCallback.clear();
    if (mInput != AUDIO_IO_HANDLE_NONE) {
        AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput);
        AudioSystem::removeAudioDeviceCallback(this, mInput);
    }
    mDeviceCallback = 0;
    return NO_ERROR;
}

void AudioRecord::onAudioDeviceUpdate(audio_io_handle_t audioIo,
                                 audio_port_handle_t deviceId)
{
    sp<AudioSystem::AudioDeviceCallback> callback;
    {
        AutoMutex lock(mLock);
        if (audioIo != mInput) {
            return;
        }
        callback = mDeviceCallback.promote();
        // only update device if the record is active as route changes due to other use cases are
        // irrelevant for this client
        if (mActive) {
            mRoutedDeviceId = deviceId;
        }
    }
    if (callback.get() != nullptr) {
        callback->onAudioDeviceUpdate(mInput, mRoutedDeviceId);
    }
}

// =========================================================================

void AudioRecord::DeathNotifier::binderDied(const wp<IBinder>& who __unused)
+39 −17
Original line number Diff line number Diff line
@@ -493,14 +493,16 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even
    if (ioDesc == 0 || ioDesc->mIoHandle == AUDIO_IO_HANDLE_NONE) return;

    audio_port_handle_t deviceId = AUDIO_PORT_HANDLE_NONE;
    Vector < sp<AudioDeviceCallback> > callbacks;
    Vector < wp<AudioDeviceCallback> > callbacks;

    {
        Mutex::Autolock _l(mLock);

        switch (event) {
        case AUDIO_OUTPUT_OPENED:
        case AUDIO_INPUT_OPENED: {
        case AUDIO_OUTPUT_REGISTERED:
        case AUDIO_INPUT_OPENED:
        case AUDIO_INPUT_REGISTERED: {
            sp<AudioIoDescriptor> oldDesc = getIoDescriptor_l(ioDesc->mIoHandle);
            if (oldDesc == 0) {
                mIoDescriptors.add(ioDesc->mIoHandle, ioDesc);
@@ -511,13 +513,19 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even

            if (ioDesc->getDeviceId() != AUDIO_PORT_HANDLE_NONE) {
                deviceId = ioDesc->getDeviceId();
                if (event == AUDIO_OUTPUT_OPENED || event == AUDIO_INPUT_OPENED) {
                    ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(ioDesc->mIoHandle);
                    if (ioIndex >= 0) {
                        callbacks = mAudioDeviceCallbacks.valueAt(ioIndex);
                    }
                }
            ALOGV("ioConfigChanged() new %s opened %d samplingRate %u, format %#x channel mask %#x "
                    "frameCount %zu deviceId %d", event == AUDIO_OUTPUT_OPENED ? "output" : "input",
            }
            ALOGV("ioConfigChanged() new %s %s %d samplingRate %u, format %#x channel mask %#x "
                    "frameCount %zu deviceId %d",
                    event == AUDIO_OUTPUT_OPENED || event == AUDIO_OUTPUT_REGISTERED ?
                            "output" : "input",
                            event == AUDIO_OUTPUT_OPENED || event == AUDIO_INPUT_OPENED ?
                            "opened" : "registered",
                    ioDesc->mIoHandle, ioDesc->mSamplingRate, ioDesc->mFormat, ioDesc->mChannelMask,
                    ioDesc->mFrameCount, ioDesc->getDeviceId());
            } break;
@@ -563,9 +571,23 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even
        } break;
        }
    }
    bool callbackRemoved = false;
    // callbacks.size() != 0 =>  ioDesc->mIoHandle and deviceId are valid
    for (size_t i = 0; i < callbacks.size(); i++) {
        callbacks[i]->onAudioDeviceUpdate(ioDesc->mIoHandle, deviceId);
    for (size_t i = 0; i < callbacks.size(); ) {
        sp<AudioDeviceCallback> callback = callbacks[i].promote();
        if (callback.get() != nullptr) {
            callback->onAudioDeviceUpdate(ioDesc->mIoHandle, deviceId);
            i++;
        } else {
            callbacks.removeAt(i);
            callbackRemoved = true;
        }
    }
    // clean up callback list while we are here if some clients have disappeared without
    // unregistering their callback
    if (callbackRemoved) {
        Mutex::Autolock _l(mLock);
        mAudioDeviceCallbacks.replaceValueFor(ioDesc->mIoHandle, callbacks);
    }
}

@@ -618,17 +640,17 @@ sp<AudioIoDescriptor> AudioSystem::AudioFlingerClient::getIoDescriptor(audio_io_
}

status_t AudioSystem::AudioFlingerClient::addAudioDeviceCallback(
        const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
        const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
{
    Mutex::Autolock _l(mLock);
    Vector < sp<AudioDeviceCallback> > callbacks;
    Vector < wp<AudioDeviceCallback> > callbacks;
    ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(audioIo);
    if (ioIndex >= 0) {
        callbacks = mAudioDeviceCallbacks.valueAt(ioIndex);
    }

    for (size_t cbIndex = 0; cbIndex < callbacks.size(); cbIndex++) {
        if (callbacks[cbIndex] == callback) {
        if (callbacks[cbIndex].unsafe_get() == callback.unsafe_get()) {
            return INVALID_OPERATION;
        }
    }
@@ -639,18 +661,18 @@ status_t AudioSystem::AudioFlingerClient::addAudioDeviceCallback(
}

status_t AudioSystem::AudioFlingerClient::removeAudioDeviceCallback(
        const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
        const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
{
    Mutex::Autolock _l(mLock);
    ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(audioIo);
    if (ioIndex < 0) {
        return INVALID_OPERATION;
    }
    Vector < sp<AudioDeviceCallback> > callbacks = mAudioDeviceCallbacks.valueAt(ioIndex);
    Vector < wp<AudioDeviceCallback> > callbacks = mAudioDeviceCallbacks.valueAt(ioIndex);

    size_t cbIndex;
    for (cbIndex = 0; cbIndex < callbacks.size(); cbIndex++) {
        if (callbacks[cbIndex] == callback) {
        if (callbacks[cbIndex].unsafe_get() == callback.unsafe_get()) {
            break;
        }
    }
@@ -1128,7 +1150,7 @@ status_t AudioSystem::removeAudioPortCallback(const sp<AudioPortCallback>& callb
}

status_t AudioSystem::addAudioDeviceCallback(
        const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
        const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
{
    const sp<AudioFlingerClient> afc = getAudioFlingerClient();
    if (afc == 0) {
@@ -1145,7 +1167,7 @@ status_t AudioSystem::addAudioDeviceCallback(
}

status_t AudioSystem::removeAudioDeviceCallback(
        const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
        const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
{
    const sp<AudioFlingerClient> afc = getAudioFlingerClient();
    if (afc == 0) {
+67 −28
Original line number Diff line number Diff line
@@ -276,7 +276,7 @@ AudioTrack::~AudioTrack()
        }
        // No lock here: worst case we remove a NULL callback which will be a nop
        if (mDeviceCallback != 0 && mOutput != AUDIO_IO_HANDLE_NONE) {
            AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput);
            AudioSystem::removeAudioDeviceCallback(this, mOutput);
        }
        IInterface::asBinder(mAudioTrack)->unlinkToDeath(mDeathNotifier, this);
        mAudioTrack.clear();
@@ -1229,19 +1229,26 @@ audio_port_handle_t AudioTrack::getOutputDevice() {
    return mSelectedDeviceId;
}

audio_port_handle_t AudioTrack::getRoutedDeviceId() {
    AutoMutex lock(mLock);
    if (mOutput == AUDIO_IO_HANDLE_NONE) {
        return AUDIO_PORT_HANDLE_NONE;
// must be called with mLock held
void AudioTrack::updateRoutedDeviceId_l()
{
    // if the track is inactive, do not update actual device as the output stream maybe routed
    // to a device not relevant to this client because of other active use cases.
    if (mState != STATE_ACTIVE) {
        return;
    }
    // if the output stream does not have an active audio patch, use either the device initially
    // selected by audio policy manager or the last routed device
    if (mOutput != AUDIO_IO_HANDLE_NONE) {
        audio_port_handle_t deviceId = AudioSystem::getDeviceIdForIo(mOutput);
    if (deviceId == AUDIO_PORT_HANDLE_NONE) {
        deviceId = mRoutedDeviceId;
    }
        if (deviceId != AUDIO_PORT_HANDLE_NONE) {
            mRoutedDeviceId = deviceId;
    return deviceId;
        }
    }
}

audio_port_handle_t AudioTrack::getRoutedDeviceId() {
    AutoMutex lock(mLock);
    updateRoutedDeviceId_l();
    return mRoutedDeviceId;
}

status_t AudioTrack::attachAuxEffect(int effectId)
@@ -1305,12 +1312,10 @@ status_t AudioTrack::createTrack_l()
        return NO_INIT;
    }

    if (mDeviceCallback != 0 && mOutput != AUDIO_IO_HANDLE_NONE) {
        AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput);
    }
    audio_io_handle_t output;
    audio_stream_type_t streamType = mStreamType;
    audio_attributes_t *attr = (mStreamType == AUDIO_STREAM_DEFAULT) ? &mAttributes : NULL;
    bool callbackAdded = false;

    // mFlags (not mOrigFlags) is modified depending on whether fast request is accepted.
    // After fast request is denied, we will request again if IAudioTrack is re-created.
@@ -1515,12 +1520,14 @@ status_t AudioTrack::createTrack_l()
    sp<IMemory> iMem = track->getCblk();
    if (iMem == 0) {
        ALOGE("Could not get control block");
        return NO_INIT;
        status = NO_INIT;
        goto release;
    }
    void *iMemPointer = iMem->pointer();
    if (iMemPointer == NULL) {
        ALOGE("Could not get control block pointer");
        return NO_INIT;
        status = NO_INIT;
        goto release;
    }
    // invariant that mAudioTrack != 0 is true only after set() returns successfully
    if (mAudioTrack != 0) {
@@ -1582,6 +1589,15 @@ status_t AudioTrack::createTrack_l()
        }
    }

    //mOutput != output includes the case where mOutput == AUDIO_IO_HANDLE_NONE for first creation
    if (mDeviceCallback != 0 && mOutput != output) {
        if (mOutput != AUDIO_IO_HANDLE_NONE) {
            AudioSystem::removeAudioDeviceCallback(this, mOutput);
        }
        AudioSystem::addAudioDeviceCallback(this, output);
        callbackAdded = true;
    }

    // We retain a copy of the I/O handle, but don't own the reference
    mOutput = output;
    mRefreshRemaining = true;
@@ -1597,7 +1613,8 @@ status_t AudioTrack::createTrack_l()
        buffers = mSharedBuffer->pointer();
        if (buffers == NULL) {
            ALOGE("Could not get buffer pointer");
            return NO_INIT;
            status = NO_INIT;
            goto release;
        }
    }

@@ -1642,15 +1659,15 @@ status_t AudioTrack::createTrack_l()
    mDeathNotifier = new DeathNotifier(this);
    IInterface::asBinder(mAudioTrack)->linkToDeath(mDeathNotifier, this);

    if (mDeviceCallback != 0) {
        AudioSystem::addAudioDeviceCallback(mDeviceCallback, mOutput);
    }

    return NO_ERROR;
    }

release:
    AudioSystem::releaseOutput(output, streamType, mSessionId);
    if (callbackAdded) {
        // note: mOutput is always valid is callbackAdded is true
        AudioSystem::removeAudioDeviceCallback(this, mOutput);
    }
    if (status == NO_ERROR) {
        status = NO_INIT;
    }
@@ -2851,7 +2868,7 @@ status_t AudioTrack::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCal
        return BAD_VALUE;
    }
    AutoMutex lock(mLock);
    if (mDeviceCallback == callback) {
    if (mDeviceCallback.unsafe_get() == callback.get()) {
        ALOGW("%s adding same callback!", __FUNCTION__);
        return INVALID_OPERATION;
    }
@@ -2859,9 +2876,9 @@ status_t AudioTrack::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCal
    if (mOutput != AUDIO_IO_HANDLE_NONE) {
        if (mDeviceCallback != 0) {
            ALOGW("%s callback already present!", __FUNCTION__);
            AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput);
            AudioSystem::removeAudioDeviceCallback(this, mOutput);
        }
        status = AudioSystem::addAudioDeviceCallback(callback, mOutput);
        status = AudioSystem::addAudioDeviceCallback(this, mOutput);
    }
    mDeviceCallback = callback;
    return status;
@@ -2875,17 +2892,39 @@ status_t AudioTrack::removeAudioDeviceCallback(
        return BAD_VALUE;
    }
    AutoMutex lock(mLock);
    if (mDeviceCallback != callback) {
    if (mDeviceCallback.unsafe_get() != callback.get()) {
        ALOGW("%s removing different callback!", __FUNCTION__);
        return INVALID_OPERATION;
    }
    mDeviceCallback.clear();
    if (mOutput != AUDIO_IO_HANDLE_NONE) {
        AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput);
        AudioSystem::removeAudioDeviceCallback(this, mOutput);
    }
    mDeviceCallback = 0;
    return NO_ERROR;
}


void AudioTrack::onAudioDeviceUpdate(audio_io_handle_t audioIo,
                                 audio_port_handle_t deviceId)
{
    sp<AudioSystem::AudioDeviceCallback> callback;
    {
        AutoMutex lock(mLock);
        if (audioIo != mOutput) {
            return;
        }
        callback = mDeviceCallback.promote();
        // only update device if the track is active as route changes due to other use cases are
        // irrelevant for this client
        if (mState == STATE_ACTIVE) {
            mRoutedDeviceId = deviceId;
        }
    }
    if (callback.get() != nullptr) {
        callback->onAudioDeviceUpdate(mOutput, mRoutedDeviceId);
    }
}

status_t AudioTrack::pendingDuration(int32_t *msec, ExtendedTimestamp::Location location)
{
    if (msec == nullptr ||
+2 −0
Original line number Diff line number Diff line
@@ -20,9 +20,11 @@
namespace android {

enum audio_io_config_event {
    AUDIO_OUTPUT_REGISTERED,
    AUDIO_OUTPUT_OPENED,
    AUDIO_OUTPUT_CLOSED,
    AUDIO_OUTPUT_CONFIG_CHANGED,
    AUDIO_INPUT_REGISTERED,
    AUDIO_INPUT_OPENED,
    AUDIO_INPUT_CLOSED,
    AUDIO_INPUT_CONFIG_CHANGED,
+14 −3
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ class AudioRecordClientProxy;

// ----------------------------------------------------------------------------

class AudioRecord : public RefBase
class AudioRecord : public AudioSystem::AudioDeviceCallback
{
public:

@@ -424,7 +424,12 @@ public:

     /* Returns the ID of the audio device actually used by the input to which this AudioRecord
      * is attached.
      * A value of AUDIO_PORT_HANDLE_NONE indicates the AudioRecord is not attached to any input.
      * The device ID is relevant only if the AudioRecord is active.
      * When the AudioRecord is inactive, the device ID returned can be either:
      * - AUDIO_PORT_HANDLE_NONE if the AudioRecord is not attached to any output.
      * - The device ID used before paused or stopped.
      * - The device ID selected by audio policy manager of setOutputDevice() if the AudioRecord
      * has not been started yet.
      *
      * Parameters:
      *  none.
@@ -454,6 +459,10 @@ public:
            status_t removeAudioDeviceCallback(
                    const sp<AudioSystem::AudioDeviceCallback>& callback);

            // AudioSystem::AudioDeviceCallback> virtuals
            virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo,
                                             audio_port_handle_t deviceId);

private:
    /* If nonContig is non-NULL, it is an output parameter that will be set to the number of
     * additional non-contiguous frames that are predicted to be available immediately,
@@ -561,6 +570,8 @@ private:
            // FIXME enum is faster than strcmp() for parameter 'from'
            status_t restoreRecord_l(const char *from);

            void     updateRoutedDeviceId_l();

    sp<AudioRecordThread>   mAudioRecordThread;
    mutable Mutex           mLock;

@@ -665,7 +676,7 @@ private:
    audio_port_handle_t     mRoutedDeviceId;   // Device actually selected by audio policy manager:
                                              // May not match the app selection depending on other
                                              // activity and connected devices
    sp<AudioSystem::AudioDeviceCallback> mDeviceCallback;
    wp<AudioSystem::AudioDeviceCallback> mDeviceCallback;
    audio_port_handle_t    mPortId;  // unique ID allocated by audio policy

};
Loading