Allow call audio access for default dialer application
The access to call audio (record and play) will be granted only to the app associated with Dialer role, who also includes a new system permission.
Test: Compilation and manual tests
Bug: 135197853
Change-Id: I65ca823c235d4d3420630837427103783ad1d1b0
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 152883b..2f67a18 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -879,6 +879,7 @@
audio_stream_type_t *stream,
pid_t pid,
uid_t uid,
+ const String16& opPackageName,
const audio_config_t *config,
audio_output_flags_t flags,
audio_port_handle_t *selectedDeviceId,
@@ -888,7 +889,7 @@
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return NO_INIT;
return aps->getOutputForAttr(attr, output, session, stream, pid, uid,
- config,
+ opPackageName, config,
flags, selectedDeviceId, portId, secondaryOutputs);
}
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index 5b3a057..cccb131 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -214,6 +214,7 @@
audio_stream_type_t *stream,
pid_t pid,
uid_t uid,
+ const String16& opPackageName,
const audio_config_t *config,
audio_output_flags_t flags,
audio_port_handle_t *selectedDeviceId,
@@ -252,6 +253,7 @@
}
data.writeInt32(pid);
data.writeInt32(uid);
+ data.writeString16(opPackageName);
data.write(config, sizeof(audio_config_t));
data.writeInt32(static_cast <uint32_t>(flags));
data.writeInt32(*selectedDeviceId);
@@ -1645,6 +1647,11 @@
}
pid_t pid = (pid_t)data.readInt32();
uid_t uid = (uid_t)data.readInt32();
+ String16 opPackageName;
+ status = data.readString16(&opPackageName);
+ if (status != NO_ERROR) {
+ return status;
+ }
audio_config_t config;
memset(&config, 0, sizeof(audio_config_t));
data.read(&config, sizeof(audio_config_t));
@@ -1656,7 +1663,7 @@
std::vector<audio_io_handle_t> secondaryOutputs;
status = getOutputForAttr(&attr,
&output, session, &stream, pid, uid,
- &config,
+ opPackageName, &config,
flags, &selectedDeviceId, &portId, &secondaryOutputs);
reply->writeInt32(status);
status = reply->write(&attr, sizeof(audio_attributes_t));
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index fe211e0..07a2292 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -240,6 +240,7 @@
audio_stream_type_t *stream,
pid_t pid,
uid_t uid,
+ const String16& opPackageName,
const audio_config_t *config,
audio_output_flags_t flags,
audio_port_handle_t *selectedDeviceId,
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 8bc1d83..8658cfa 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -70,6 +70,7 @@
if (clientInfo.readFromParcel(parcel) != NO_ERROR) {
return DEAD_OBJECT;
}
+ opPackageName = parcel->readString16();
if (parcel->readInt32() != 0) {
// TODO: Using unsecurePointer() has some associated security
// pitfalls (see declaration for details).
@@ -97,6 +98,7 @@
(void)parcel->write(&attr, sizeof(audio_attributes_t));
(void)parcel->write(&config, sizeof(audio_config_t));
(void)clientInfo.writeToParcel(parcel);
+ (void)parcel->writeString16(opPackageName);
if (sharedBuffer != 0) {
(void)parcel->writeInt32(1);
(void)parcel->writeStrongBinder(IInterface::asBinder(sharedBuffer));
@@ -119,6 +121,7 @@
audio_attributes_t attr;
audio_config_t config;
AudioClient clientInfo;
+ String16 opPackageName;
sp<IMemory> sharedBuffer;
uint32_t notificationsPerBuffer;
float speed;
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index fe54dc5..779ca43 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -64,6 +64,7 @@
audio_stream_type_t *stream,
pid_t pid,
uid_t uid,
+ const String16& opPackageName,
const audio_config_t *config,
audio_output_flags_t flags,
audio_port_handle_t *selectedDeviceId,
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 87ea084..7fd4d0a 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -223,6 +223,25 @@
return ok;
}
+bool accessCallAudioAllowed(const String16& opPackageName, pid_t pid, uid_t uid) {
+ static const String16 sAccessCallAudio("android.permission.ACCESS_CALL_AUDIO");
+ PermissionController permissionController;
+ const String16 resolvedOpPackageName = resolveCallingPackage(
+ permissionController, opPackageName, uid);
+ if (resolvedOpPackageName.size() == 0) {
+ ALOGE("accessCallAudioAllowed - FAIL - package not found.");
+ return false;
+ }
+ AppOpsManager appOps;
+ const int32_t op = appOps.permissionToOpCode(sAccessCallAudio);
+ const int32_t opResult = appOps.noteOp(op, uid, resolvedOpPackageName);
+ if (opResult == PermissionController::MODE_DEFAULT) {
+ // Only allow in case this is a system app with the proper privilege permission
+ return PermissionCache::checkPermission(sAccessCallAudio, pid, uid);
+ }
+ return opResult == PermissionController::MODE_ALLOWED;
+}
+
// privileged behavior needed by Dialer, Settings, SetupWizard and CellBroadcastReceiver
bool bypassInterruptionPolicyAllowed(pid_t pid, uid_t uid) {
static const String16 sWriteSecureSettings("android.permission.WRITE_SECURE_SETTINGS");
@@ -259,28 +278,29 @@
return NO_ERROR;
}
-sp<content::pm::IPackageManagerNative> MediaPackageManager::retreivePackageManager() {
+void MediaPackageManager::loadPackageManager() {
+ if (mPackageManager != nullptr) {
+ return;
+ }
const sp<IServiceManager> sm = defaultServiceManager();
if (sm == nullptr) {
ALOGW("%s: failed to retrieve defaultServiceManager", __func__);
- return nullptr;
+ return;
}
sp<IBinder> packageManager = sm->checkService(String16(nativePackageManagerName));
if (packageManager == nullptr) {
ALOGW("%s: failed to retrieve native package manager", __func__);
- return nullptr;
+ return;
}
- return interface_cast<content::pm::IPackageManagerNative>(packageManager);
+ mPackageManager = interface_cast<content::pm::IPackageManagerNative>(packageManager);
}
std::optional<bool> MediaPackageManager::doIsAllowed(uid_t uid) {
+ /** Can not fetch package manager at construction it may not yet be registered. */
+ loadPackageManager();
if (mPackageManager == nullptr) {
- /** Can not fetch package manager at construction it may not yet be registered. */
- mPackageManager = retreivePackageManager();
- if (mPackageManager == nullptr) {
- ALOGW("%s: Playback capture is denied as package manager is not reachable", __func__);
- return std::nullopt;
- }
+ ALOGW("%s: Playback capture is denied as package manager is not reachable", __func__);
+ return std::nullopt;
}
std::vector<std::string> packageNames;
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index 212599a..060e849 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -93,6 +93,7 @@
bool dumpAllowed();
bool modifyPhoneStateAllowed(pid_t pid, uid_t uid);
bool bypassInterruptionPolicyAllowed(pid_t pid, uid_t uid);
+bool accessCallAudioAllowed(const String16& opPackageName, pid_t pid, uid_t uid);
status_t checkIMemory(const sp<IMemory>& iMemory);
@@ -110,7 +111,7 @@
private:
static constexpr const char* nativePackageManagerName = "package_native";
std::optional<bool> doIsAllowed(uid_t uid);
- sp<content::pm::IPackageManagerNative> retreivePackageManager();
+ void loadPackageManager();
sp<content::pm::IPackageManagerNative> mPackageManager; // To check apps manifest
uint_t mPackageManagerErrors = 0;
struct Package {
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 5c5c5bb..e5a6e27 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -326,7 +326,7 @@
ret = AudioSystem::getOutputForAttr(&localAttr, &io,
actualSessionId,
&streamType, client.clientPid, client.clientUid,
- &fullConfig,
+ client.packageName, &fullConfig,
(audio_output_flags_t)(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ |
AUDIO_OUTPUT_FLAG_DIRECT),
deviceId, &portId, &secondaryOutputs);
@@ -766,8 +766,9 @@
output.outputId = AUDIO_IO_HANDLE_NONE;
output.selectedDeviceId = input.selectedDeviceId;
lStatus = AudioSystem::getOutputForAttr(&localAttr, &output.outputId, sessionId, &streamType,
- clientPid, clientUid, &input.config, input.flags,
- &output.selectedDeviceId, &portId, &secondaryOutputs);
+ clientPid, clientUid, input.opPackageName,
+ &input.config, input.flags, &output.selectedDeviceId,
+ &portId, &secondaryOutputs);
if (lStatus != NO_ERROR || output.outputId == AUDIO_IO_HANDLE_NONE) {
ALOGE("createTrack() getOutputForAttr() return error %d or invalid output handle", lStatus);
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 6ef2035..2833525 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -8731,6 +8731,7 @@
&stream,
client.clientPid,
client.clientUid,
+ client.packageName,
&config,
flags,
&deviceId,
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 4d071c8..38801ec 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -211,6 +211,7 @@
audio_stream_type_t *stream,
pid_t pid,
uid_t uid,
+ const String16& opPackageName,
const audio_config_t *config,
audio_output_flags_t flags,
audio_port_handle_t *selectedDeviceId,
@@ -257,7 +258,8 @@
case AudioPolicyInterface::API_OUTPUT_LEGACY:
break;
case AudioPolicyInterface::API_OUTPUT_TELEPHONY_TX:
- if (!modifyPhoneStateAllowed(pid, uid)) {
+ if (!modifyPhoneStateAllowed(pid, uid) &&
+ !accessCallAudioAllowed(opPackageName, pid, uid)) {
ALOGE("%s() permission denied: modify phone state not allowed for uid %d",
__func__, uid);
result = PERMISSION_DENIED;
@@ -454,15 +456,22 @@
}
bool canCaptureOutput = captureAudioOutputAllowed(pid, uid);
- if ((inputSource == AUDIO_SOURCE_VOICE_UPLINK ||
- inputSource == AUDIO_SOURCE_VOICE_DOWNLINK ||
- inputSource == AUDIO_SOURCE_VOICE_CALL ||
- inputSource == AUDIO_SOURCE_ECHO_REFERENCE||
- inputSource == AUDIO_SOURCE_FM_TUNER) &&
+ bool canCaptureTelephonyOutput = canCaptureOutput
+ || accessCallAudioAllowed(opPackageName, pid, uid);
+
+ if ((attr->source == AUDIO_SOURCE_ECHO_REFERENCE ||
+ attr->source == AUDIO_SOURCE_FM_TUNER) &&
!canCaptureOutput) {
return PERMISSION_DENIED;
}
+ if ((attr->source == AUDIO_SOURCE_VOICE_UPLINK ||
+ attr->source == AUDIO_SOURCE_VOICE_DOWNLINK ||
+ attr->source == AUDIO_SOURCE_VOICE_CALL) &&
+ !canCaptureTelephonyOutput) {
+ return PERMISSION_DENIED;
+ }
+
bool canCaptureHotword = captureHotwordAllowed(opPackageName, pid, uid);
if ((inputSource == AUDIO_SOURCE_HOTWORD) && !canCaptureHotword) {
return BAD_VALUE;
@@ -494,6 +503,11 @@
break;
case AudioPolicyInterface::API_INPUT_TELEPHONY_RX:
// FIXME: use the same permission as for remote submix for now.
+ if (!canCaptureTelephonyOutput) {
+ ALOGE("getInputForAttr() permission denied: call capture not allowed");
+ status = PERMISSION_DENIED;
+ }
+ break;
case AudioPolicyInterface::API_INPUT_MIX_CAPTURE:
if (!canCaptureOutput) {
ALOGE("getInputForAttr() permission denied: capture not allowed");
@@ -521,9 +535,13 @@
return status;
}
+ bool allowAudioCapture = canCaptureOutput ||
+ (inputType == AudioPolicyInterface::API_INPUT_TELEPHONY_RX &&
+ canCaptureTelephonyOutput);
+
sp<AudioRecordClient> client = new AudioRecordClient(*attr, *input, uid, pid, session, *portId,
*selectedDeviceId, opPackageName,
- canCaptureOutput, canCaptureHotword);
+ allowAudioCapture, canCaptureHotword);
mAudioRecordClients.add(*portId, client);
}
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index e5c36ea..99cec5a 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -534,8 +534,8 @@
// OR client has CAPTURE_AUDIO_OUTPUT privileged permission
bool allowCapture = !isAssistantOnTop
&& ((isTopOrLatestActive && !isLatestSensitive) || isLatestSensitive)
- && !(isSensitiveActive && !(isLatestSensitive || current->canCaptureOutput))
- && !(isInCall && !current->canCaptureOutput);
+ && !(isSensitiveActive && !(isLatestSensitive || current->canCaptureCallOrOutput))
+ && !(isInCall && !current->canCaptureCallOrOutput);
if (isVirtualSource(source)) {
// Allow capture for virtual (remote submix, call audio TX or RX...) sources
@@ -555,7 +555,7 @@
} else {
if (((isAssistantOnTop && source == AUDIO_SOURCE_VOICE_RECOGNITION) ||
source == AUDIO_SOURCE_HOTWORD) &&
- (!(isSensitiveActive || isInCall) || current->canCaptureOutput)) {
+ (!(isSensitiveActive || isInCall) || current->canCaptureCallOrOutput)) {
allowCapture = true;
}
}
@@ -567,7 +567,7 @@
// OR
// Is on TOP AND the source is VOICE_RECOGNITION or HOTWORD
if (!isAssistantOnTop
- && (!(isSensitiveActive || isInCall) || current->canCaptureOutput)) {
+ && (!(isSensitiveActive || isInCall) || current->canCaptureCallOrOutput)) {
allowCapture = true;
}
if (isA11yOnTop) {
@@ -580,7 +580,7 @@
// 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)) {
+ if (onlyHotwordActive && !(isInCall && !current->canCaptureCallOrOutput)) {
allowCapture = true;
}
}
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 41a0d2b..c3c87f1 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -82,6 +82,7 @@
audio_stream_type_t *stream,
pid_t pid,
uid_t uid,
+ const String16& opPackageName,
const audio_config_t *config,
audio_output_flags_t flags,
audio_port_handle_t *selectedDeviceId,
@@ -807,15 +808,16 @@
const audio_io_handle_t io, uid_t uid, pid_t pid,
const audio_session_t session, audio_port_handle_t portId,
const audio_port_handle_t deviceId, const String16& opPackageName,
- bool canCaptureOutput, bool canCaptureHotword) :
+ bool canCaptureCallOrOutput, bool canCaptureHotword) :
AudioClient(attributes, io, uid, pid, session, portId, deviceId),
opPackageName(opPackageName), startTimeNs(0),
- canCaptureOutput(canCaptureOutput), canCaptureHotword(canCaptureHotword) {}
+ canCaptureCallOrOutput(canCaptureCallOrOutput),
+ canCaptureHotword(canCaptureHotword) {}
~AudioRecordClient() override = default;
const String16 opPackageName; // client package name
nsecs_t startTimeNs;
- const bool canCaptureOutput;
+ const bool canCaptureCallOrOutput;
const bool canCaptureHotword;
};