diff options
author | Kevin F. Haggerty <haggertk@lineageos.org> | 2019-12-02 19:47:22 -0700 |
---|---|---|
committer | Kevin F. Haggerty <haggertk@lineageos.org> | 2019-12-02 19:47:22 -0700 |
commit | 92595d033186aa2b0307ac078d0d6aa62632d5ba (patch) | |
tree | f0c9e42d20c25d9e6d9a0dcf2827f4a7ebde4a1a /services | |
parent | fb53ac69f4d87f4a53e0a8c5416802bada0b1bfb (diff) | |
parent | e79a0716216edade8100dd4d6b05a69e80ce25ed (diff) | |
download | frameworks_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
Diffstat (limited to 'services')
-rw-r--r-- | services/audioflinger/AudioFlinger.cpp | 3 | ||||
-rw-r--r-- | services/audioflinger/AudioFlinger.h | 2 | ||||
-rw-r--r-- | services/audioflinger/RecordTracks.h | 41 | ||||
-rw-r--r-- | services/audioflinger/ServiceUtilities.h | 9 | ||||
-rw-r--r-- | services/audioflinger/Threads.cpp | 7 | ||||
-rw-r--r-- | services/audioflinger/Threads.h | 3 | ||||
-rw-r--r-- | services/audioflinger/TrackBase.h | 2 | ||||
-rw-r--r-- | services/audioflinger/Tracks.cpp | 107 |
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) / |