Loading services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp +7 −4 Original line number Diff line number Diff line Loading @@ -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; } Loading Loading @@ -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; } Loading @@ -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); } Loading services/audiopolicy/service/AudioPolicyService.cpp +85 −46 Original line number Diff line number Diff line Loading @@ -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()) { Loading @@ -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; Loading @@ -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; } Loading services/audiopolicy/service/AudioPolicyService.h +6 −2 Original line number Diff line number Diff line Loading @@ -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 --- Loading Loading
services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp +7 −4 Original line number Diff line number Diff line Loading @@ -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; } Loading Loading @@ -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; } Loading @@ -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); } Loading
services/audiopolicy/service/AudioPolicyService.cpp +85 −46 Original line number Diff line number Diff line Loading @@ -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()) { Loading @@ -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; Loading @@ -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; } Loading
services/audiopolicy/service/AudioPolicyService.h +6 −2 Original line number Diff line number Diff line Loading @@ -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 --- Loading