Loading services/audiopolicy/service/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ cc_library { ], srcs: [ "AudioRecordClient.cpp", "AudioPolicyClientImpl.cpp", "AudioPolicyEffects.cpp", "AudioPolicyInterfaceImpl.cpp", Loading services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ //#define LOG_NDEBUG 0 #include "AudioPolicyService.h" #include "AudioRecordClient.h" #include "TypeConverter.h" #include <media/AidlConversion.h> #include <media/AudioPolicy.h> Loading services/audiopolicy/service/AudioPolicyService.cpp +1 −117 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ #include <binder/IResultReceiver.h> #include <utils/String16.h> #include <utils/threads.h> #include "AudioRecordClient.h" #include "AudioPolicyService.h" #include <hardware_legacy/power.h> #include <media/AidlConversion.h> Loading Loading @@ -1164,20 +1165,6 @@ 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: case AUDIO_SOURCE_REMOTE_SUBMIX: return false; default: break; } return true; } void AudioPolicyService::setAppState_l(sp<AudioRecordClient> client, app_state_t state) { AutoCallerClear acc; Loading Loading @@ -1878,109 +1865,6 @@ binder::Status AudioPolicyService::SensorPrivacyPolicy::onSensorPrivacyChanged( 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 (isAudioServerOrRootUid(attributionSource.uid)) { ALOGV("not silencing record for audio or root source %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 services/audiopolicy/service/AudioPolicyService.h +9 −77 Original line number Diff line number Diff line /* * Copyright (C) 2009 The Android Open Source Project * Loading Loading @@ -28,7 +27,6 @@ #include <utils/Vector.h> #include <utils/SortedVector.h> #include <binder/ActivityManager.h> #include <binder/AppOpsManager.h> #include <binder/BinderService.h> #include <binder/IUidObserver.h> #include <system/audio.h> Loading Loading @@ -64,6 +62,12 @@ using media::audio::common::Int; // ---------------------------------------------------------------------------- namespace media::audiopolicy { class AudioRecordClient; } using ::android::media::audiopolicy::AudioRecordClient; class AudioPolicyService : public BinderService<AudioPolicyService>, public media::BnAudioPolicyService, Loading Loading @@ -401,7 +405,6 @@ private: // Handles binder shell commands virtual status_t shellCommand(int in, int out, int err, Vector<String16>& args); class AudioRecordClient; // Sets whether the given UID records only silence virtual void setAppState_l(sp<AudioRecordClient> client, app_state_t state) REQUIRES(mLock); Loading Loading @@ -542,6 +545,7 @@ private: // Thread used to send audio config commands to audio flinger // For audio config commands, it is necessary because audio flinger requires that the calling // process (user) has permission to modify audio settings. public: class AudioCommandThread : public Thread { class AudioCommand; public: Loading Loading @@ -732,6 +736,7 @@ private: wp<AudioPolicyService> mService; }; private: class AudioPolicyClient : public AudioPolicyClientInterface { public: Loading Loading @@ -906,6 +911,7 @@ private: bool mAudioVolumeGroupCallbacksEnabled; }; public: class AudioClient : public virtual RefBase { public: AudioClient(const audio_attributes_t attributes, Loading @@ -927,82 +933,8 @@ private: const audio_port_handle_t deviceId; // selected input device port ID bool active; // Playback/Capture is active or inactive }; // Checks and monitors app ops for AudioRecordClient 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, wp<AudioCommandThread> commandThread); private: OpRecordAudioMonitor(const AttributionSourceState& attributionSource, int32_t appOp, wp<AudioCommandThread> commandThread); 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() // updateUidStates is true when the silenced state of active AudioRecordClients must be // re-evaluated void checkOp(bool updateUidStates = false); std::atomic_bool mHasOp; const AttributionSourceState mAttributionSource; const int32_t mAppOp; wp<AudioCommandThread> mCommandThread; }; // --- AudioRecordClient --- // Information about each registered AudioRecord client // (between calls to getInputForAttr() and releaseInput()) class AudioRecordClient : public AudioClient { public: AudioRecordClient(const audio_attributes_t attributes, const audio_io_handle_t io, const audio_session_t session, audio_port_handle_t portId, const audio_port_handle_t deviceId, const AttributionSourceState& attributionSource, bool canCaptureOutput, bool canCaptureHotword, wp<AudioCommandThread> commandThread) : AudioClient(attributes, io, attributionSource, session, portId, deviceId), attributionSource(attributionSource), startTimeNs(0), canCaptureOutput(canCaptureOutput), canCaptureHotword(canCaptureHotword), silenced(false), mOpRecordAudioMonitor( OpRecordAudioMonitor::createIfNeeded(attributionSource, attributes, commandThread)) {} ~AudioRecordClient() override = default; bool hasOp() const { return mOpRecordAudioMonitor ? mOpRecordAudioMonitor->hasOp() : true; } const AttributionSourceState attributionSource; // attribution source of client nsecs_t startTimeNs; const bool canCaptureOutput; const bool canCaptureHotword; bool silenced; private: sp<OpRecordAudioMonitor> mOpRecordAudioMonitor; }; // --- AudioPlaybackClient --- Loading services/audiopolicy/service/AudioRecordClient.cpp 0 → 100644 +140 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "AudioRecordClient.h" #include "AudioPolicyService.h" namespace android::media::audiopolicy { using android::AudioPolicyService; namespace { bool isAppOpSource(audio_source_t source) { switch (source) { case AUDIO_SOURCE_FM_TUNER: case AUDIO_SOURCE_ECHO_REFERENCE: case AUDIO_SOURCE_REMOTE_SUBMIX: return false; default: break; } return true; } } // static sp<OpRecordAudioMonitor> OpRecordAudioMonitor::createIfNeeded( const AttributionSourceState& attributionSource, const audio_attributes_t& attr, wp<AudioPolicyService::AudioCommandThread> commandThread) { if (isAudioServerOrRootUid(attributionSource.uid)) { ALOGV("not silencing record for audio or root source %s", attributionSource.toString().c_str()); return nullptr; } if (!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); } OpRecordAudioMonitor::OpRecordAudioMonitor( const AttributionSourceState& attributionSource, int32_t appOp, wp<AudioPolicyService::AudioCommandThread> commandThread) : mHasOp(true), mAttributionSource(attributionSource), mAppOp(appOp), mCommandThread(commandThread) { } OpRecordAudioMonitor::~OpRecordAudioMonitor() { if (mOpCallback != 0) { mAppOpsManager.stopWatchingMode(mOpCallback); } mOpCallback.clear(); } void 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(""))), AppOpsManager::WATCH_FOREGROUND_CHANGES, mOpCallback); } bool 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 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<AudioPolicyService::AudioCommandThread> commandThread = mCommandThread.promote(); if (commandThread != nullptr) { commandThread->updateUidStatesCommand(); } } } OpRecordAudioMonitor::RecordAudioOpCallback::RecordAudioOpCallback( const wp<OpRecordAudioMonitor>& monitor) : mMonitor(monitor) { } void 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); } } } // android::media::audiopolicy::internal Loading
services/audiopolicy/service/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ cc_library { ], srcs: [ "AudioRecordClient.cpp", "AudioPolicyClientImpl.cpp", "AudioPolicyEffects.cpp", "AudioPolicyInterfaceImpl.cpp", Loading
services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ //#define LOG_NDEBUG 0 #include "AudioPolicyService.h" #include "AudioRecordClient.h" #include "TypeConverter.h" #include <media/AidlConversion.h> #include <media/AudioPolicy.h> Loading
services/audiopolicy/service/AudioPolicyService.cpp +1 −117 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ #include <binder/IResultReceiver.h> #include <utils/String16.h> #include <utils/threads.h> #include "AudioRecordClient.h" #include "AudioPolicyService.h" #include <hardware_legacy/power.h> #include <media/AidlConversion.h> Loading Loading @@ -1164,20 +1165,6 @@ 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: case AUDIO_SOURCE_REMOTE_SUBMIX: return false; default: break; } return true; } void AudioPolicyService::setAppState_l(sp<AudioRecordClient> client, app_state_t state) { AutoCallerClear acc; Loading Loading @@ -1878,109 +1865,6 @@ binder::Status AudioPolicyService::SensorPrivacyPolicy::onSensorPrivacyChanged( 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 (isAudioServerOrRootUid(attributionSource.uid)) { ALOGV("not silencing record for audio or root source %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
services/audiopolicy/service/AudioPolicyService.h +9 −77 Original line number Diff line number Diff line /* * Copyright (C) 2009 The Android Open Source Project * Loading Loading @@ -28,7 +27,6 @@ #include <utils/Vector.h> #include <utils/SortedVector.h> #include <binder/ActivityManager.h> #include <binder/AppOpsManager.h> #include <binder/BinderService.h> #include <binder/IUidObserver.h> #include <system/audio.h> Loading Loading @@ -64,6 +62,12 @@ using media::audio::common::Int; // ---------------------------------------------------------------------------- namespace media::audiopolicy { class AudioRecordClient; } using ::android::media::audiopolicy::AudioRecordClient; class AudioPolicyService : public BinderService<AudioPolicyService>, public media::BnAudioPolicyService, Loading Loading @@ -401,7 +405,6 @@ private: // Handles binder shell commands virtual status_t shellCommand(int in, int out, int err, Vector<String16>& args); class AudioRecordClient; // Sets whether the given UID records only silence virtual void setAppState_l(sp<AudioRecordClient> client, app_state_t state) REQUIRES(mLock); Loading Loading @@ -542,6 +545,7 @@ private: // Thread used to send audio config commands to audio flinger // For audio config commands, it is necessary because audio flinger requires that the calling // process (user) has permission to modify audio settings. public: class AudioCommandThread : public Thread { class AudioCommand; public: Loading Loading @@ -732,6 +736,7 @@ private: wp<AudioPolicyService> mService; }; private: class AudioPolicyClient : public AudioPolicyClientInterface { public: Loading Loading @@ -906,6 +911,7 @@ private: bool mAudioVolumeGroupCallbacksEnabled; }; public: class AudioClient : public virtual RefBase { public: AudioClient(const audio_attributes_t attributes, Loading @@ -927,82 +933,8 @@ private: const audio_port_handle_t deviceId; // selected input device port ID bool active; // Playback/Capture is active or inactive }; // Checks and monitors app ops for AudioRecordClient 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, wp<AudioCommandThread> commandThread); private: OpRecordAudioMonitor(const AttributionSourceState& attributionSource, int32_t appOp, wp<AudioCommandThread> commandThread); 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() // updateUidStates is true when the silenced state of active AudioRecordClients must be // re-evaluated void checkOp(bool updateUidStates = false); std::atomic_bool mHasOp; const AttributionSourceState mAttributionSource; const int32_t mAppOp; wp<AudioCommandThread> mCommandThread; }; // --- AudioRecordClient --- // Information about each registered AudioRecord client // (between calls to getInputForAttr() and releaseInput()) class AudioRecordClient : public AudioClient { public: AudioRecordClient(const audio_attributes_t attributes, const audio_io_handle_t io, const audio_session_t session, audio_port_handle_t portId, const audio_port_handle_t deviceId, const AttributionSourceState& attributionSource, bool canCaptureOutput, bool canCaptureHotword, wp<AudioCommandThread> commandThread) : AudioClient(attributes, io, attributionSource, session, portId, deviceId), attributionSource(attributionSource), startTimeNs(0), canCaptureOutput(canCaptureOutput), canCaptureHotword(canCaptureHotword), silenced(false), mOpRecordAudioMonitor( OpRecordAudioMonitor::createIfNeeded(attributionSource, attributes, commandThread)) {} ~AudioRecordClient() override = default; bool hasOp() const { return mOpRecordAudioMonitor ? mOpRecordAudioMonitor->hasOp() : true; } const AttributionSourceState attributionSource; // attribution source of client nsecs_t startTimeNs; const bool canCaptureOutput; const bool canCaptureHotword; bool silenced; private: sp<OpRecordAudioMonitor> mOpRecordAudioMonitor; }; // --- AudioPlaybackClient --- Loading
services/audiopolicy/service/AudioRecordClient.cpp 0 → 100644 +140 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "AudioRecordClient.h" #include "AudioPolicyService.h" namespace android::media::audiopolicy { using android::AudioPolicyService; namespace { bool isAppOpSource(audio_source_t source) { switch (source) { case AUDIO_SOURCE_FM_TUNER: case AUDIO_SOURCE_ECHO_REFERENCE: case AUDIO_SOURCE_REMOTE_SUBMIX: return false; default: break; } return true; } } // static sp<OpRecordAudioMonitor> OpRecordAudioMonitor::createIfNeeded( const AttributionSourceState& attributionSource, const audio_attributes_t& attr, wp<AudioPolicyService::AudioCommandThread> commandThread) { if (isAudioServerOrRootUid(attributionSource.uid)) { ALOGV("not silencing record for audio or root source %s", attributionSource.toString().c_str()); return nullptr; } if (!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); } OpRecordAudioMonitor::OpRecordAudioMonitor( const AttributionSourceState& attributionSource, int32_t appOp, wp<AudioPolicyService::AudioCommandThread> commandThread) : mHasOp(true), mAttributionSource(attributionSource), mAppOp(appOp), mCommandThread(commandThread) { } OpRecordAudioMonitor::~OpRecordAudioMonitor() { if (mOpCallback != 0) { mAppOpsManager.stopWatchingMode(mOpCallback); } mOpCallback.clear(); } void 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(""))), AppOpsManager::WATCH_FOREGROUND_CHANGES, mOpCallback); } bool 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 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<AudioPolicyService::AudioCommandThread> commandThread = mCommandThread.promote(); if (commandThread != nullptr) { commandThread->updateUidStatesCommand(); } } } OpRecordAudioMonitor::RecordAudioOpCallback::RecordAudioOpCallback( const wp<OpRecordAudioMonitor>& monitor) : mMonitor(monitor) { } void 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); } } } // android::media::audiopolicy::internal