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

Commit 1c81145d authored by Eric Laurent's avatar Eric Laurent Committed by Android (Google) Code Review
Browse files

Merge "audio policy: fix several problems with capture policy"

parents 125f082b 1ff16a77
Loading
Loading
Loading
Loading
+7 −4
Original line number Diff line number Diff line
@@ -376,15 +376,17 @@ status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr,
        return PERMISSION_DENIED;
    }

    bool canCaptureOutput = captureAudioOutputAllowed(pid, uid);
    if ((attr->source == AUDIO_SOURCE_VOICE_UPLINK ||
        attr->source == AUDIO_SOURCE_VOICE_DOWNLINK ||
        attr->source == AUDIO_SOURCE_VOICE_CALL ||
        attr->source == AUDIO_SOURCE_ECHO_REFERENCE) &&
        !captureAudioOutputAllowed(pid, uid)) {
        !canCaptureOutput) {
        return PERMISSION_DENIED;
    }

    if ((attr->source == AUDIO_SOURCE_HOTWORD) && !captureHotwordAllowed(pid, uid)) {
    bool canCaptureHotword = captureHotwordAllowed(pid, uid);
    if ((attr->source == AUDIO_SOURCE_HOTWORD) && !canCaptureHotword) {
        return BAD_VALUE;
    }

@@ -415,7 +417,7 @@ status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr,
            case AudioPolicyInterface::API_INPUT_TELEPHONY_RX:
                // FIXME: use the same permission as for remote submix for now.
            case AudioPolicyInterface::API_INPUT_MIX_CAPTURE:
                if (!captureAudioOutputAllowed(pid, uid)) {
                if (!canCaptureOutput) {
                    ALOGE("getInputForAttr() permission denied: capture not allowed");
                    status = PERMISSION_DENIED;
                }
@@ -442,7 +444,8 @@ status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr,
        }

        sp<AudioRecordClient> client = new AudioRecordClient(*attr, *input, uid, pid, session,
                                                             *selectedDeviceId, opPackageName);
                                                             *selectedDeviceId, opPackageName,
                                                             canCaptureOutput, canCaptureHotword);
        mAudioRecordClients.add(*portId, client);
    }

+85 −46
Original line number Diff line number Diff line
@@ -414,32 +414,35 @@ void AudioPolicyService::updateUidStates_l()
{
//    Go over all active clients and allow capture (does not force silence) in the
//    following cases:
//    The client is the assistant
//    Another client in the same UID has already been allowed to capture
//    OR The client is the assistant
//        AND an accessibility service is on TOP
//               AND the source is VOICE_RECOGNITION or HOTWORD
//        OR uses VOICE_RECOGNITION AND is on TOP OR latest started
//               OR uses HOTWORD
//            AND there is no privacy sensitive active capture
//            AND there is no active privacy sensitive capture or call
//                OR client has CAPTURE_AUDIO_OUTPUT privileged permission
//    OR The client is an accessibility service
//        AND is on TOP OR latest started
//        AND the source is VOICE_RECOGNITION or HOTWORD
//    OR the source is one of: AUDIO_SOURCE_VOICE_DOWNLINK, AUDIO_SOURCE_VOICE_UPLINK,
//       AUDIO_SOURCE_VOICE_CALL
//    OR the client source is virtual (remote submix, call audio TX or RX...)
//    OR Any other client
//        AND The assistant is not on TOP
//        AND is on TOP OR latest started
//        AND there is no privacy sensitive active capture
//        AND there is no active privacy sensitive capture or call
//                OR client has CAPTURE_AUDIO_OUTPUT privileged permission
//TODO: mamanage pre processing effects according to use case priority

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

    nsecs_t topStartNs = 0;
    nsecs_t latestStartNs = 0;
    nsecs_t latestSensitiveStartNs = 0;
    bool isA11yOnTop = mUidPolicy->isA11yOnTop();
    bool isAssistantOnTop = false;
    bool isSensitiveActive = false;
    bool isInCall = mPhoneState == AUDIO_MODE_IN_CALL;

    // if Sensor Privacy is enabled then all recordings should be silenced.
    if (mSensorPrivacyPolicy->isSensorPrivacyEnabled()) {
@@ -449,15 +452,18 @@ void AudioPolicyService::updateUidStates_l()

    for (size_t i =0; i < mAudioRecordClients.size(); i++) {
        sp<AudioRecordClient> current = mAudioRecordClients[i];
        if (!current->active) continue;
        if (isPrivacySensitiveSource(current->attributes.source)) {
            if (current->startTimeNs > latestSensitiveStartNs) {
                latestSensitiveActive = current;
                latestSensitiveStartNs = current->startTimeNs;
        if (!current->active) {
            continue;
        }
            isSensitiveActive = true;

        app_state_t appState = apmStatFromAmState(mUidPolicy->getUidState(current->uid));
        // clients which app is in IDLE state are not eligible for top active or
        // latest active
        if (appState == APP_STATE_IDLE) {
            continue;
        }
        if (mUidPolicy->getUidState(current->uid) == ActivityManager::PROCESS_STATE_TOP) {

        if (appState == APP_STATE_TOP) {
            if (current->startTimeNs > topStartNs) {
                topActive = current;
                topStartNs = current->startTimeNs;
@@ -470,72 +476,105 @@ void AudioPolicyService::updateUidStates_l()
            latestActive = current;
            latestStartNs = current->startTimeNs;
        }
        if (isPrivacySensitiveSource(current->attributes.source)) {
            if (current->startTimeNs > latestSensitiveStartNs) {
                latestSensitiveActive = current;
                latestSensitiveStartNs = current->startTimeNs;
            }
            isSensitiveActive = true;
        }

    if (topActive == nullptr && latestActive == nullptr) {
        return;
    }

    if (topActive != nullptr) {
        latestActive = nullptr;
    // if no active client with UI on Top, consider latest active as top
    if (topActive == nullptr) {
        topActive = latestActive;
    }

    std::vector<uid_t> enabledUids;

    for (size_t i =0; i < mAudioRecordClients.size(); i++) {
        sp<AudioRecordClient> current = mAudioRecordClients[i];
        if (!current->active) continue;
        if (!current->active) {
            continue;
        }

        // keep capture allowed if another client with the same UID has already
        // been allowed to capture
        if (std::find(enabledUids.begin(), enabledUids.end(), current->uid)
                != enabledUids.end()) {
            continue;
        }

        audio_source_t source = current->attributes.source;
        bool isOnTop = current == topActive;
        bool isLatest = current == latestActive;
        bool isLatestSensitive = current == latestSensitiveActive;
        bool forceIdle = true;
        bool isTopOrLatestActive = topActive == nullptr ? false : current->uid == topActive->uid;
        bool isLatestSensitive = latestSensitiveActive == nullptr ?
                                 false : current->uid == latestSensitiveActive->uid;

        // By default allow capture if:
        //     The assistant is not on TOP
        //     AND there is no active privacy sensitive capture or call
        //             OR client has CAPTURE_AUDIO_OUTPUT privileged permission
        bool allowCapture = !isAssistantOnTop
                && !(isSensitiveActive && !(isLatestSensitive || current->canCaptureOutput))
                && !(isInCall && !current->canCaptureOutput);

        if (isVirtualSource(source)) {
            forceIdle = false;
            // Allow capture for virtual (remote submix, call audio TX or RX...) sources
            allowCapture = true;
        } else if (mUidPolicy->isAssistantUid(current->uid)) {
            // For assistant allow capture if:
            //     An accessibility service is on TOP
            //            AND the source is VOICE_RECOGNITION or HOTWORD
            //     OR is on TOP OR latest started AND uses VOICE_RECOGNITION
            //            OR uses HOTWORD
            //         AND there is no active privacy sensitive capture or call
            //             OR client has CAPTURE_AUDIO_OUTPUT privileged permission
            if (isA11yOnTop) {
                if (source == AUDIO_SOURCE_HOTWORD || source == AUDIO_SOURCE_VOICE_RECOGNITION) {
                    forceIdle = false;
                    allowCapture = true;
                }
            } else {
                if ((((isOnTop || isLatest) && source == AUDIO_SOURCE_VOICE_RECOGNITION) ||
                     source == AUDIO_SOURCE_HOTWORD) && !isSensitiveActive) {
                    forceIdle = false;
                if (((isTopOrLatestActive && source == AUDIO_SOURCE_VOICE_RECOGNITION) ||
                        source == AUDIO_SOURCE_HOTWORD) &&
                        (!(isSensitiveActive || isInCall) || current->canCaptureOutput)) {
                    allowCapture = true;
                }
            }
        } else if (mUidPolicy->isA11yUid(current->uid)) {
            if ((isOnTop || isLatest) &&
            // For accessibility service allow capture if:
            //     Is on TOP OR latest started
            //     AND the source is VOICE_RECOGNITION or HOTWORD
            if (isTopOrLatestActive &&
                    (source == AUDIO_SOURCE_VOICE_RECOGNITION || source == AUDIO_SOURCE_HOTWORD)) {
                forceIdle = false;
            }
        } else {
            if (!isAssistantOnTop && (isOnTop || isLatest) &&
                (!isSensitiveActive || isLatestSensitive)) {
                forceIdle = false;
                allowCapture = true;
            }
        }
        setAppState_l(current->uid,
                      forceIdle ? APP_STATE_IDLE :
                                  apmStatFromAmState(mUidPolicy->getUidState(current->uid)));
                      allowCapture ? apmStatFromAmState(mUidPolicy->getUidState(current->uid)) :
                                APP_STATE_IDLE);
        if (allowCapture) {
            enabledUids.push_back(current->uid);
        }
    }
}

void AudioPolicyService::silenceAllRecordings_l() {
    for (size_t i = 0; i < mAudioRecordClients.size(); i++) {
        sp<AudioRecordClient> current = mAudioRecordClients[i];
        if (!isVirtualSource(current->attributes.source)) {
            setAppState_l(current->uid, APP_STATE_IDLE);
        }
    }
}

/* static */
app_state_t AudioPolicyService::apmStatFromAmState(int amState) {
    switch (amState) {
    case ActivityManager::PROCESS_STATE_UNKNOWN:

    if (amState == ActivityManager::PROCESS_STATE_UNKNOWN) {
        return APP_STATE_IDLE;
    case ActivityManager::PROCESS_STATE_TOP:
    } else if (amState <= ActivityManager::PROCESS_STATE_TOP) {
      // include persistent services
      return APP_STATE_TOP;
    default:
        break;
    }
    return APP_STATE_FOREGROUND;
}
+6 −2
Original line number Diff line number Diff line
@@ -753,13 +753,17 @@ private:
                AudioRecordClient(const audio_attributes_t attributes,
                          const audio_io_handle_t io, uid_t uid, pid_t pid,
                          const audio_session_t session, const audio_port_handle_t deviceId,
                          const String16& opPackageName) :
                          const String16& opPackageName,
                          bool canCaptureOutput, bool canCaptureHotword) :
                    AudioClient(attributes, io, uid, pid, session, deviceId),
                    opPackageName(opPackageName), startTimeNs(0) {}
                    opPackageName(opPackageName), startTimeNs(0),
                    canCaptureOutput(canCaptureOutput), canCaptureHotword(canCaptureHotword) {}
                ~AudioRecordClient() override = default;

        const String16 opPackageName;        // client package name
        nsecs_t startTimeNs;
        const bool canCaptureOutput;
        const bool canCaptureHotword;
    };

    // --- AudioPlaybackClient ---