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

Commit 09f1ed2c authored by Eric Laurent's avatar Eric Laurent
Browse files

audio: improve audio routing callbacks

Do not force audio device changed callback when the client
(AudioTrack or AudioRecord) registers to AudioFlinger but only when
it starts playback or capture. Doing so prevents a spurious callback
happing at registration time where a stale device
(previously selected by AudioFlinger thread) but irrelevant to this
client is indicated. This causes a disconnection of AAudio streams
despite no real device change.

Bug: 128630993
Test: CTS: android.nativemedia.aaudio.AAudioTests, android.media.cts.RoutingTest
      CTS Verifier: Audio Input/Output Routing Notifications Test

Change-Id: Ia7f1d11490989b0287c97479466c1c07a223aab3
parent 2f7a6072
Loading
Loading
Loading
Loading
+10 −10
Original line number Original line Diff line number Diff line
@@ -177,7 +177,7 @@ AudioRecord::~AudioRecord()
        }
        }
        // No lock here: worst case we remove a NULL callback which will be a nop
        // No lock here: worst case we remove a NULL callback which will be a nop
        if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) {
        if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) {
            AudioSystem::removeAudioDeviceCallback(this, mInput);
            AudioSystem::removeAudioDeviceCallback(this, mInput, mPortId);
        }
        }
        IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this);
        IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this);
        mAudioRecord.clear();
        mAudioRecord.clear();
@@ -790,14 +790,13 @@ status_t AudioRecord::createRecord_l(const Modulo<uint32_t> &epoch, const String
    mAudioRecord = record;
    mAudioRecord = record;
    mCblkMemory = output.cblk;
    mCblkMemory = output.cblk;
    mBufferMemory = output.buffers;
    mBufferMemory = output.buffers;
    mPortId = output.portId;
    IPCThreadState::self()->flushCommands();
    IPCThreadState::self()->flushCommands();


    mCblk = cblk;
    mCblk = cblk;
    // note that output.frameCount is the (possibly revised) value of mReqFrameCount
    // note that output.frameCount is the (possibly revised) value of mReqFrameCount
    if (output.frameCount < mReqFrameCount || (mReqFrameCount == 0 && output.frameCount == 0)) {
    if (output.frameCount < mReqFrameCount || (mReqFrameCount == 0 && output.frameCount == 0)) {
        ALOGW("%s(%d): Requested frameCount %zu but received frameCount %zu",
        ALOGW("%s(%d): Requested frameCount %zu but received frameCount %zu",
              __func__, mPortId,
              __func__, output.portId,
              mReqFrameCount,  output.frameCount);
              mReqFrameCount,  output.frameCount);
    }
    }


@@ -805,19 +804,20 @@ status_t AudioRecord::createRecord_l(const Modulo<uint32_t> &epoch, const String
    // The computation is done on server side.
    // The computation is done on server side.
    if (mNotificationFramesReq > 0 && output.notificationFrameCount != mNotificationFramesReq) {
    if (mNotificationFramesReq > 0 && output.notificationFrameCount != mNotificationFramesReq) {
        ALOGW("%s(%d): Server adjusted notificationFrames from %u to %zu for frameCount %zu",
        ALOGW("%s(%d): Server adjusted notificationFrames from %u to %zu for frameCount %zu",
                __func__, mPortId,
                __func__, output.portId,
                mNotificationFramesReq, output.notificationFrameCount, output.frameCount);
                mNotificationFramesReq, output.notificationFrameCount, output.frameCount);
    }
    }
    mNotificationFramesAct = (uint32_t)output.notificationFrameCount;
    mNotificationFramesAct = (uint32_t)output.notificationFrameCount;


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


    mPortId = output.portId;
    // We retain a copy of the I/O handle, but don't own the reference
    // We retain a copy of the I/O handle, but don't own the reference
    mInput = output.inputId;
    mInput = output.inputId;
    mRefreshRemaining = true;
    mRefreshRemaining = true;
@@ -1332,9 +1332,9 @@ status_t AudioRecord::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCa
    if (mInput != AUDIO_IO_HANDLE_NONE) {
    if (mInput != AUDIO_IO_HANDLE_NONE) {
        if (mDeviceCallback != 0) {
        if (mDeviceCallback != 0) {
            ALOGW("%s(%d): callback already present!", __func__, mPortId);
            ALOGW("%s(%d): callback already present!", __func__, mPortId);
            AudioSystem::removeAudioDeviceCallback(this, mInput);
            AudioSystem::removeAudioDeviceCallback(this, mInput, mPortId);
        }
        }
        status = AudioSystem::addAudioDeviceCallback(this, mInput);
        status = AudioSystem::addAudioDeviceCallback(this, mInput, mPortId);
    }
    }
    mDeviceCallback = callback;
    mDeviceCallback = callback;
    return status;
    return status;
@@ -1354,7 +1354,7 @@ status_t AudioRecord::removeAudioDeviceCallback(
    }
    }
    mDeviceCallback.clear();
    mDeviceCallback.clear();
    if (mInput != AUDIO_IO_HANDLE_NONE) {
    if (mInput != AUDIO_IO_HANDLE_NONE) {
        AudioSystem::removeAudioDeviceCallback(this, mInput);
        AudioSystem::removeAudioDeviceCallback(this, mInput, mPortId);
    }
    }
    return NO_ERROR;
    return NO_ERROR;
}
}
+57 −74
Original line number Original line Diff line number Diff line
@@ -523,12 +523,10 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even
    if (ioDesc == 0 || ioDesc->mIoHandle == AUDIO_IO_HANDLE_NONE) return;
    if (ioDesc == 0 || ioDesc->mIoHandle == AUDIO_IO_HANDLE_NONE) return;


    audio_port_handle_t deviceId = AUDIO_PORT_HANDLE_NONE;
    audio_port_handle_t deviceId = AUDIO_PORT_HANDLE_NONE;
    Vector<sp<AudioDeviceCallback>> callbacksToCall;
    std::vector<sp<AudioDeviceCallback>> callbacksToCall;
    {
    {
        Mutex::Autolock _l(mLock);
        Mutex::Autolock _l(mLock);
        bool deviceValidOrChanged = false;
        auto callbacks = std::map<audio_port_handle_t, wp<AudioDeviceCallback>>();
        bool sendCallbacks = false;
        ssize_t ioIndex = -1;


        switch (event) {
        switch (event) {
        case AUDIO_OUTPUT_OPENED:
        case AUDIO_OUTPUT_OPENED:
@@ -546,17 +544,11 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even
            if (ioDesc->getDeviceId() != AUDIO_PORT_HANDLE_NONE) {
            if (ioDesc->getDeviceId() != AUDIO_PORT_HANDLE_NONE) {
                deviceId = ioDesc->getDeviceId();
                deviceId = ioDesc->getDeviceId();
                if (event == AUDIO_OUTPUT_OPENED || event == AUDIO_INPUT_OPENED) {
                if (event == AUDIO_OUTPUT_OPENED || event == AUDIO_INPUT_OPENED) {
                    ioIndex = mAudioDeviceCallbackProxies.indexOfKey(ioDesc->mIoHandle);
                    auto it = mAudioDeviceCallbacks.find(ioDesc->mIoHandle);
                    if (ioIndex >= 0) {
                    if (it != mAudioDeviceCallbacks.end()) {
                        sendCallbacks = true;
                        callbacks = it->second;
                        deviceValidOrChanged = true;
                    }
                    }
                }
                }
                if (event == AUDIO_OUTPUT_REGISTERED || event == AUDIO_INPUT_REGISTERED) {
                    ioIndex = mAudioDeviceCallbackProxies.indexOfKey(ioDesc->mIoHandle);
                    sendCallbacks = (ioIndex >= 0)
                            && !mAudioDeviceCallbackProxies.valueAt(ioIndex).notifiedOnce();
                }
            }
            }
            ALOGV("ioConfigChanged() new %s %s %d samplingRate %u, format %#x channel mask %#x "
            ALOGV("ioConfigChanged() new %s %s %d samplingRate %u, format %#x channel mask %#x "
                    "frameCount %zu deviceId %d",
                    "frameCount %zu deviceId %d",
@@ -578,7 +570,7 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even
                  event == AUDIO_OUTPUT_CLOSED ? "output" : "input", ioDesc->mIoHandle);
                  event == AUDIO_OUTPUT_CLOSED ? "output" : "input", ioDesc->mIoHandle);


            mIoDescriptors.removeItem(ioDesc->mIoHandle);
            mIoDescriptors.removeItem(ioDesc->mIoHandle);
            mAudioDeviceCallbackProxies.removeItem(ioDesc->mIoHandle);
            mAudioDeviceCallbacks.erase(ioDesc->mIoHandle);
            } break;
            } break;


        case AUDIO_OUTPUT_CONFIG_CHANGED:
        case AUDIO_OUTPUT_CONFIG_CHANGED:
@@ -593,10 +585,11 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even
            mIoDescriptors.replaceValueFor(ioDesc->mIoHandle, ioDesc);
            mIoDescriptors.replaceValueFor(ioDesc->mIoHandle, ioDesc);


            if (deviceId != ioDesc->getDeviceId()) {
            if (deviceId != ioDesc->getDeviceId()) {
                deviceValidOrChanged = true;
                deviceId = ioDesc->getDeviceId();
                deviceId = ioDesc->getDeviceId();
                ioIndex = mAudioDeviceCallbackProxies.indexOfKey(ioDesc->mIoHandle);
                auto it = mAudioDeviceCallbacks.find(ioDesc->mIoHandle);
                sendCallbacks = ioIndex >= 0;
                if (it != mAudioDeviceCallbacks.end()) {
                    callbacks = it->second;
                }
            }
            }
            ALOGV("ioConfigChanged() new config for %s %d samplingRate %u, format %#x "
            ALOGV("ioConfigChanged() new config for %s %d samplingRate %u, format %#x "
                    "channel mask %#x frameCount %zu frameCountHAL %zu deviceId %d",
                    "channel mask %#x frameCount %zu frameCountHAL %zu deviceId %d",
@@ -606,35 +599,40 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even
                    ioDesc->getDeviceId());
                    ioDesc->getDeviceId());


        } break;
        } break;
        case AUDIO_CLIENT_STARTED: {
            sp<AudioIoDescriptor> oldDesc = getIoDescriptor_l(ioDesc->mIoHandle);
            if (oldDesc == 0) {
                ALOGW("ioConfigChanged() start client on unknown io! %d", ioDesc->mIoHandle);
                break;
            }
            }

            ALOGV("ioConfigChanged() AUDIO_CLIENT_STARTED  io %d port %d num callbacks %zu",
        // sendCallbacks true =>  ioDesc->mIoHandle and deviceId are valid
                ioDesc->mIoHandle, ioDesc->mPortId, mAudioDeviceCallbacks.size());
        if (sendCallbacks) {
            oldDesc->mPatch = ioDesc->mPatch;
            AudioDeviceCallbackProxies &callbackProxies =
            auto it = mAudioDeviceCallbacks.find(ioDesc->mIoHandle);
                mAudioDeviceCallbackProxies.editValueAt(ioIndex);
            if (it != mAudioDeviceCallbacks.end()) {
            for (size_t i = 0; i < callbackProxies.size(); ) {
                auto cbks = it->second;
                sp<AudioDeviceCallback> callback = callbackProxies[i]->callback();
                auto it2 = cbks.find(ioDesc->mPortId);
                if (callback.get() != nullptr) {
                if (it2 != cbks.end()) {
                    // Call the callback only if the device actually changed, the input or output
                   callbacks.emplace(ioDesc->mPortId, it2->second);
                    // was opened or closed or the client was newly registered and the callback
                   deviceId = oldDesc->getDeviceId();
                    // was never called
                    if (!callbackProxies[i]->notifiedOnce() || deviceValidOrChanged) {
                        callbacksToCall.add(callback);
                        callbackProxies[i]->setNotifiedOnce();
                    }
                    i++;
                } else {
                    callbackProxies.removeAt(i);
                }
                }
            }
            }
            callbackProxies.setNotifiedOnce();
        } break;
        }

        for (auto wpCbk : callbacks) {
            sp<AudioDeviceCallback> spCbk = wpCbk.second.promote();
            if (spCbk != nullptr) {
                callbacksToCall.push_back(spCbk);
            }
        }
        }
    }
    }


    // Callbacks must be called without mLock held. May lead to dead lock if calling for
    // Callbacks must be called without mLock held. May lead to dead lock if calling for
    // example getRoutedDevice that updates the device and tries to acquire mLock.
    // example getRoutedDevice that updates the device and tries to acquire mLock.
    for (size_t i = 0; i < callbacksToCall.size(); i++) {
    for (auto cb  : callbacksToCall) {
        callbacksToCall[i]->onAudioDeviceUpdate(ioDesc->mIoHandle, deviceId);
        // If callbacksToCall is not empty, it implies ioDesc->mIoHandle and deviceId are valid
        cb->onAudioDeviceUpdate(ioDesc->mIoHandle, deviceId);
    }
    }
}
}


@@ -687,51 +685,34 @@ sp<AudioIoDescriptor> AudioSystem::AudioFlingerClient::getIoDescriptor(audio_io_
}
}


status_t AudioSystem::AudioFlingerClient::addAudioDeviceCallback(
status_t AudioSystem::AudioFlingerClient::addAudioDeviceCallback(
        const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
        const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo,
        audio_port_handle_t portId)
{
{
    ALOGV("%s audioIo %d portId %d", __func__, audioIo, portId);
    Mutex::Autolock _l(mLock);
    Mutex::Autolock _l(mLock);
    AudioDeviceCallbackProxies callbackProxies;
    auto& callbacks = mAudioDeviceCallbacks.emplace(audioIo, std::map<audio_port_handle_t, wp<AudioDeviceCallback>>()).first->second;
    ssize_t ioIndex = mAudioDeviceCallbackProxies.indexOfKey(audioIo);
    auto result = callbacks.try_emplace(portId, callback);
    if (ioIndex >= 0) {
    if (!result.second) {
        callbackProxies = mAudioDeviceCallbackProxies.valueAt(ioIndex);
    }

    for (size_t cbIndex = 0; cbIndex < callbackProxies.size(); cbIndex++) {
        sp<AudioDeviceCallback> cbk = callbackProxies[cbIndex]->callback();
        if (cbk.get() == callback.unsafe_get()) {
        return INVALID_OPERATION;
        return INVALID_OPERATION;
    }
    }
    }
    callbackProxies.add(new AudioDeviceCallbackProxy(callback));
    callbackProxies.resetNotifiedOnce();
    mAudioDeviceCallbackProxies.replaceValueFor(audioIo, callbackProxies);
    return NO_ERROR;
    return NO_ERROR;
}
}


status_t AudioSystem::AudioFlingerClient::removeAudioDeviceCallback(
status_t AudioSystem::AudioFlingerClient::removeAudioDeviceCallback(
        const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
        const wp<AudioDeviceCallback>& callback __unused, audio_io_handle_t audioIo,
        audio_port_handle_t portId)
{
{
    ALOGV("%s audioIo %d portId %d", __func__, audioIo, portId);
    Mutex::Autolock _l(mLock);
    Mutex::Autolock _l(mLock);
    ssize_t ioIndex = mAudioDeviceCallbackProxies.indexOfKey(audioIo);
    auto it = mAudioDeviceCallbacks.find(audioIo);
    if (ioIndex < 0) {
    if (it == mAudioDeviceCallbacks.end()) {
        return INVALID_OPERATION;
        return INVALID_OPERATION;
    }
    }
    AudioDeviceCallbackProxies callbackProxies = mAudioDeviceCallbackProxies.valueAt(ioIndex);
    if (it->second.erase(portId) == 0) {
    size_t cbIndex;
    for (cbIndex = 0; cbIndex < callbackProxies.size(); cbIndex++) {
        sp<AudioDeviceCallback> cbk = callbackProxies[cbIndex]->callback();
        if (cbk.get() == callback.unsafe_get()) {
            break;
        }
    }
    if (cbIndex == callbackProxies.size()) {
        return INVALID_OPERATION;
        return INVALID_OPERATION;
    }
    }
    callbackProxies.removeAt(cbIndex);
    if (it->second.size() == 0) {
    if (callbackProxies.size() != 0) {
        mAudioDeviceCallbacks.erase(audioIo);
        mAudioDeviceCallbackProxies.replaceValueFor(audioIo, callbackProxies);
    } else {
        mAudioDeviceCallbackProxies.removeItem(audioIo);
    }
    }
    return NO_ERROR;
    return NO_ERROR;
}
}
@@ -1271,13 +1252,14 @@ status_t AudioSystem::removeAudioVolumeGroupCallback(const sp<AudioVolumeGroupCa
}
}


status_t AudioSystem::addAudioDeviceCallback(
status_t AudioSystem::addAudioDeviceCallback(
        const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
        const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo,
        audio_port_handle_t portId)
{
{
    const sp<AudioFlingerClient> afc = getAudioFlingerClient();
    const sp<AudioFlingerClient> afc = getAudioFlingerClient();
    if (afc == 0) {
    if (afc == 0) {
        return NO_INIT;
        return NO_INIT;
    }
    }
    status_t status = afc->addAudioDeviceCallback(callback, audioIo);
    status_t status = afc->addAudioDeviceCallback(callback, audioIo, portId);
    if (status == NO_ERROR) {
    if (status == NO_ERROR) {
        const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
        const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
        if (af != 0) {
        if (af != 0) {
@@ -1288,13 +1270,14 @@ status_t AudioSystem::addAudioDeviceCallback(
}
}


status_t AudioSystem::removeAudioDeviceCallback(
status_t AudioSystem::removeAudioDeviceCallback(
        const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
        const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo,
        audio_port_handle_t portId)
{
{
    const sp<AudioFlingerClient> afc = getAudioFlingerClient();
    const sp<AudioFlingerClient> afc = getAudioFlingerClient();
    if (afc == 0) {
    if (afc == 0) {
        return NO_INIT;
        return NO_INIT;
    }
    }
    return afc->removeAudioDeviceCallback(callback, audioIo);
    return afc->removeAudioDeviceCallback(callback, audioIo, portId);
}
}


audio_port_handle_t AudioSystem::getDeviceIdForIo(audio_io_handle_t audioIo)
audio_port_handle_t AudioSystem::getDeviceIdForIo(audio_io_handle_t audioIo)
+11 −9
Original line number Original line Diff line number Diff line
@@ -309,7 +309,7 @@ AudioTrack::~AudioTrack()
        }
        }
        // No lock here: worst case we remove a NULL callback which will be a nop
        // No lock here: worst case we remove a NULL callback which will be a nop
        if (mDeviceCallback != 0 && mOutput != AUDIO_IO_HANDLE_NONE) {
        if (mDeviceCallback != 0 && mOutput != AUDIO_IO_HANDLE_NONE) {
            AudioSystem::removeAudioDeviceCallback(this, mOutput);
            AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId);
        }
        }
        IInterface::asBinder(mAudioTrack)->unlinkToDeath(mDeathNotifier, this);
        IInterface::asBinder(mAudioTrack)->unlinkToDeath(mDeathNotifier, this);
        mAudioTrack.clear();
        mAudioTrack.clear();
@@ -1495,7 +1495,6 @@ status_t AudioTrack::createTrack_l()
    mAfFrameCount = output.afFrameCount;
    mAfFrameCount = output.afFrameCount;
    mAfSampleRate = output.afSampleRate;
    mAfSampleRate = output.afSampleRate;
    mAfLatency = output.afLatencyMs;
    mAfLatency = output.afLatencyMs;
    mPortId = output.portId;


    mLatency = mAfLatency + (1000LL * mFrameCount) / mSampleRate;
    mLatency = mAfLatency + (1000LL * mFrameCount) / mSampleRate;


@@ -1543,14 +1542,15 @@ status_t AudioTrack::createTrack_l()
    mFlags = output.flags;
    mFlags = output.flags;


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


    mPortId = output.portId;
    // We retain a copy of the I/O handle, but don't own the reference
    // We retain a copy of the I/O handle, but don't own the reference
    mOutput = output.outputId;
    mOutput = output.outputId;
    mRefreshRemaining = true;
    mRefreshRemaining = true;
@@ -1615,7 +1615,7 @@ status_t AudioTrack::createTrack_l()
exit:
exit:
    if (status != NO_ERROR && callbackAdded) {
    if (status != NO_ERROR && callbackAdded) {
        // note: mOutput is always valid is callbackAdded is true
        // note: mOutput is always valid is callbackAdded is true
        AudioSystem::removeAudioDeviceCallback(this, mOutput);
        AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId);
    }
    }


    mStatus = status;
    mStatus = status;
@@ -2922,6 +2922,7 @@ uint32_t AudioTrack::getUnderrunFrames() const


status_t AudioTrack::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback)
status_t AudioTrack::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback)
{
{

    if (callback == 0) {
    if (callback == 0) {
        ALOGW("%s(%d): adding NULL callback!", __func__, mPortId);
        ALOGW("%s(%d): adding NULL callback!", __func__, mPortId);
        return BAD_VALUE;
        return BAD_VALUE;
@@ -2935,9 +2936,9 @@ status_t AudioTrack::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCal
    if (mOutput != AUDIO_IO_HANDLE_NONE) {
    if (mOutput != AUDIO_IO_HANDLE_NONE) {
        if (mDeviceCallback != 0) {
        if (mDeviceCallback != 0) {
            ALOGW("%s(%d): callback already present!", __func__, mPortId);
            ALOGW("%s(%d): callback already present!", __func__, mPortId);
            AudioSystem::removeAudioDeviceCallback(this, mOutput);
            AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId);
        }
        }
        status = AudioSystem::addAudioDeviceCallback(this, mOutput);
        status = AudioSystem::addAudioDeviceCallback(this, mOutput, mPortId);
    }
    }
    mDeviceCallback = callback;
    mDeviceCallback = callback;
    return status;
    return status;
@@ -2957,7 +2958,7 @@ status_t AudioTrack::removeAudioDeviceCallback(
    }
    }
    mDeviceCallback.clear();
    mDeviceCallback.clear();
    if (mOutput != AUDIO_IO_HANDLE_NONE) {
    if (mOutput != AUDIO_IO_HANDLE_NONE) {
        AudioSystem::removeAudioDeviceCallback(this, mOutput);
        AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId);
    }
    }
    return NO_ERROR;
    return NO_ERROR;
}
}
@@ -2979,6 +2980,7 @@ void AudioTrack::onAudioDeviceUpdate(audio_io_handle_t audioIo,
            mRoutedDeviceId = deviceId;
            mRoutedDeviceId = deviceId;
        }
        }
    }
    }

    if (callback.get() != nullptr) {
    if (callback.get() != nullptr) {
        callback->onAudioDeviceUpdate(mOutput, mRoutedDeviceId);
        callback->onAudioDeviceUpdate(mOutput, mRoutedDeviceId);
    }
    }
+2 −0
Original line number Original line Diff line number Diff line
@@ -52,6 +52,7 @@ public:
        data.writeInt64(ioDesc->mFrameCount);
        data.writeInt64(ioDesc->mFrameCount);
        data.writeInt64(ioDesc->mFrameCountHAL);
        data.writeInt64(ioDesc->mFrameCountHAL);
        data.writeInt32(ioDesc->mLatency);
        data.writeInt32(ioDesc->mLatency);
        data.writeInt32(ioDesc->mPortId);
        remote()->transact(IO_CONFIG_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
        remote()->transact(IO_CONFIG_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
    }
    }
};
};
@@ -76,6 +77,7 @@ status_t BnAudioFlingerClient::onTransact(
            ioDesc->mFrameCount = data.readInt64();
            ioDesc->mFrameCount = data.readInt64();
            ioDesc->mFrameCountHAL = data.readInt64();
            ioDesc->mFrameCountHAL = data.readInt64();
            ioDesc->mLatency = data.readInt32();
            ioDesc->mLatency = data.readInt32();
            ioDesc->mPortId = data.readInt32();
            ioConfigChanged(event, ioDesc);
            ioConfigChanged(event, ioDesc);
            return NO_ERROR;
            return NO_ERROR;
        } break;
        } break;
+3 −1
Original line number Original line Diff line number Diff line
@@ -28,6 +28,7 @@ enum audio_io_config_event {
    AUDIO_INPUT_OPENED,
    AUDIO_INPUT_OPENED,
    AUDIO_INPUT_CLOSED,
    AUDIO_INPUT_CLOSED,
    AUDIO_INPUT_CONFIG_CHANGED,
    AUDIO_INPUT_CONFIG_CHANGED,
    AUDIO_CLIENT_STARTED,
};
};


// audio input/output descriptor used to cache output configurations in client process to avoid
// audio input/output descriptor used to cache output configurations in client process to avoid
@@ -37,7 +38,7 @@ public:
    AudioIoDescriptor() :
    AudioIoDescriptor() :
        mIoHandle(AUDIO_IO_HANDLE_NONE),
        mIoHandle(AUDIO_IO_HANDLE_NONE),
        mSamplingRate(0), mFormat(AUDIO_FORMAT_DEFAULT), mChannelMask(AUDIO_CHANNEL_NONE),
        mSamplingRate(0), mFormat(AUDIO_FORMAT_DEFAULT), mChannelMask(AUDIO_CHANNEL_NONE),
        mFrameCount(0), mFrameCountHAL(0), mLatency(0)
        mFrameCount(0), mFrameCountHAL(0), mLatency(0), mPortId(AUDIO_PORT_HANDLE_NONE)
    {
    {
        memset(&mPatch, 0, sizeof(struct audio_patch));
        memset(&mPatch, 0, sizeof(struct audio_patch));
    }
    }
@@ -66,6 +67,7 @@ public:
    size_t                  mFrameCount;
    size_t                  mFrameCount;
    size_t                  mFrameCountHAL;
    size_t                  mFrameCountHAL;
    uint32_t                mLatency;   // only valid for output
    uint32_t                mLatency;   // only valid for output
    audio_port_handle_t     mPortId;    // valid for event AUDIO_CLIENT_STARTED
};
};




Loading