Loading services/audioflinger/RecordTracks.h +1 −39 Original line number Diff line number Diff line Loading @@ -21,42 +21,6 @@ #error This header file should only be included from AudioFlinger.h #endif // Checks and monitors app ops for audio record class OpRecordAudioMonitor : public RefBase { public: ~OpRecordAudioMonitor() override; bool hasOp() const; int32_t getOp() const { return mAppOp; } static sp<OpRecordAudioMonitor> createIfNeeded(const AttributionSourceState& attributionSource, const audio_attributes_t& attr); private: OpRecordAudioMonitor(const AttributionSourceState& attributionSource, int32_t appOp); 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 the app op for this OpRecordAudioMonitor is updated // in AppOp callback and in onFirstRef() void checkOp(); std::atomic_bool mHasOp; const AttributionSourceState mAttributionSource; const int32_t mAppOp; }; // record track class RecordTrack : public TrackBase { public: Loading Loading @@ -107,7 +71,7 @@ public: { return (mFlags & AUDIO_INPUT_FLAG_DIRECT) != 0; } void setSilenced(bool silenced) { if (!isPatchTrack()) mSilenced = silenced; } bool isSilenced() const; bool isSilenced() const { return mSilenced; } status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones); Loading Loading @@ -154,8 +118,6 @@ private: bool mSilenced; // used to enforce the audio record app op corresponding to this track's audio source sp<OpRecordAudioMonitor> mOpRecordAudioMonitor; std::string mSharedAudioPackageName = {}; int32_t mStartFrames = -1; }; Loading services/audioflinger/Tracks.cpp +0 −112 Original line number Diff line number Diff line Loading @@ -2247,109 +2247,6 @@ void AudioFlinger::PlaybackThread::PatchTrack::restartIfDisabled() // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // AppOp for audio recording // ------------------------------- #undef LOG_TAG #define LOG_TAG "AF::OpRecordAudioMonitor" // static sp<AudioFlinger::RecordThread::OpRecordAudioMonitor> AudioFlinger::RecordThread::OpRecordAudioMonitor::createIfNeeded( const AttributionSourceState& attributionSource, const audio_attributes_t& attr) { if (isServiceUid(attributionSource.uid)) { ALOGV("not silencing record for service %s", attributionSource.toString().c_str()); return nullptr; } // Capturing from FM TUNER output is not controlled by an app op // 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", attributionSource.uid); return nullptr; } AttributionSourceState checkedAttributionSource = AudioFlinger::checkAttributionSourcePackage( attributionSource); if (!checkedAttributionSource.packageName.has_value() || checkedAttributionSource.packageName.value().size() == 0) { return nullptr; } return new OpRecordAudioMonitor(checkedAttributionSource, getOpForSource(attr.source)); } AudioFlinger::RecordThread::OpRecordAudioMonitor::OpRecordAudioMonitor( const AttributionSourceState& attributionSource, int32_t appOp) : mHasOp(true), mAttributionSource(attributionSource), mAppOp(appOp) { } AudioFlinger::RecordThread::OpRecordAudioMonitor::~OpRecordAudioMonitor() { if (mOpCallback != 0) { mAppOpsManager.stopWatchingMode(mOpCallback); } mOpCallback.clear(); } void AudioFlinger::RecordThread::OpRecordAudioMonitor::onFirstRef() { checkOp(); mOpCallback = new RecordAudioOpCallback(this); ALOGV("start watching op %d for %s", mAppOp, mAttributionSource.toString().c_str()); // TODO: We need to always watch AppOpsManager::OP_RECORD_AUDIO too // since it controls the mic permission for legacy apps. mAppOpsManager.startWatchingMode(mAppOp, VALUE_OR_FATAL(aidl2legacy_string_view_String16( mAttributionSource.packageName.value_or(""))), mOpCallback); } bool AudioFlinger::RecordThread::OpRecordAudioMonitor::hasOp() const { return mHasOp.load(); } // Called by RecordAudioOpCallback when the app op corresponding to this OpRecordAudioMonitor // is updated in AppOp callback and in onFirstRef() // Note this method is never called (and never to be) for audio server / root 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::checkOp() { // TODO: We need to always check AppOpsManager::OP_RECORD_AUDIO too // since it controls the mic permission for legacy apps. const int32_t mode = mAppOpsManager.checkOp(mAppOp, mAttributionSource.uid, VALUE_OR_FATAL(aidl2legacy_string_view_String16( mAttributionSource.packageName.value_or("")))); const bool hasIt = (mode == AppOpsManager::MODE_ALLOWED); // verbose logging only log when appOp changed ALOGI_IF(hasIt != mHasOp.load(), "App op %d missing, %ssilencing record %s", mAppOp, hasIt ? "un" : "", mAttributionSource.toString().c_str()); mHasOp.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); sp<OpRecordAudioMonitor> monitor = mMonitor.promote(); if (monitor != NULL) { if (op != monitor->getOp()) { return; } monitor->checkOp(); } } #undef LOG_TAG #define LOG_TAG "AF::RecordHandle" Loading Loading @@ -2450,7 +2347,6 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack( mRecordBufferConverter(NULL), mFlags(flags), mSilenced(false), mOpRecordAudioMonitor(OpRecordAudioMonitor::createIfNeeded(attributionSource, attr)), mStartFrames(startFrames) { if (mCblk == NULL) { Loading Loading @@ -2709,14 +2605,6 @@ void AudioFlinger::RecordThread::RecordTrack::updateTrackFrameInfo( mServerLatencyMs.store(latencyMs); } 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->hasOp() : false; } status_t AudioFlinger::RecordThread::RecordTrack::getActiveMicrophones( std::vector<media::MicrophoneInfo>* activeMicrophones) { Loading services/audiopolicy/service/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ cc_library_shared { "libmedia_helper", "libmediametrics", "libmediautils", "libpermission", "libsensorprivacy", "libutils", "audioclient-types-aidl-cpp", Loading services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -674,7 +674,8 @@ Status AudioPolicyService::getInputForAttr(const media::AudioAttributesInternal& sp<AudioRecordClient> client = new AudioRecordClient(attr, input, session, portId, selectedDeviceId, adjAttributionSource, canCaptureOutput, canCaptureHotword); canCaptureOutput, canCaptureHotword, mAudioCommandThread); mAudioRecordClients.add(portId, client); } Loading services/audiopolicy/service/AudioPolicyService.cpp +139 −1 Original line number Diff line number Diff line Loading @@ -730,7 +730,10 @@ void AudioPolicyService::updateUidStates_l() && !(isTopOrLatestSensitive || current->canCaptureOutput)) && canCaptureIfInCallOrCommunication(current); if (isVirtualSource(source)) { if (!current->hasOp()) { // Never allow capture if app op is denied allowCapture = false; } else if (isVirtualSource(source)) { // Allow capture for virtual (remote submix, call audio TX or RX...) sources allowCapture = true; } else if (mUidPolicy->isAssistantUid(currentUid)) { Loading Loading @@ -830,6 +833,19 @@ bool AudioPolicyService::isVirtualSource(audio_source_t source) return false; } /* static */ bool AudioPolicyService::isAppOpSource(audio_source_t source) { switch (source) { case AUDIO_SOURCE_FM_TUNER: case AUDIO_SOURCE_ECHO_REFERENCE: return false; default: break; } return true; } void AudioPolicyService::setAppState_l(sp<AudioRecordClient> client, app_state_t state) { AutoCallerClear acc; Loading Loading @@ -1418,6 +1434,109 @@ binder::Status AudioPolicyService::SensorPrivacyPolicy::onSensorPrivacyChanged(b return binder::Status::ok(); } // ----------- AudioPolicyService::OpRecordAudioMonitor implementation ---------- // static sp<AudioPolicyService::OpRecordAudioMonitor> AudioPolicyService::OpRecordAudioMonitor::createIfNeeded( const AttributionSourceState& attributionSource, const audio_attributes_t& attr, wp<AudioCommandThread> commandThread) { if (isServiceUid(attributionSource.uid)) { ALOGV("not silencing record for service %s", attributionSource.toString().c_str()); return nullptr; } if (!AudioPolicyService::isAppOpSource(attr.source)) { ALOGD("not monitoring app op for uid %d and source %d", attributionSource.uid, attr.source); return nullptr; } if (!attributionSource.packageName.has_value() || attributionSource.packageName.value().size() == 0) { return nullptr; } return new OpRecordAudioMonitor(attributionSource, getOpForSource(attr.source), commandThread); } AudioPolicyService::OpRecordAudioMonitor::OpRecordAudioMonitor( const AttributionSourceState& attributionSource, int32_t appOp, wp<AudioCommandThread> commandThread) : mHasOp(true), mAttributionSource(attributionSource), mAppOp(appOp), mCommandThread(commandThread) { } AudioPolicyService::OpRecordAudioMonitor::~OpRecordAudioMonitor() { if (mOpCallback != 0) { mAppOpsManager.stopWatchingMode(mOpCallback); } mOpCallback.clear(); } void AudioPolicyService::OpRecordAudioMonitor::onFirstRef() { checkOp(); mOpCallback = new RecordAudioOpCallback(this); ALOGV("start watching op %d for %s", mAppOp, mAttributionSource.toString().c_str()); // TODO: We need to always watch AppOpsManager::OP_RECORD_AUDIO too // since it controls the mic permission for legacy apps. mAppOpsManager.startWatchingMode(mAppOp, VALUE_OR_FATAL(aidl2legacy_string_view_String16( mAttributionSource.packageName.value_or(""))), mOpCallback); } bool AudioPolicyService::OpRecordAudioMonitor::hasOp() const { return mHasOp.load(); } // Called by RecordAudioOpCallback when the app op corresponding to this OpRecordAudioMonitor // is updated in AppOp callback and in onFirstRef() // Note this method is never called (and never to be) for audio server / root 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 AudioPolicyService::OpRecordAudioMonitor::checkOp(bool updateUidStates) { // TODO: We need to always check AppOpsManager::OP_RECORD_AUDIO too // since it controls the mic permission for legacy apps. const int32_t mode = mAppOpsManager.checkOp(mAppOp, mAttributionSource.uid, VALUE_OR_FATAL(aidl2legacy_string_view_String16( mAttributionSource.packageName.value_or("")))); const bool hasIt = (mode == AppOpsManager::MODE_ALLOWED); // verbose logging only log when appOp changed ALOGI_IF(hasIt != mHasOp.load(), "App op %d missing, %ssilencing record %s", mAppOp, hasIt ? "un" : "", mAttributionSource.toString().c_str()); mHasOp.store(hasIt); if (updateUidStates) { sp<AudioCommandThread> commandThread = mCommandThread.promote(); if (commandThread != nullptr) { commandThread->updateUidStatesCommand(); } } } AudioPolicyService::OpRecordAudioMonitor::RecordAudioOpCallback::RecordAudioOpCallback( const wp<OpRecordAudioMonitor>& monitor) : mMonitor(monitor) { } void AudioPolicyService::OpRecordAudioMonitor::RecordAudioOpCallback::opChanged(int32_t op, const String16& packageName __unused) { sp<OpRecordAudioMonitor> monitor = mMonitor.promote(); if (monitor != NULL) { if (op != monitor->getOp()) { return; } monitor->checkOp(true); } } // ----------- AudioPolicyService::AudioCommandThread implementation ---------- AudioPolicyService::AudioCommandThread::AudioCommandThread(String8 name, Loading Loading @@ -1634,6 +1753,17 @@ bool AudioPolicyService::AudioCommandThread::threadLoop() mLock.lock(); } break; case UPDATE_UID_STATES: { ALOGV("AudioCommandThread() processing updateUID states"); svc = mService.promote(); if (svc == 0) { break; } mLock.unlock(); svc->updateUidStates(); mLock.lock(); } break; default: ALOGW("AudioCommandThread() unknown command %d", command->mCommand); } Loading Loading @@ -1847,6 +1977,14 @@ void AudioPolicyService::AudioCommandThread::updateAudioPortListCommand() sendCommand(command); } void AudioPolicyService::AudioCommandThread::updateUidStatesCommand() { sp<AudioCommand> command = new AudioCommand(); command->mCommand = UPDATE_UID_STATES; ALOGV("AudioCommandThread() adding update UID states"); sendCommand(command); } void AudioPolicyService::AudioCommandThread::updateAudioPatchListCommand() { sp<AudioCommand>command = new AudioCommand(); Loading Loading
services/audioflinger/RecordTracks.h +1 −39 Original line number Diff line number Diff line Loading @@ -21,42 +21,6 @@ #error This header file should only be included from AudioFlinger.h #endif // Checks and monitors app ops for audio record class OpRecordAudioMonitor : public RefBase { public: ~OpRecordAudioMonitor() override; bool hasOp() const; int32_t getOp() const { return mAppOp; } static sp<OpRecordAudioMonitor> createIfNeeded(const AttributionSourceState& attributionSource, const audio_attributes_t& attr); private: OpRecordAudioMonitor(const AttributionSourceState& attributionSource, int32_t appOp); 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 the app op for this OpRecordAudioMonitor is updated // in AppOp callback and in onFirstRef() void checkOp(); std::atomic_bool mHasOp; const AttributionSourceState mAttributionSource; const int32_t mAppOp; }; // record track class RecordTrack : public TrackBase { public: Loading Loading @@ -107,7 +71,7 @@ public: { return (mFlags & AUDIO_INPUT_FLAG_DIRECT) != 0; } void setSilenced(bool silenced) { if (!isPatchTrack()) mSilenced = silenced; } bool isSilenced() const; bool isSilenced() const { return mSilenced; } status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones); Loading Loading @@ -154,8 +118,6 @@ private: bool mSilenced; // used to enforce the audio record app op corresponding to this track's audio source sp<OpRecordAudioMonitor> mOpRecordAudioMonitor; std::string mSharedAudioPackageName = {}; int32_t mStartFrames = -1; }; Loading
services/audioflinger/Tracks.cpp +0 −112 Original line number Diff line number Diff line Loading @@ -2247,109 +2247,6 @@ void AudioFlinger::PlaybackThread::PatchTrack::restartIfDisabled() // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // AppOp for audio recording // ------------------------------- #undef LOG_TAG #define LOG_TAG "AF::OpRecordAudioMonitor" // static sp<AudioFlinger::RecordThread::OpRecordAudioMonitor> AudioFlinger::RecordThread::OpRecordAudioMonitor::createIfNeeded( const AttributionSourceState& attributionSource, const audio_attributes_t& attr) { if (isServiceUid(attributionSource.uid)) { ALOGV("not silencing record for service %s", attributionSource.toString().c_str()); return nullptr; } // Capturing from FM TUNER output is not controlled by an app op // 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", attributionSource.uid); return nullptr; } AttributionSourceState checkedAttributionSource = AudioFlinger::checkAttributionSourcePackage( attributionSource); if (!checkedAttributionSource.packageName.has_value() || checkedAttributionSource.packageName.value().size() == 0) { return nullptr; } return new OpRecordAudioMonitor(checkedAttributionSource, getOpForSource(attr.source)); } AudioFlinger::RecordThread::OpRecordAudioMonitor::OpRecordAudioMonitor( const AttributionSourceState& attributionSource, int32_t appOp) : mHasOp(true), mAttributionSource(attributionSource), mAppOp(appOp) { } AudioFlinger::RecordThread::OpRecordAudioMonitor::~OpRecordAudioMonitor() { if (mOpCallback != 0) { mAppOpsManager.stopWatchingMode(mOpCallback); } mOpCallback.clear(); } void AudioFlinger::RecordThread::OpRecordAudioMonitor::onFirstRef() { checkOp(); mOpCallback = new RecordAudioOpCallback(this); ALOGV("start watching op %d for %s", mAppOp, mAttributionSource.toString().c_str()); // TODO: We need to always watch AppOpsManager::OP_RECORD_AUDIO too // since it controls the mic permission for legacy apps. mAppOpsManager.startWatchingMode(mAppOp, VALUE_OR_FATAL(aidl2legacy_string_view_String16( mAttributionSource.packageName.value_or(""))), mOpCallback); } bool AudioFlinger::RecordThread::OpRecordAudioMonitor::hasOp() const { return mHasOp.load(); } // Called by RecordAudioOpCallback when the app op corresponding to this OpRecordAudioMonitor // is updated in AppOp callback and in onFirstRef() // Note this method is never called (and never to be) for audio server / root 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::checkOp() { // TODO: We need to always check AppOpsManager::OP_RECORD_AUDIO too // since it controls the mic permission for legacy apps. const int32_t mode = mAppOpsManager.checkOp(mAppOp, mAttributionSource.uid, VALUE_OR_FATAL(aidl2legacy_string_view_String16( mAttributionSource.packageName.value_or("")))); const bool hasIt = (mode == AppOpsManager::MODE_ALLOWED); // verbose logging only log when appOp changed ALOGI_IF(hasIt != mHasOp.load(), "App op %d missing, %ssilencing record %s", mAppOp, hasIt ? "un" : "", mAttributionSource.toString().c_str()); mHasOp.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); sp<OpRecordAudioMonitor> monitor = mMonitor.promote(); if (monitor != NULL) { if (op != monitor->getOp()) { return; } monitor->checkOp(); } } #undef LOG_TAG #define LOG_TAG "AF::RecordHandle" Loading Loading @@ -2450,7 +2347,6 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack( mRecordBufferConverter(NULL), mFlags(flags), mSilenced(false), mOpRecordAudioMonitor(OpRecordAudioMonitor::createIfNeeded(attributionSource, attr)), mStartFrames(startFrames) { if (mCblk == NULL) { Loading Loading @@ -2709,14 +2605,6 @@ void AudioFlinger::RecordThread::RecordTrack::updateTrackFrameInfo( mServerLatencyMs.store(latencyMs); } 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->hasOp() : false; } status_t AudioFlinger::RecordThread::RecordTrack::getActiveMicrophones( std::vector<media::MicrophoneInfo>* activeMicrophones) { Loading
services/audiopolicy/service/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ cc_library_shared { "libmedia_helper", "libmediametrics", "libmediautils", "libpermission", "libsensorprivacy", "libutils", "audioclient-types-aidl-cpp", Loading
services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -674,7 +674,8 @@ Status AudioPolicyService::getInputForAttr(const media::AudioAttributesInternal& sp<AudioRecordClient> client = new AudioRecordClient(attr, input, session, portId, selectedDeviceId, adjAttributionSource, canCaptureOutput, canCaptureHotword); canCaptureOutput, canCaptureHotword, mAudioCommandThread); mAudioRecordClients.add(portId, client); } Loading
services/audiopolicy/service/AudioPolicyService.cpp +139 −1 Original line number Diff line number Diff line Loading @@ -730,7 +730,10 @@ void AudioPolicyService::updateUidStates_l() && !(isTopOrLatestSensitive || current->canCaptureOutput)) && canCaptureIfInCallOrCommunication(current); if (isVirtualSource(source)) { if (!current->hasOp()) { // Never allow capture if app op is denied allowCapture = false; } else if (isVirtualSource(source)) { // Allow capture for virtual (remote submix, call audio TX or RX...) sources allowCapture = true; } else if (mUidPolicy->isAssistantUid(currentUid)) { Loading Loading @@ -830,6 +833,19 @@ bool AudioPolicyService::isVirtualSource(audio_source_t source) return false; } /* static */ bool AudioPolicyService::isAppOpSource(audio_source_t source) { switch (source) { case AUDIO_SOURCE_FM_TUNER: case AUDIO_SOURCE_ECHO_REFERENCE: return false; default: break; } return true; } void AudioPolicyService::setAppState_l(sp<AudioRecordClient> client, app_state_t state) { AutoCallerClear acc; Loading Loading @@ -1418,6 +1434,109 @@ binder::Status AudioPolicyService::SensorPrivacyPolicy::onSensorPrivacyChanged(b return binder::Status::ok(); } // ----------- AudioPolicyService::OpRecordAudioMonitor implementation ---------- // static sp<AudioPolicyService::OpRecordAudioMonitor> AudioPolicyService::OpRecordAudioMonitor::createIfNeeded( const AttributionSourceState& attributionSource, const audio_attributes_t& attr, wp<AudioCommandThread> commandThread) { if (isServiceUid(attributionSource.uid)) { ALOGV("not silencing record for service %s", attributionSource.toString().c_str()); return nullptr; } if (!AudioPolicyService::isAppOpSource(attr.source)) { ALOGD("not monitoring app op for uid %d and source %d", attributionSource.uid, attr.source); return nullptr; } if (!attributionSource.packageName.has_value() || attributionSource.packageName.value().size() == 0) { return nullptr; } return new OpRecordAudioMonitor(attributionSource, getOpForSource(attr.source), commandThread); } AudioPolicyService::OpRecordAudioMonitor::OpRecordAudioMonitor( const AttributionSourceState& attributionSource, int32_t appOp, wp<AudioCommandThread> commandThread) : mHasOp(true), mAttributionSource(attributionSource), mAppOp(appOp), mCommandThread(commandThread) { } AudioPolicyService::OpRecordAudioMonitor::~OpRecordAudioMonitor() { if (mOpCallback != 0) { mAppOpsManager.stopWatchingMode(mOpCallback); } mOpCallback.clear(); } void AudioPolicyService::OpRecordAudioMonitor::onFirstRef() { checkOp(); mOpCallback = new RecordAudioOpCallback(this); ALOGV("start watching op %d for %s", mAppOp, mAttributionSource.toString().c_str()); // TODO: We need to always watch AppOpsManager::OP_RECORD_AUDIO too // since it controls the mic permission for legacy apps. mAppOpsManager.startWatchingMode(mAppOp, VALUE_OR_FATAL(aidl2legacy_string_view_String16( mAttributionSource.packageName.value_or(""))), mOpCallback); } bool AudioPolicyService::OpRecordAudioMonitor::hasOp() const { return mHasOp.load(); } // Called by RecordAudioOpCallback when the app op corresponding to this OpRecordAudioMonitor // is updated in AppOp callback and in onFirstRef() // Note this method is never called (and never to be) for audio server / root 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 AudioPolicyService::OpRecordAudioMonitor::checkOp(bool updateUidStates) { // TODO: We need to always check AppOpsManager::OP_RECORD_AUDIO too // since it controls the mic permission for legacy apps. const int32_t mode = mAppOpsManager.checkOp(mAppOp, mAttributionSource.uid, VALUE_OR_FATAL(aidl2legacy_string_view_String16( mAttributionSource.packageName.value_or("")))); const bool hasIt = (mode == AppOpsManager::MODE_ALLOWED); // verbose logging only log when appOp changed ALOGI_IF(hasIt != mHasOp.load(), "App op %d missing, %ssilencing record %s", mAppOp, hasIt ? "un" : "", mAttributionSource.toString().c_str()); mHasOp.store(hasIt); if (updateUidStates) { sp<AudioCommandThread> commandThread = mCommandThread.promote(); if (commandThread != nullptr) { commandThread->updateUidStatesCommand(); } } } AudioPolicyService::OpRecordAudioMonitor::RecordAudioOpCallback::RecordAudioOpCallback( const wp<OpRecordAudioMonitor>& monitor) : mMonitor(monitor) { } void AudioPolicyService::OpRecordAudioMonitor::RecordAudioOpCallback::opChanged(int32_t op, const String16& packageName __unused) { sp<OpRecordAudioMonitor> monitor = mMonitor.promote(); if (monitor != NULL) { if (op != monitor->getOp()) { return; } monitor->checkOp(true); } } // ----------- AudioPolicyService::AudioCommandThread implementation ---------- AudioPolicyService::AudioCommandThread::AudioCommandThread(String8 name, Loading Loading @@ -1634,6 +1753,17 @@ bool AudioPolicyService::AudioCommandThread::threadLoop() mLock.lock(); } break; case UPDATE_UID_STATES: { ALOGV("AudioCommandThread() processing updateUID states"); svc = mService.promote(); if (svc == 0) { break; } mLock.unlock(); svc->updateUidStates(); mLock.lock(); } break; default: ALOGW("AudioCommandThread() unknown command %d", command->mCommand); } Loading Loading @@ -1847,6 +1977,14 @@ void AudioPolicyService::AudioCommandThread::updateAudioPortListCommand() sendCommand(command); } void AudioPolicyService::AudioCommandThread::updateUidStatesCommand() { sp<AudioCommand> command = new AudioCommand(); command->mCommand = UPDATE_UID_STATES; ALOGV("AudioCommandThread() adding update UID states"); sendCommand(command); } void AudioPolicyService::AudioCommandThread::updateAudioPatchListCommand() { sp<AudioCommand>command = new AudioCommand(); Loading