audio policy: update capture policy for HOTWORD source
Restore pre Q behavior for HOTWORD capture for non
Assistant applications. This allows non Assistant privileged
applications to capture audio with source HOTWORD and no visible
foreground UI as long as no other app is capturing. This capture
will be silenced as soon as another app starts capturing and will not
prevent other apps from capturing.
Bug: 140799148
Test: manual OK Google and Now Playing tests
Test: CTS AudioRecordTest, GTS HotwordTest
Change-Id: I9473851e2949e42abc02fb5974be21d351810854
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 7dfc205..2319838 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -422,12 +422,18 @@
// AND is on TOP
// AND the source is VOICE_RECOGNITION or HOTWORD
// OR the client source is virtual (remote submix, call audio TX or RX...)
+// OR the client source is HOTWORD
+// AND is on TOP
+// OR all active clients are using HOTWORD source
+// AND no call is active
+// OR client has CAPTURE_AUDIO_OUTPUT privileged permission
// OR Any client
// AND The assistant is not on TOP
// AND is on TOP or latest started
// AND there is no active privacy sensitive capture or call
// OR client has CAPTURE_AUDIO_OUTPUT privileged permission
+
sp<AudioRecordClient> topActive;
sp<AudioRecordClient> latestActive;
sp<AudioRecordClient> latestSensitiveActive;
@@ -442,6 +448,7 @@
bool rttCallActive =
(mPhoneState == AUDIO_MODE_IN_CALL || mPhoneState == AUDIO_MODE_IN_COMMUNICATION)
&& mUidPolicy->isRttEnabled();
+ bool onlyHotwordActive = true;
// if Sensor Privacy is enabled then all recordings should be silenced.
if (mSensorPrivacyPolicy->isSensorPrivacyEnabled()) {
@@ -473,12 +480,11 @@
isAssistantOnTop = true;
}
}
- // Assistant capturing for HOTWORD or Accessibility services not considered
+ // Client capturing for HOTWORD or Accessibility services 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)
+ && !(current->attributes.source == AUDIO_SOURCE_HOTWORD
+ || ((isA11yOnTop || rttCallActive) && isAssistant))
&& !isAccessibility) {
latestActive = current;
latestStartNs = current->startTimeNs;
@@ -490,6 +496,9 @@
}
isSensitiveActive = true;
}
+ if (current->attributes.source != AUDIO_SOURCE_HOTWORD) {
+ onlyHotwordActive = false;
+ }
}
// if no active client with UI on Top, consider latest active as top
@@ -556,6 +565,14 @@
allowCapture = true;
}
}
+ } else if (source == AUDIO_SOURCE_HOTWORD) {
+ // For HOTWORD source allow capture when not on TOP if:
+ // All active clients are using HOTWORD source
+ // AND no call is active
+ // OR client has CAPTURE_AUDIO_OUTPUT privileged permission
+ if (onlyHotwordActive && !(isInCall && !current->canCaptureOutput)) {
+ allowCapture = true;
+ }
}
setAppState_l(current->portId,
allowCapture ? apmStatFromAmState(mUidPolicy->getUidState(current->uid)) :