Audio policy: modify permission needed to capture from source FM_TUNER

Capturing from source AUDIO_SOURCE_FM_TUNER is possible only via @SystemApi
on one end and does not capture from an actual on the other end.
Accordingly, do not check android.permission.RECORD_AUDIO anymore but
check privileged permission android.permission.CAPTURE_AUDIO_OUTPUT instead.
Also bypass App Ops OP_RECORD_AUDIO check which is applicable only to capture from
microphones.

Also fix audio recording permission check in MediaRecordClient to use
recordingAllowed() from ServiceUtilities

Bug: 135717621
Test: CTS tests for AudioRecord
Change-Id: Ibb1d72f018d2e3ceee195338f2e262183eee2a23
gugelfrei
Eric Laurent 5 years ago
parent 9f03917ce0
commit 58a0dd8321

@ -32,6 +32,7 @@
#include <cutils/atomic.h>
#include <cutils/properties.h> // for property_get
#include <gui/IGraphicBufferProducer.h>
#include <mediautils/ServiceUtilities.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <system/audio.h>
@ -44,7 +45,6 @@
namespace android {
const char* cameraPermission = "android.permission.CAMERA";
const char* recordAudioPermission = "android.permission.RECORD_AUDIO";
static bool checkPermission(const char* permissionString) {
if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
@ -118,7 +118,16 @@ status_t MediaRecorderClient::setVideoSource(int vs)
status_t MediaRecorderClient::setAudioSource(int as)
{
ALOGV("setAudioSource(%d)", as);
if (!checkPermission(recordAudioPermission)) {
if (as < AUDIO_SOURCE_DEFAULT
|| (as >= AUDIO_SOURCE_CNT && as != AUDIO_SOURCE_FM_TUNER)) {
ALOGE("Invalid audio source: %d", as);
return BAD_VALUE;
}
pid_t pid = IPCThreadState::self()->getCallingPid();
uid_t uid = IPCThreadState::self()->getCallingUid();
if ((as == AUDIO_SOURCE_FM_TUNER && !captureAudioOutputAllowed(pid, uid))
|| !recordingAllowed(String16(""), pid, uid)) {
return PERMISSION_DENIED;
}
Mutex::Autolock lock(mLock);

@ -232,11 +232,6 @@ sp<IGraphicBufferProducer> StagefrightRecorder::querySurfaceMediaSource() const
status_t StagefrightRecorder::setAudioSource(audio_source_t as) {
ALOGV("setAudioSource: %d", as);
if (as < AUDIO_SOURCE_DEFAULT ||
(as >= AUDIO_SOURCE_CNT && as != AUDIO_SOURCE_FM_TUNER)) {
ALOGE("Invalid audio source: %d", as);
return BAD_VALUE;
}
if (as == AUDIO_SOURCE_DEFAULT) {
mAudioSource = AUDIO_SOURCE_MIC;

@ -61,12 +61,12 @@ static String16 resolveCallingPackage(PermissionController& permissionController
static bool checkRecordingInternal(const String16& opPackageName, pid_t pid,
uid_t uid, bool start) {
// Okay to not track in app ops as audio server is us and if
// Okay to not track in app ops as audio server or media server is us and if
// device is rooted security model is considered compromised.
// system_server loses its RECORD_AUDIO permission when a secondary
// user is active, but it is a core system service so let it through.
// TODO(b/141210120): UserManager.DISALLOW_RECORD_AUDIO should not affect system user 0
if (isAudioServerOrSystemServerOrRootUid(uid)) return true;
if (isAudioServerOrMediaServerOrSystemServerOrRootUid(uid)) return true;
// We specify a pid and uid here as mediaserver (aka MediaRecorder or StageFrightRecorder)
// may open a record track on behalf of a client. Note that pid may be a tid.

@ -58,10 +58,11 @@ static inline bool isAudioServerOrSystemServerUid(uid_t uid) {
return multiuser_get_app_id(uid) == AID_SYSTEM || uid == AID_AUDIOSERVER;
}
// used for calls that should come from system_server or audio_server and
// used for calls that should come from system_server or audio_server or media server and
// include AID_ROOT for command-line tests.
static inline bool isAudioServerOrSystemServerOrRootUid(uid_t uid) {
return multiuser_get_app_id(uid) == AID_SYSTEM || uid == AID_AUDIOSERVER || uid == AID_ROOT;
static inline bool isAudioServerOrMediaServerOrSystemServerOrRootUid(uid_t uid) {
return multiuser_get_app_id(uid) == AID_SYSTEM || uid == AID_AUDIOSERVER
|| uid == AID_MEDIA || uid == AID_ROOT;
}
// Mediaserver may forward the client PID and UID as part of a binder interface call;

@ -25,7 +25,8 @@ public:
~OpRecordAudioMonitor() override;
bool hasOpRecordAudio() const;
static sp<OpRecordAudioMonitor> createIfNeeded(uid_t uid, const String16& opPackageName);
static sp<OpRecordAudioMonitor> createIfNeeded
(uid_t uid, const audio_attributes_t& attr, const String16& opPackageName);
private:
OpRecordAudioMonitor(uid_t uid, const String16& opPackageName);

@ -1898,7 +1898,7 @@ void AudioFlinger::PlaybackThread::PatchTrack::restartIfDisabled()
// static
sp<AudioFlinger::RecordThread::OpRecordAudioMonitor>
AudioFlinger::RecordThread::OpRecordAudioMonitor::createIfNeeded(
uid_t uid, const String16& opPackageName)
uid_t uid, const audio_attributes_t& attr, const String16& opPackageName)
{
if (isServiceUid(uid)) {
ALOGV("not silencing record for service uid:%d pack:%s",
@ -1906,6 +1906,13 @@ AudioFlinger::RecordThread::OpRecordAudioMonitor::createIfNeeded(
return nullptr;
}
// Capturing from FM TUNER output is not controlled by OP_RECORD_AUDIO
// because it does not affect users privacy as does capturing from an actual microphone.
if (attr.source == AUDIO_SOURCE_FM_TUNER) {
ALOGV("not muting FM TUNER capture for uid %d", uid);
return nullptr;
}
if (opPackageName.size() == 0) {
Vector<String16> packages;
// no package name, happens with SL ES clients
@ -2071,7 +2078,7 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack(
mRecordBufferConverter(NULL),
mFlags(flags),
mSilenced(false),
mOpRecordAudioMonitor(OpRecordAudioMonitor::createIfNeeded(uid, opPackageName))
mOpRecordAudioMonitor(OpRecordAudioMonitor::createIfNeeded(uid, attr, opPackageName))
{
if (mCblk == NULL) {
return;

@ -377,8 +377,10 @@ status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr,
pid = callingPid;
}
// check calling permissions
if (!recordingAllowed(opPackageName, pid, uid)) {
// check calling permissions.
// Capturing from FM_TUNER source is controlled by captureAudioOutputAllowed() only as this
// does not affect users privacy as does capturing from an actual microphone.
if (!(recordingAllowed(opPackageName, pid, uid) || attr->source == AUDIO_SOURCE_FM_TUNER)) {
ALOGE("%s permission denied: recording not allowed for uid %d pid %d",
__func__, uid, pid);
return PERMISSION_DENIED;
@ -388,7 +390,8 @@ status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr,
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) &&
attr->source == AUDIO_SOURCE_ECHO_REFERENCE||
attr->source == AUDIO_SOURCE_FM_TUNER) &&
!canCaptureOutput) {
return PERMISSION_DENIED;
}
@ -494,7 +497,8 @@ status_t AudioPolicyService::startInput(audio_port_handle_t portId)
}
// check calling permissions
if (!startRecording(client->opPackageName, client->pid, client->uid)) {
if (!(startRecording(client->opPackageName, client->pid, client->uid)
|| client->attributes.source == AUDIO_SOURCE_FM_TUNER)) {
ALOGE("%s permission denied: recording not allowed for uid %d pid %d",
__func__, client->uid, client->pid);
return PERMISSION_DENIED;

Loading…
Cancel
Save