summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin F. Haggerty <haggertk@lineageos.org>2019-12-02 19:47:22 -0700
committerKevin F. Haggerty <haggertk@lineageos.org>2019-12-02 19:47:22 -0700
commit92595d033186aa2b0307ac078d0d6aa62632d5ba (patch)
treef0c9e42d20c25d9e6d9a0dcf2827f4a7ebde4a1a
parentfb53ac69f4d87f4a53e0a8c5416802bada0b1bfb (diff)
parente79a0716216edade8100dd4d6b05a69e80ce25ed (diff)
downloadframeworks_av-92595d033186aa2b0307ac078d0d6aa62632d5ba.tar.gz
frameworks_av-92595d033186aa2b0307ac078d0d6aa62632d5ba.tar.bz2
frameworks_av-92595d033186aa2b0307ac078d0d6aa62632d5ba.zip
Merge tag 'android-9.0.0_r51' into staging/lineage-16.0_merge-android-9.0.0_r51
Android 9.0.0 Release 51 (5948683) * tag 'android-9.0.0_r51': AudioFlinger: enforce OP_RECORD_AUDIO during recording Change-Id: Ie009cb689c284ba93f53df10c0ea892a1401b722
-rw-r--r--services/audioflinger/AudioFlinger.cpp3
-rw-r--r--services/audioflinger/AudioFlinger.h2
-rw-r--r--services/audioflinger/RecordTracks.h41
-rw-r--r--services/audioflinger/ServiceUtilities.h9
-rw-r--r--services/audioflinger/Threads.cpp7
-rw-r--r--services/audioflinger/Threads.h3
-rw-r--r--services/audioflinger/TrackBase.h2
-rw-r--r--services/audioflinger/Tracks.cpp107
8 files changed, 166 insertions, 8 deletions
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index c77d082cfe..b884cf489a 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1723,7 +1723,8 @@ sp<media::IAudioRecord> AudioFlinger::createRecord(const CreateRecordInput& inpu
&output.notificationFrameCount,
clientUid, &output.flags,
input.clientInfo.clientTid,
- &lStatus, portId);
+ &lStatus, portId,
+ input.opPackageName);
LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (recordTrack == 0));
// lStatus == BAD_TYPE means FAST flag was rejected: request a new input from
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 963a87da58..567c5a93a9 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -48,7 +48,9 @@
#include <utils/TypeHelpers.h>
#include <utils/Vector.h>
+#include <binder/AppOpsManager.h>
#include <binder/BinderService.h>
+#include <binder/IAppOpsCallback.h>
#include <binder/MemoryDealer.h>
#include <system/audio.h>
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index fc2dbbba8c..37b8f9114f 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -19,6 +19,39 @@
#error This header file should only be included from AudioFlinger.h
#endif
+// Checks and monitors OP_RECORD_AUDIO
+class OpRecordAudioMonitor : public RefBase {
+public:
+ ~OpRecordAudioMonitor() override;
+ bool hasOpRecordAudio() const;
+
+ static sp<OpRecordAudioMonitor> createIfNeeded(uid_t uid, const String16& opPackageName);
+
+private:
+ OpRecordAudioMonitor(uid_t uid, const String16& opPackageName);
+ void onFirstRef() override;
+
+ AppOpsManager mAppOpsManager;
+
+ class RecordAudioOpCallback : public BnAppOpsCallback {
+ public:
+ explicit RecordAudioOpCallback(const wp<OpRecordAudioMonitor>& monitor);
+ void opChanged(int32_t op, const String16& packageName) override;
+
+ private:
+ const wp<OpRecordAudioMonitor> mMonitor;
+ };
+
+ sp<RecordAudioOpCallback> mOpCallback;
+ // called by RecordAudioOpCallback when OP_RECORD_AUDIO is updated in AppOp callback
+ // and in onFirstRef()
+ void checkRecordAudio();
+
+ std::atomic_bool mHasOpRecordAudio;
+ const uid_t mUid;
+ const String16 mPackage;
+};
+
// record track
class RecordTrack : public TrackBase {
public:
@@ -35,6 +68,7 @@ public:
uid_t uid,
audio_input_flags_t flags,
track_type type,
+ const String16& opPackageName,
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
virtual ~RecordTrack();
virtual status_t initCheck() const;
@@ -65,7 +99,7 @@ public:
virtual bool isFastTrack() const { return (mFlags & AUDIO_INPUT_FLAG_FAST) != 0; }
void setSilenced(bool silenced) { if (!isPatchTrack()) mSilenced = silenced; }
- bool isSilenced() const { return mSilenced; }
+ bool isSilenced() const;
status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
@@ -99,6 +133,11 @@ private:
audio_input_flags_t mFlags;
bool mSilenced;
+
+ // used to enforce OP_RECORD_AUDIO
+ uid_t mUid;
+ String16 mOpPackageName;
+ sp<OpRecordAudioMonitor> mOpRecordAudioMonitor;
};
// playback track, used by PatchPanel
diff --git a/services/audioflinger/ServiceUtilities.h b/services/audioflinger/ServiceUtilities.h
index f45ada1a4a..03756b34d0 100644
--- a/services/audioflinger/ServiceUtilities.h
+++ b/services/audioflinger/ServiceUtilities.h
@@ -14,12 +14,21 @@
* limitations under the License.
*/
+#include <cutils/multiuser.h>
+#include <private/android_filesystem_config.h>
#include <unistd.h>
#include <binder/PermissionController.h>
namespace android {
+// Used for calls that should originate from system services.
+// We allow that some services might have separate processes to
+// handle multiple users, e.g. u10_system, u10_bluetooth, u10_radio.
+static inline bool isServiceUid(uid_t uid) {
+ return multiuser_get_app_id(uid) < AID_APP_START;
+}
+
extern pid_t getpid_cached;
bool isTrustedCallingUid(uid_t uid);
bool recordingAllowed(const String16& opPackageName, pid_t pid, uid_t uid);
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index dcad8660a9..499342001b 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -6778,7 +6778,7 @@ reacquire_wakelock:
// Sanitize before releasing if the track has no access to the source data
// An idle UID receives silence from non virtual devices until active
if (activeTrack->isSilenced()) {
- memset(activeTrack->mSink.raw, 0, framesOut * mFrameSize);
+ memset(activeTrack->mSink.raw, 0, framesOut * activeTrack->frameSize());
}
activeTrack->releaseBuffer(&activeTrack->mSink);
}
@@ -6921,7 +6921,8 @@ sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRe
audio_input_flags_t *flags,
pid_t tid,
status_t *status,
- audio_port_handle_t portId)
+ audio_port_handle_t portId,
+ const String16& opPackageName)
{
size_t frameCount = *pFrameCount;
size_t notificationFrameCount = *pNotificationFrameCount;
@@ -7047,7 +7048,7 @@ sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRe
track = new RecordTrack(this, client, attr, sampleRate,
format, channelMask, frameCount,
nullptr /* buffer */, (size_t)0 /* bufferSize */, sessionId, uid,
- *flags, TrackBase::TYPE_DEFAULT, portId);
+ *flags, TrackBase::TYPE_DEFAULT, opPackageName, portId);
lStatus = track->initCheck();
if (lStatus != NO_ERROR) {
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 28d4482129..33d692372d 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1413,7 +1413,8 @@ public:
audio_input_flags_t *flags,
pid_t tid,
status_t *status /*non-NULL*/,
- audio_port_handle_t portId);
+ audio_port_handle_t portId,
+ const String16& opPackageName);
status_t start(RecordTrack* recordTrack,
AudioSystem::sync_event_t event,
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index ccfb69fbb2..3b8369f025 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -115,6 +115,8 @@ protected:
uint32_t channelCount() const { return mChannelCount; }
+ size_t frameSize() const { return mFrameSize; }
+
audio_channel_mask_t channelMask() const { return mChannelMask; }
virtual uint32_t sampleRate() const { return mSampleRate; }
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index a7c4253569..de15e4b75e 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -1601,6 +1601,99 @@ void AudioFlinger::PlaybackThread::PatchTrack::restartIfDisabled()
// Record
// ----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
+// AppOp for audio recording
+// -------------------------------
+
+// static
+sp<AudioFlinger::RecordThread::OpRecordAudioMonitor>
+AudioFlinger::RecordThread::OpRecordAudioMonitor::createIfNeeded(
+ uid_t uid, const String16& opPackageName)
+{
+ if (isServiceUid(uid)) {
+ ALOGV("not silencing record for service uid:%d pack:%s",
+ uid, String8(opPackageName).string());
+ return nullptr;
+ }
+
+ if (opPackageName.size() == 0) {
+ Vector<String16> packages;
+ // no package name, happens with SL ES clients
+ // query package manager to find one
+ PermissionController permissionController;
+ permissionController.getPackagesForUid(uid, packages);
+ if (packages.isEmpty()) {
+ return nullptr;
+ } else {
+ ALOGV("using pack:%s for uid:%d", String8(packages[0]).string(), uid);
+ return new OpRecordAudioMonitor(uid, packages[0]);
+ }
+ }
+
+ return new OpRecordAudioMonitor(uid, opPackageName);
+}
+
+AudioFlinger::RecordThread::OpRecordAudioMonitor::OpRecordAudioMonitor(
+ uid_t uid, const String16& opPackageName)
+ : mHasOpRecordAudio(true), mUid(uid), mPackage(opPackageName)
+{
+}
+
+AudioFlinger::RecordThread::OpRecordAudioMonitor::~OpRecordAudioMonitor()
+{
+ if (mOpCallback != 0) {
+ mAppOpsManager.stopWatchingMode(mOpCallback);
+ }
+ mOpCallback.clear();
+}
+
+void AudioFlinger::RecordThread::OpRecordAudioMonitor::onFirstRef()
+{
+ checkRecordAudio();
+ mOpCallback = new RecordAudioOpCallback(this);
+ ALOGV("start watching OP_RECORD_AUDIO for pack:%s", String8(mPackage).string());
+ mAppOpsManager.startWatchingMode(AppOpsManager::OP_RECORD_AUDIO, mPackage, mOpCallback);
+}
+
+bool AudioFlinger::RecordThread::OpRecordAudioMonitor::hasOpRecordAudio() const {
+ return mHasOpRecordAudio.load();
+}
+
+// Called by RecordAudioOpCallback when OP_RECORD_AUDIO is updated in AppOp callback
+// and in onFirstRef()
+// Note this method is never called (and never to be) for audio server / patch record track
+// due to the UID in createIfNeeded(). As a result for those record track, it's:
+// - not called from constructor,
+// - not called from RecordAudioOpCallback because the callback is not installed in this case
+void AudioFlinger::RecordThread::OpRecordAudioMonitor::checkRecordAudio()
+{
+ const int32_t mode = mAppOpsManager.checkOp(AppOpsManager::OP_RECORD_AUDIO,
+ mUid, mPackage);
+ const bool hasIt = (mode == AppOpsManager::MODE_ALLOWED);
+ // verbose logging only log when appOp changed
+ ALOGI_IF(hasIt != mHasOpRecordAudio.load(),
+ "OP_RECORD_AUDIO missing, %ssilencing record uid%d pack:%s",
+ hasIt ? "un" : "", mUid, String8(mPackage).string());
+ mHasOpRecordAudio.store(hasIt);
+}
+
+AudioFlinger::RecordThread::OpRecordAudioMonitor::RecordAudioOpCallback::RecordAudioOpCallback(
+ const wp<OpRecordAudioMonitor>& monitor) : mMonitor(monitor)
+{ }
+
+void AudioFlinger::RecordThread::OpRecordAudioMonitor::RecordAudioOpCallback::opChanged(int32_t op,
+ const String16& packageName) {
+ UNUSED(packageName);
+ if (op != AppOpsManager::OP_RECORD_AUDIO) {
+ return;
+ }
+ sp<OpRecordAudioMonitor> monitor = mMonitor.promote();
+ if (monitor != NULL) {
+ monitor->checkRecordAudio();
+ }
+}
+
+//----------------------------------------
AudioFlinger::RecordHandle::RecordHandle(
const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
: BnAudioRecord(),
@@ -1654,6 +1747,7 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack(
uid_t uid,
audio_input_flags_t flags,
track_type type,
+ const String16& opPackageName,
audio_port_handle_t portId)
: TrackBase(thread, client, attr, sampleRate, format,
channelMask, frameCount, buffer, bufferSize, sessionId, uid, false /*isOut*/,
@@ -1666,7 +1760,8 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack(
mResamplerBufferProvider(NULL), // initialize in case of early constructor exit
mRecordBufferConverter(NULL),
mFlags(flags),
- mSilenced(false)
+ mSilenced(false),
+ mOpRecordAudioMonitor(OpRecordAudioMonitor::createIfNeeded(uid, opPackageName))
{
if (mCblk == NULL) {
return;
@@ -1852,6 +1947,14 @@ void AudioFlinger::RecordThread::RecordTrack::updateTrackFrameInfo(
mServerProxy->setTimestamp(local);
}
+bool AudioFlinger::RecordThread::RecordTrack::isSilenced() const {
+ if (mSilenced) {
+ return true;
+ }
+ // The monitor is only created for record tracks that can be silenced.
+ return mOpRecordAudioMonitor ? !mOpRecordAudioMonitor->hasOpRecordAudio() : false;
+}
+
status_t AudioFlinger::RecordThread::RecordTrack::getActiveMicrophones(
std::vector<media::MicrophoneInfo>* activeMicrophones)
{
@@ -1875,7 +1978,7 @@ AudioFlinger::RecordThread::PatchRecord::PatchRecord(RecordThread *recordThread,
: RecordTrack(recordThread, NULL,
audio_attributes_t{} /* currently unused for patch track */,
sampleRate, format, channelMask, frameCount,
- buffer, bufferSize, AUDIO_SESSION_NONE, getuid(), flags, TYPE_PATCH),
+ buffer, bufferSize, AUDIO_SESSION_NONE, getuid(), flags, TYPE_PATCH, String16()),
mProxy(new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true))
{
uint64_t mixBufferNs = ((uint64_t)2 * recordThread->frameCount() * 1000000000) /