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

Commit 72af8011 authored by Eric Laurent's avatar Eric Laurent
Browse files

audio policy: optimize preferred device selection

Several optimizations to avoid redundant track invalidation
when a preferred device is specified for an AudioTrack.
1) in AudioTrack: only invalidate the track if the preferred device
   differs from the actual device. If the track is not active,
   immediately restore it instead of waiting for next start.
2) in AudioPolicyManager: avoid invalidating the track in startSource() and
   stopSource() if another active client with the same preferred device
   exists.

Also fix a problem in getOutput() preventing MediaPlayer to open a sink
for call assistant use case.

Bug: 272560885
Test: atest RoutingTest
Change-Id: Ia3fb06eaf2e292d2795d588226c7672b7ab6722f
parent b6cf5390
Loading
Loading
Loading
Loading
+13 −5
Original line number Diff line number Diff line
@@ -1789,13 +1789,21 @@ audio_io_handle_t AudioTrack::getOutput() const

status_t AudioTrack::setOutputDevice(audio_port_handle_t deviceId) {
    AutoMutex lock(mLock);
    ALOGV("%s(%d): deviceId=%d mSelectedDeviceId=%d",
            __func__, mPortId, deviceId, mSelectedDeviceId);
    ALOGV("%s(%d): deviceId=%d mSelectedDeviceId=%d mRoutedDeviceId %d",
            __func__, mPortId, deviceId, mSelectedDeviceId, mRoutedDeviceId);
    if (mSelectedDeviceId != deviceId) {
        mSelectedDeviceId = deviceId;
        if (mStatus == NO_ERROR) {
        if (mStatus == NO_ERROR && mSelectedDeviceId != mRoutedDeviceId) {
            if (isPlaying_l()) {
                android_atomic_or(CBLK_INVALID, &mCblk->mFlags);
                mProxy->interrupt();
            } else {
                // if the track is idle, try to restore now and
                // defer to next start if not possible
                if (restoreTrack_l("setOutputDevice") != OK) {
                    android_atomic_or(CBLK_INVALID, &mCblk->mFlags);
                }
            }
        }
    }
    return NO_ERROR;
+3 −0
Original line number Diff line number Diff line
@@ -1176,6 +1176,9 @@ public:

            bool isPlaying() {
                AutoMutex lock(mLock);
                return isPlaying_l();
            }
            bool isPlaying_l() {
                return mState == STATE_ACTIVE || mState == STATE_STOPPING;
            }

+1 −2
Original line number Diff line number Diff line
@@ -1836,7 +1836,6 @@ MediaPlayerService::AudioOutput::AudioOutput(audio_session_t sessionId,
    } else {
        mAttributes = NULL;
    }

    setMinBufferCount();
}

@@ -2683,7 +2682,7 @@ size_t MediaPlayerService::AudioOutput::CallbackData::onMoreData(const AudioTrac
    // This is a benign busy-wait, with the next data request generated 10 ms or more later;
    // nevertheless for power reasons, we don't want to see too many of these.

    ALOGV_IF(actualSize == 0 && buffer->size > 0, "callbackwrapper: empty buffer returned");
    ALOGV_IF(actualSize == 0 && buffer.size() > 0, "callbackwrapper: empty buffer returned");
    unlock();
    return actualSize;
}
+4 −0
Original line number Diff line number Diff line
@@ -301,6 +301,10 @@ public:
        return mActiveClients;
    }

    // Returns 0 if not all active clients have the same exclusive preferred device
    // or the number of active clients with the same exclusive preferred device
    size_t sameExclusivePreferredDevicesCount() const;

    bool useHwGain() const
    {
        return !devices().isEmpty() ? devices().itemAt(0)->hasGainController() : false;
+21 −0
Original line number Diff line number Diff line
@@ -237,6 +237,27 @@ TrackClientVector AudioOutputDescriptor::clientsList(bool activeOnly, product_st
    return clients;
}

size_t AudioOutputDescriptor::sameExclusivePreferredDevicesCount() const
{
    audio_port_handle_t deviceId = AUDIO_PORT_HANDLE_NONE;
    size_t count = 0;
    for (const auto &client : getClientIterable()) {
        if (client->active()) {
            if (!(client->hasPreferredDevice() &&
                    client->isPreferredDeviceForExclusiveUse())) {
                return 0;
            }
            if (deviceId == AUDIO_PORT_HANDLE_NONE) {
                deviceId = client->preferredDeviceId();
            } else if (deviceId != client->preferredDeviceId()) {
                return 0;
            }
            count++;
        }
    }
    return count;
}

bool AudioOutputDescriptor::isAnyActive(VolumeSource volumeSourceToIgnore) const
{
    return std::find_if(begin(mActiveClients), end(mActiveClients),
Loading