Loading services/audioflinger/IAfTrack.h +27 −5 Original line number Diff line number Diff line Loading @@ -269,6 +269,12 @@ class AfPlaybackCommon : public virtual VolumePortInterface { using AppOpsSession = media::permission::AppOpsSession<media::permission::DefaultAppOpsFacade>; public: enum class EnforcementLevel { NONE, // no enforcement PARTIAL, // enforcement for CONTROL_PARTIAL FULL, // enforcement for CONTROL }; AfPlaybackCommon(IAfTrackBase& self, IAfThreadBase& thread, float volume, bool muted, const audio_attributes_t& attr, const AttributionSourceState& attributionSource, Loading @@ -284,11 +290,25 @@ class AfPlaybackCommon : public virtual VolumePortInterface { // Restricted due to OP_AUDIO_CONTROL_PARTIAL bool hasOpControlPartial() const { return mOpControlSession ? mHasOpControlPartial.load(std::memory_order_acquire) : true; return mOpControlPartialSession ? mHasOpControlPartial.load(std::memory_order_acquire) : true; } // Restricted due to OP_AUDIO_CONTROL bool hasOpControlFull() const { return mOpControlFullSession ? mHasOpControlFull.load(std::memory_order_acquire) : true; } bool isPlaybackRestrictedControl() const { return !(mIsExemptedFromOpControl || hasOpControlPartial()); using enum EnforcementLevel; switch (mEnforcementLevel) { case NONE: return false; case PARTIAL: return !hasOpControlPartial(); case FULL: return !hasOpControlFull(); } } // VolumePortInterface implementation Loading Loading @@ -323,13 +343,15 @@ class AfPlaybackCommon : public virtual VolumePortInterface { // associated with port std::atomic<float> mVolume = 0.0f; const bool mIsExemptedFromOpControl; const EnforcementLevel mEnforcementLevel; std::atomic<bool> mHasOpControlPartial {true}; std::atomic<bool> mHasOpControlFull {true}; mutable std::atomic<bool> mPlaybackHardeningLogged {false}; // the ref behind the optional is const // this member is last in decl order to ensure it is destroyed first std::optional<AppOpsSession> mOpControlSession; // these members are last in decl order to ensure it is destroyed first std::optional<AppOpsSession> mOpControlPartialSession; std::optional<AppOpsSession> mOpControlFullSession; }; // Common interface for audioflinger Playback tracks. Loading services/audioflinger/Tracks.cpp +51 −16 Original line number Diff line number Diff line Loading @@ -3687,19 +3687,21 @@ void PassthruPatchRecord::releaseBuffer( // ---------------------------------------------------------------------------- // AfPlaybackCommon static bool shouldExemptFromOpControl(audio_usage_t usage, IAfThreadCallback& cb) { static AfPlaybackCommon::EnforcementLevel getOpControlEnforcementLevel(audio_usage_t usage, IAfThreadCallback& cb) { using enum AfPlaybackCommon::EnforcementLevel; if (cb.isHardeningOverrideEnabled()) { return false; return FULL; } if (hardening_partial()) { switch (usage) { case AUDIO_USAGE_VIRTUAL_SOURCE: return true; default: return media::permission::isSystemUsage(usage); if (usage == AUDIO_USAGE_VIRTUAL_SOURCE || media::permission::isSystemUsage(usage)) { return NONE; } if (hardening_strict()) { return FULL; } else if (hardening_partial()) { return PARTIAL; } else { return true; return NONE; } } Loading @@ -3711,8 +3713,10 @@ AfPlaybackCommon::AfPlaybackCommon(IAfTrackBase& self, IAfThreadBase& thread, fl : mSelf(self), mMutedFromPort(muted), mVolume(volume), mIsExemptedFromOpControl(shouldExemptFromOpControl(attr.usage, *thread.afThreadCallback())) { mEnforcementLevel(getOpControlEnforcementLevel(attr.usage, *thread.afThreadCallback())) { ALOGI("creating track with enforcement level %d", mEnforcementLevel); using AppOpsManager::OP_CONTROL_AUDIO_PARTIAL; using AppOpsManager::OP_CONTROL_AUDIO; using media::permission::Ops; using media::permission::skipOpsForUid; using media::permission::ValidatedAttributionSourceState; Loading @@ -3724,7 +3728,7 @@ AfPlaybackCommon::AfPlaybackCommon(IAfTrackBase& self, IAfThreadBase& thread, fl mExecutor.emplace(); } auto thread_wp = wp<IAfThreadBase>::fromExisting(&thread); mOpControlSession.emplace( mOpControlPartialSession.emplace( ValidatedAttributionSourceState::createFromTrustedSource(attributionSource), Ops{.attributedOp = OP_CONTROL_AUDIO_PARTIAL}, [this, isOffloadOrMmap, thread_wp](bool isPermitted) { Loading @@ -3740,12 +3744,30 @@ AfPlaybackCommon::AfPlaybackCommon(IAfTrackBase& self, IAfThreadBase& thread, fl } } ); // Same as previous but for mHasOpControlFull, OP_CONTROL_AUDIO mOpControlFullSession.emplace( ValidatedAttributionSourceState::createFromTrustedSource(attributionSource), Ops{.attributedOp = OP_CONTROL_AUDIO}, [this, isOffloadOrMmap, thread_wp](bool isPermitted) { mHasOpControlFull.store(isPermitted, std::memory_order_release); if (isOffloadOrMmap) { mExecutor->enqueue(mediautils::Runnable{[thread_wp]() { auto thread = thread_wp.promote(); if (thread != nullptr) { audio_utils::lock_guard l {thread->mutex()}; thread->broadcast_l(); } }}); } } ); } } } void AfPlaybackCommon::maybeLogPlaybackHardening(media::IAudioManagerNative& am) const { using media::IAudioManagerNative::HardeningType::PARTIAL; using media::IAudioManagerNative::HardeningType::FULL; // The op state deviates from if the track is actually muted if the playback was exempted for // some compat reason. // The state could have technically TOCTOU, but this is for metrics and that is very unlikely Loading @@ -3755,6 +3777,12 @@ void AfPlaybackCommon::maybeLogPlaybackHardening(media::IAudioManagerNative& am) /* bypassed= */ !isPlaybackRestrictedControl()); } } else if (!hasOpControlFull()) { if (!mPlaybackHardeningLogged.exchange(true, std::memory_order_acq_rel)) { am.playbackHardeningEvent(mSelf.uid(), FULL, /* bypassed= */ !isPlaybackRestrictedControl()); } } } Loading @@ -3780,15 +3808,22 @@ void AfPlaybackCommon::processMuteEvent(media::IAudioManagerNative& am, mute_sta } void AfPlaybackCommon::startPlaybackDelivery() { if (mOpControlSession) { mHasOpControlPartial.store(mOpControlSession->beginDeliveryRequest(), if (mOpControlPartialSession) { mHasOpControlPartial.store(mOpControlPartialSession->beginDeliveryRequest(), std::memory_order_release); } if (mOpControlFullSession) { mHasOpControlFull.store(mOpControlFullSession->beginDeliveryRequest(), std::memory_order_release); } } void AfPlaybackCommon::endPlaybackDelivery() { if (mOpControlSession) { mOpControlSession->endDeliveryRequest(); if (mOpControlPartialSession) { mOpControlPartialSession->endDeliveryRequest(); } if (mOpControlFullSession) { mOpControlFullSession->endDeliveryRequest(); } } Loading Loading
services/audioflinger/IAfTrack.h +27 −5 Original line number Diff line number Diff line Loading @@ -269,6 +269,12 @@ class AfPlaybackCommon : public virtual VolumePortInterface { using AppOpsSession = media::permission::AppOpsSession<media::permission::DefaultAppOpsFacade>; public: enum class EnforcementLevel { NONE, // no enforcement PARTIAL, // enforcement for CONTROL_PARTIAL FULL, // enforcement for CONTROL }; AfPlaybackCommon(IAfTrackBase& self, IAfThreadBase& thread, float volume, bool muted, const audio_attributes_t& attr, const AttributionSourceState& attributionSource, Loading @@ -284,11 +290,25 @@ class AfPlaybackCommon : public virtual VolumePortInterface { // Restricted due to OP_AUDIO_CONTROL_PARTIAL bool hasOpControlPartial() const { return mOpControlSession ? mHasOpControlPartial.load(std::memory_order_acquire) : true; return mOpControlPartialSession ? mHasOpControlPartial.load(std::memory_order_acquire) : true; } // Restricted due to OP_AUDIO_CONTROL bool hasOpControlFull() const { return mOpControlFullSession ? mHasOpControlFull.load(std::memory_order_acquire) : true; } bool isPlaybackRestrictedControl() const { return !(mIsExemptedFromOpControl || hasOpControlPartial()); using enum EnforcementLevel; switch (mEnforcementLevel) { case NONE: return false; case PARTIAL: return !hasOpControlPartial(); case FULL: return !hasOpControlFull(); } } // VolumePortInterface implementation Loading Loading @@ -323,13 +343,15 @@ class AfPlaybackCommon : public virtual VolumePortInterface { // associated with port std::atomic<float> mVolume = 0.0f; const bool mIsExemptedFromOpControl; const EnforcementLevel mEnforcementLevel; std::atomic<bool> mHasOpControlPartial {true}; std::atomic<bool> mHasOpControlFull {true}; mutable std::atomic<bool> mPlaybackHardeningLogged {false}; // the ref behind the optional is const // this member is last in decl order to ensure it is destroyed first std::optional<AppOpsSession> mOpControlSession; // these members are last in decl order to ensure it is destroyed first std::optional<AppOpsSession> mOpControlPartialSession; std::optional<AppOpsSession> mOpControlFullSession; }; // Common interface for audioflinger Playback tracks. Loading
services/audioflinger/Tracks.cpp +51 −16 Original line number Diff line number Diff line Loading @@ -3687,19 +3687,21 @@ void PassthruPatchRecord::releaseBuffer( // ---------------------------------------------------------------------------- // AfPlaybackCommon static bool shouldExemptFromOpControl(audio_usage_t usage, IAfThreadCallback& cb) { static AfPlaybackCommon::EnforcementLevel getOpControlEnforcementLevel(audio_usage_t usage, IAfThreadCallback& cb) { using enum AfPlaybackCommon::EnforcementLevel; if (cb.isHardeningOverrideEnabled()) { return false; return FULL; } if (hardening_partial()) { switch (usage) { case AUDIO_USAGE_VIRTUAL_SOURCE: return true; default: return media::permission::isSystemUsage(usage); if (usage == AUDIO_USAGE_VIRTUAL_SOURCE || media::permission::isSystemUsage(usage)) { return NONE; } if (hardening_strict()) { return FULL; } else if (hardening_partial()) { return PARTIAL; } else { return true; return NONE; } } Loading @@ -3711,8 +3713,10 @@ AfPlaybackCommon::AfPlaybackCommon(IAfTrackBase& self, IAfThreadBase& thread, fl : mSelf(self), mMutedFromPort(muted), mVolume(volume), mIsExemptedFromOpControl(shouldExemptFromOpControl(attr.usage, *thread.afThreadCallback())) { mEnforcementLevel(getOpControlEnforcementLevel(attr.usage, *thread.afThreadCallback())) { ALOGI("creating track with enforcement level %d", mEnforcementLevel); using AppOpsManager::OP_CONTROL_AUDIO_PARTIAL; using AppOpsManager::OP_CONTROL_AUDIO; using media::permission::Ops; using media::permission::skipOpsForUid; using media::permission::ValidatedAttributionSourceState; Loading @@ -3724,7 +3728,7 @@ AfPlaybackCommon::AfPlaybackCommon(IAfTrackBase& self, IAfThreadBase& thread, fl mExecutor.emplace(); } auto thread_wp = wp<IAfThreadBase>::fromExisting(&thread); mOpControlSession.emplace( mOpControlPartialSession.emplace( ValidatedAttributionSourceState::createFromTrustedSource(attributionSource), Ops{.attributedOp = OP_CONTROL_AUDIO_PARTIAL}, [this, isOffloadOrMmap, thread_wp](bool isPermitted) { Loading @@ -3740,12 +3744,30 @@ AfPlaybackCommon::AfPlaybackCommon(IAfTrackBase& self, IAfThreadBase& thread, fl } } ); // Same as previous but for mHasOpControlFull, OP_CONTROL_AUDIO mOpControlFullSession.emplace( ValidatedAttributionSourceState::createFromTrustedSource(attributionSource), Ops{.attributedOp = OP_CONTROL_AUDIO}, [this, isOffloadOrMmap, thread_wp](bool isPermitted) { mHasOpControlFull.store(isPermitted, std::memory_order_release); if (isOffloadOrMmap) { mExecutor->enqueue(mediautils::Runnable{[thread_wp]() { auto thread = thread_wp.promote(); if (thread != nullptr) { audio_utils::lock_guard l {thread->mutex()}; thread->broadcast_l(); } }}); } } ); } } } void AfPlaybackCommon::maybeLogPlaybackHardening(media::IAudioManagerNative& am) const { using media::IAudioManagerNative::HardeningType::PARTIAL; using media::IAudioManagerNative::HardeningType::FULL; // The op state deviates from if the track is actually muted if the playback was exempted for // some compat reason. // The state could have technically TOCTOU, but this is for metrics and that is very unlikely Loading @@ -3755,6 +3777,12 @@ void AfPlaybackCommon::maybeLogPlaybackHardening(media::IAudioManagerNative& am) /* bypassed= */ !isPlaybackRestrictedControl()); } } else if (!hasOpControlFull()) { if (!mPlaybackHardeningLogged.exchange(true, std::memory_order_acq_rel)) { am.playbackHardeningEvent(mSelf.uid(), FULL, /* bypassed= */ !isPlaybackRestrictedControl()); } } } Loading @@ -3780,15 +3808,22 @@ void AfPlaybackCommon::processMuteEvent(media::IAudioManagerNative& am, mute_sta } void AfPlaybackCommon::startPlaybackDelivery() { if (mOpControlSession) { mHasOpControlPartial.store(mOpControlSession->beginDeliveryRequest(), if (mOpControlPartialSession) { mHasOpControlPartial.store(mOpControlPartialSession->beginDeliveryRequest(), std::memory_order_release); } if (mOpControlFullSession) { mHasOpControlFull.store(mOpControlFullSession->beginDeliveryRequest(), std::memory_order_release); } } void AfPlaybackCommon::endPlaybackDelivery() { if (mOpControlSession) { mOpControlSession->endDeliveryRequest(); if (mOpControlPartialSession) { mOpControlPartialSession->endDeliveryRequest(); } if (mOpControlFullSession) { mOpControlFullSession->endDeliveryRequest(); } } Loading