summaryrefslogtreecommitdiff
path: root/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
diff options
context:
space:
mode:
authorAtneya Nair <atneya@google.com>2025-06-30 17:08:22 -0700
committeraoleary <seanm187@gmail.com>2025-10-07 18:44:08 +0000
commitd4d87d930bfbc5c7a00ed5f7a2649f8b838673a8 (patch)
treeeef2f14546ccf8ce19a0e573477c80563f924fb2 /services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
parente385f5a69f5d3a87d14149bd840894e9247aee9b (diff)
[RESTRICT AUTOMERGE] Fix audio AppOps refcount mismatchHEADt13.0
Iea630bb2bf1b54697ab6a95ee9f65db5cc4d134a I8a3498a08a31543219279cb063c043fd0c767cd7 The state of the appop corresponding to a recording must be consistent with the APS notion of whether a recording is silenced. Ensure that when we start recording, we only un-silence the track if the op is allowed from the appop side. This requires plumbing the exact perm state through the startRecording API. Correctly handle virtual sources by checking only their associated op state, rather than OP_RECORD. Update the appop callback listening/handling as well, by only listening/evaluating OP_RECORD for relevant sources. Ie7d2661b4027b5ce6bee9b6c63b70f0b120dcbcc When AppOp restrictions are in place, starting an op will return SOFT_DENY, but leave the op in a paused state, which can restart unexpectedly when the restriction is removed (despite no data delivery occurring). Work around this by first checking if recording is restricted, and avoiding the start call in that case. Instead, use a note call in order to maintain a rejected op for listeners (for prompting the mic unblock dialogue). Idd4389e7e79ee819c29ec2676d2e22d5a4b12249 Un-require RECORD_OP for VOICE_DOWNLINK Ibc735ea463aa6e09f8a24fc3cb50c39b70bbbea8 Handle targetSdk failures for recording Test: atest CtsMediaAudioPermissionTestCases Test: atest CtsMediaAudioTestCases Test: atest RuntimePermissionsAppOpTrackingTest Test: atest SensorPrivacyMicrophoneTest Test: atest AppOpsControllerTest Test: atest AudioPlaybackCaptureTest with mic blocked Test: sts-tradefed run sts-dynamic-develop -m \ CtsMediaAudioPermissionTestCases Test: manual oboetester app recording in background silenced Test: manual recorder with mic toggle disabled no indicator Test: manual poc Bug: 293603271 Flag: EXEMPT security (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:e5c79cfb8ea5c8446d5a146203e9a716067fb61d) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:3f73604fba84d1870864de76685412f8cf0c0560) Merged-In: Iea630bb2bf1b54697ab6a95ee9f65db5cc4d134a Change-Id: Iea630bb2bf1b54697ab6a95ee9f65db5cc4d134a
Diffstat (limited to 'services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp')
-rw-r--r--services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp40
1 files changed, 26 insertions, 14 deletions
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 3ba55f350a..5d4f6e78e4 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -62,6 +62,11 @@ using media::audio::common::AudioUsage;
using media::audio::common::AudioUuid;
using media::audio::common::Int;
+namespace {
+constexpr auto PERMISSION_HARD_DENIED = permission::PermissionChecker::PERMISSION_HARD_DENIED;
+constexpr auto PERMISSION_GRANTED = permission::PermissionChecker::PERMISSION_GRANTED;
+}
+
const std::vector<audio_usage_t>& SYSTEM_USAGES = {
AUDIO_USAGE_CALL_ASSISTANT,
AUDIO_USAGE_EMERGENCY,
@@ -782,13 +787,12 @@ Status AudioPolicyService::startInput(int32_t portIdAidl)
std::stringstream msg;
msg << "Audio recording on session " << client->session;
+ const auto permitted = isAudioServerOrMediaServerUid(client->attributionSource.uid) &&
+ startRecording(client->attributionSource, String16(msg.str().c_str()),
+ client->attributes.source);
+
// check calling permissions
- if (!isAudioServerOrMediaServerUid(client->attributionSource.uid)
- && !(startRecording(client->attributionSource, String16(msg.str().c_str()),
- client->attributes.source)
- || client->attributes.source == AUDIO_SOURCE_FM_TUNER
- || client->attributes.source == AUDIO_SOURCE_REMOTE_SUBMIX
- || client->attributes.source == AUDIO_SOURCE_ECHO_REFERENCE)) {
+ if (permitted == PERMISSION_HARD_DENIED) {
ALOGE("%s permission denied: recording not allowed for attribution source %s",
__func__, client->attributionSource.toString().c_str());
return binderStatusFromStatusT(PERMISSION_DENIED);
@@ -807,13 +811,17 @@ Status AudioPolicyService::startInput(int32_t portIdAidl)
return binderStatusFromStatusT(INVALID_OPERATION);
}
- // Force the possibly silenced client to be unsilenced since we just called
- // startRecording (i.e. we have assumed it is unsilenced).
- // At this point in time, the client is inactive, so no calls to appops are sent in
- // setAppState_l.
- // This ensures existing clients have the same behavior as new clients (starting unsilenced).
+ // Force the possibly silenced client to match the state on the appops side
+ // following the call to startRecording (i.e. unsilenced iff call succeeded)
+ // At this point in time, the client is inactive, so no calls to appops are
+ // sent in setAppState_l. This ensures existing clients have the same
+ // behavior as new clients.
// TODO(b/282076713)
- setAppState_l(client, APP_STATE_TOP);
+ if (permitted == PERMISSION_GRANTED) {
+ setAppState_l(client, APP_STATE_TOP);
+ } else {
+ setAppState_l(client, APP_STATE_IDLE);
+ }
client->active = true;
client->startTimeNs = systemTime();
@@ -899,7 +907,9 @@ Status AudioPolicyService::startInput(int32_t portIdAidl)
client->active = false;
client->startTimeNs = 0;
updateUidStates_l();
- finishRecording(client->attributionSource, client->attributes.source);
+ if (!client->silenced) {
+ finishRecording(client->attributionSource, client->attributes.source);
+ }
}
return binderStatusFromStatusT(status);
@@ -928,7 +938,9 @@ Status AudioPolicyService::stopInput(int32_t portIdAidl)
updateUidStates_l();
// finish the recording app op
- finishRecording(client->attributionSource, client->attributes.source);
+ if (!client->silenced) {
+ finishRecording(client->attributionSource, client->attributes.source);
+ }
AutoCallerClear acc;
return binderStatusFromStatusT(mAudioPolicyManager->stopInput(portId));
}