Fix audio AppOps refcount mismatch
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.
Test: atest AudioRecordPermissionTest.java
Bug: 293603271
Flag: EXEMPT security
Change-Id: Iea630bb2bf1b54697ab6a95ee9f65db5cc4d134a
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index bb41d00..3932a39 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -86,6 +86,10 @@
using media::audio::common::Int;
constexpr int kDefaultVirtualDeviceId = 0;
+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,
@@ -900,13 +904,13 @@
std::stringstream msg;
msg << "Audio recording on session " << client->session;
+ const auto permitted = startRecording(client->attributionSource, client->virtualDeviceId,
+ String16(msg.str().c_str()), client->attributes.source);
// check calling permissions
- if (!(startRecording(client->attributionSource, client->virtualDeviceId,
- 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 && client->attributes.source != AUDIO_SOURCE_FM_TUNER
+ && client->attributes.source != AUDIO_SOURCE_REMOTE_SUBMIX
+ && client->attributes.source != AUDIO_SOURCE_ECHO_REFERENCE) {
ALOGE("%s permission denied: recording not allowed for attribution source %s",
__func__, client->attributionSource.toString().c_str());
return binderStatusFromStatusT(PERMISSION_DENIED);
@@ -926,13 +930,17 @@
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();
@@ -1018,8 +1026,10 @@
client->active = false;
client->startTimeNs = 0;
updateUidStates_l();
- finishRecording(client->attributionSource, client->virtualDeviceId,
- client->attributes.source);
+ if (!client->silenced) {
+ finishRecording(client->attributionSource, client->virtualDeviceId,
+ client->attributes.source);
+ }
}
return binderStatusFromStatusT(status);
@@ -1048,7 +1058,11 @@
updateUidStates_l();
// finish the recording app op
- finishRecording(client->attributionSource, client->virtualDeviceId, client->attributes.source);
+ if (!client->silenced) {
+ finishRecording(client->attributionSource, client->virtualDeviceId,
+ client->attributes.source);
+ }
+
AutoCallerClear acc;
return binderStatusFromStatusT(mAudioPolicyManager->stopInput(portId));
}