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

Commit c6141c14 authored by Automerger Merge Worker's avatar Automerger Merge Worker
Browse files

Merge "audio policy: more concurrent capture fixes" into rvc-dev am: e60c66f2

Change-Id: I55fe3211363d43847a545a1f8cc8bf3f9818b253
parents e055f373 e60c66f2
Loading
Loading
Loading
Loading
+78 −34
Original line number Diff line number Diff line
@@ -446,17 +446,19 @@ void AudioPolicyService::updateUidStates_l()

    sp<AudioRecordClient> topActive;
    sp<AudioRecordClient> latestActive;
    sp<AudioRecordClient> topSensitiveActive;
    sp<AudioRecordClient> latestSensitiveActive;

    nsecs_t topStartNs = 0;
    nsecs_t latestStartNs = 0;
    nsecs_t topSensitiveStartNs = 0;
    nsecs_t latestSensitiveStartNs = 0;
    bool isA11yOnTop = mUidPolicy->isA11yOnTop();
    bool isAssistantOnTop = false;
    bool isSensitiveActive = false;
    bool isInCall = mPhoneState == AUDIO_MODE_IN_CALL;
    bool rttCallActive =
            (mPhoneState == AUDIO_MODE_IN_CALL || mPhoneState == AUDIO_MODE_IN_COMMUNICATION)
    bool isInCommunication = mPhoneState == AUDIO_MODE_IN_COMMUNICATION;
    bool rttCallActive = (isInCall || isInCommunication)
            && mUidPolicy->isRttEnabled();
    bool onlyHotwordActive = true;

@@ -479,32 +481,46 @@ void AudioPolicyService::updateUidStates_l()
            continue;
        }

        bool isAssistant = mUidPolicy->isAssistantUid(current->uid);
        bool isAccessibility = mUidPolicy->isA11yUid(current->uid);
        if (appState == APP_STATE_TOP && !isAccessibility) {
        // Clients capturing for Accessibility services are not considered
        // for top or latest active to avoid masking regular clients started before
        if (!isAccessibility) {
            bool isAssistant = mUidPolicy->isAssistantUid(current->uid);
            bool isPrivacySensitive =
                    (current->attributes.flags & AUDIO_FLAG_CAPTURE_PRIVATE) != 0;
            if (appState == APP_STATE_TOP) {
                if (isPrivacySensitive) {
                    if (current->startTimeNs > topSensitiveStartNs) {
                        topSensitiveActive = current;
                        topSensitiveStartNs = current->startTimeNs;
                    }
                } else {
                    if (current->startTimeNs > topStartNs) {
                        topActive = current;
                        topStartNs = current->startTimeNs;
                    }
                }
                if (isAssistant) {
                    isAssistantOnTop = true;
                }
            }
        // Client capturing for HOTWORD or Accessibility services not considered
            // Clients capturing for HOTWORD are not considered
            // for latest active to avoid masking regular clients started before
        if (current->startTimeNs > latestStartNs
                && !(current->attributes.source == AUDIO_SOURCE_HOTWORD
                        || ((isA11yOnTop || rttCallActive) && isAssistant))
                && !isAccessibility) {
            latestActive = current;
            latestStartNs = current->startTimeNs;
        }
        if ((current->attributes.flags & AUDIO_FLAG_CAPTURE_PRIVATE) != 0) {
            if (!(current->attributes.source == AUDIO_SOURCE_HOTWORD
                    || ((isA11yOnTop || rttCallActive) && isAssistant))) {
                if (isPrivacySensitive) {
                    if (current->startTimeNs > latestSensitiveStartNs) {
                        latestSensitiveActive = current;
                        latestSensitiveStartNs = current->startTimeNs;
                    }
                    isSensitiveActive = true;
                } else {
                    if (current->startTimeNs > latestStartNs) {
                        latestActive = current;
                        latestStartNs = current->startTimeNs;
                    }
                }
            }
        }
        if (current->attributes.source != AUDIO_SOURCE_HOTWORD) {
            onlyHotwordActive = false;
@@ -514,6 +530,21 @@ void AudioPolicyService::updateUidStates_l()
    // if no active client with UI on Top, consider latest active as top
    if (topActive == nullptr) {
        topActive = latestActive;
        topStartNs = latestStartNs;
    }
    if (topSensitiveActive == nullptr) {
        topSensitiveActive = latestSensitiveActive;
        topSensitiveStartNs = latestSensitiveStartNs;
    }

    // If both privacy sensitive and regular capture are active:
    //  if the regular capture is privileged
    //    allow concurrency
    //  else
    //    favor the privacy sensitive case
    if (topActive != nullptr && topSensitiveActive != nullptr
            && !topActive->canCaptureCallOrOutput) {
        topActive = nullptr;
    }

    for (size_t i =0; i < mAudioRecordClients.size(); i++) {
@@ -524,8 +555,17 @@ void AudioPolicyService::updateUidStates_l()

        audio_source_t source = current->attributes.source;
        bool isTopOrLatestActive = topActive == nullptr ? false : current->uid == topActive->uid;
        bool isLatestSensitive = latestSensitiveActive == nullptr ?
                                 false : current->uid == latestSensitiveActive->uid;
        bool isTopOrLatestSensitive = topSensitiveActive == nullptr ?
                                 false : current->uid == topSensitiveActive->uid;

        auto canCaptureIfInCallOrCommunication = [&](const auto &recordClient) {
            bool canCaptureCall = recordClient->canCaptureCallOrOutput;
            bool canCaptureCommunication = recordClient->canCaptureCallOrOutput
                || recordClient->uid == mPhoneStateOwnerUid
                || isServiceUid(mPhoneStateOwnerUid);
            return !(isInCall && !canCaptureCall)
                && !(isInCommunication && !canCaptureCommunication);
        };

        // By default allow capture if:
        //     The assistant is not on TOP
@@ -533,9 +573,10 @@ void AudioPolicyService::updateUidStates_l()
        //     AND there is no active privacy sensitive capture or call
        //             OR client has CAPTURE_AUDIO_OUTPUT privileged permission
        bool allowCapture = !isAssistantOnTop
                && ((isTopOrLatestActive && !isLatestSensitive) || isLatestSensitive)
                && !(isSensitiveActive && !(isLatestSensitive || current->canCaptureCallOrOutput))
                && !(isInCall && !current->canCaptureCallOrOutput);
                && (isTopOrLatestActive || isTopOrLatestSensitive)
                && !(isSensitiveActive
                    && !(isTopOrLatestSensitive || current->canCaptureCallOrOutput))
                && canCaptureIfInCallOrCommunication(current);

        if (isVirtualSource(source)) {
            // Allow capture for virtual (remote submix, call audio TX or RX...) sources
@@ -554,8 +595,9 @@ void AudioPolicyService::updateUidStates_l()
                }
            } else {
                if (((isAssistantOnTop && source == AUDIO_SOURCE_VOICE_RECOGNITION) ||
                        source == AUDIO_SOURCE_HOTWORD) &&
                        (!(isSensitiveActive || isInCall) || current->canCaptureCallOrOutput)) {
                        source == AUDIO_SOURCE_HOTWORD)
                        && !(isSensitiveActive && !current->canCaptureCallOrOutput)
                        && canCaptureIfInCallOrCommunication(current)) {
                    allowCapture = true;
                }
            }
@@ -567,7 +609,8 @@ void AudioPolicyService::updateUidStates_l()
            //     OR
            //         Is on TOP AND the source is VOICE_RECOGNITION or HOTWORD
            if (!isAssistantOnTop
                    && (!(isSensitiveActive || isInCall) || current->canCaptureCallOrOutput)) {
                    && !(isSensitiveActive && !current->canCaptureCallOrOutput)
                    && canCaptureIfInCallOrCommunication(current)) {
                allowCapture = true;
            }
            if (isA11yOnTop) {
@@ -580,7 +623,8 @@ void AudioPolicyService::updateUidStates_l()
            //     All active clients are using HOTWORD source
            //     AND no call is active
            //         OR client has CAPTURE_AUDIO_OUTPUT privileged permission
            if (onlyHotwordActive && !(isInCall && !current->canCaptureCallOrOutput)) {
            if (onlyHotwordActive
                    && canCaptureIfInCallOrCommunication(current)) {
                allowCapture = true;
            }
        }