Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 050f0a55 authored by Atneya Nair's avatar Atneya Nair Committed by Android (Google) Code Review
Browse files

Merge "[audio] Add playback hardening for MMAP" into main

parents ccd3cf62 c42bcfe8
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -511,6 +511,10 @@ public:
    // protected by MMapThread::mLock
    virtual bool getAndSetSilencedNotified_l() = 0;

    // TODO(b/241533526): Refactor shared logic between MMAP and legacy
    virtual bool isPlaybackRestrictedControl() const = 0;
    virtual void maybeLogPlaybackHardening(media::IAudioManagerNative& am) const = 0;

    /**
     * Updates the mute state and notifies the audio service. Call this only when holding player
     * thread lock.
+23 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include "TrackBase.h"

#include <android/content/AttributionSourceState.h>
#include <media/AppOpsSession.h>

namespace android {

@@ -60,6 +61,18 @@ public:
                                                        mSilencedNotified = true;
                                                        return silencedNotified; }

    // The following functions are duplicated from PlaybackTrack
    // TODO(b/241533526) refactor common code
    bool hasOpControlPartial() const {
        return mOpControlSession ? mHasOpControlPartial.load(std::memory_order_acquire) : true;
    }

    bool isPlaybackRestrictedControl() const final {
        return !(mIsExemptedFromOpControl || hasOpControlPartial());
    }

    void maybeLogPlaybackHardening(media::IAudioManagerNative& am) const final;

    /**
     * Updates the mute state and notifies the audio service. Call this only when holding player
     * thread lock.
@@ -105,6 +118,16 @@ private:
    bool mMutedFromPort;

    float mVolume = 0.0f;

    // logically const
    std::optional<media::permission::AppOpsSession<media::permission::DefaultAppOpsFacade>>
            mOpControlSession;

    // logically const
    bool mIsExemptedFromOpControl = false;
    std::atomic<bool> mHasOpControlPartial {true};
    mutable std::atomic<bool> mPlaybackHardeningLogged {false};

};  // end of Track

} // namespace android
+22 −5
Original line number Diff line number Diff line
@@ -10641,9 +10641,13 @@ status_t MmapThread::start(const AudioClient& client,
    sp<IAfMmapTrack> track = IAfMmapTrack::create(
            this, attr == nullptr ? mAttr : *attr, mSampleRate, mFormat,
                                        mChannelMask, mSessionId, isOutput(),
                                        client.attributionSource,
                                        adjAttributionSource,
                                        IPCThreadState::self()->getCallingPid(), portId,
                                        volume, muted);

    // MMAP tracks are only created when they are started, so mark them as Start for the purposes
    // of the IAfTrackBase interface
    track->start();
    if (!isOutput()) {
        track->setSilenced_l(isClientSilenced_l(portId));
    }
@@ -10654,7 +10658,7 @@ status_t MmapThread::start(const AudioClient& client,
    } else if (!track->isSilenced_l()) {
        for (const sp<IAfMmapTrack>& t : mActiveTracks) {
            if (t->isSilenced_l()
                    && t->uid() != static_cast<uid_t>(client.attributionSource.uid)) {
                    && t->uid() != static_cast<uid_t>(adjAttributionSource.uid)) {
                t->invalidate();
            }
        }
@@ -10709,6 +10713,7 @@ status_t MmapThread::stop(audio_port_handle_t handle)

    mActiveTracks.remove(track);
    eraseClientSilencedState_l(track->portId());
    track->stop();

    mutex().unlock();
    if (isOutput()) {
@@ -11403,6 +11408,13 @@ NO_THREAD_SAFETY_ANALYSIS // access of track->processMuteEvent_l
            }
        }
    }

    bool shouldMutePlaybackHardening = std::all_of(mActiveTracks.begin(), mActiveTracks.end(),
            [](const auto& x) { return x->isPlaybackRestrictedControl(); });
    if (shouldMutePlaybackHardening) {
        volume = 0;
    }

    if (volume != mHalVolFloat) {
        // Convert volumes from float to 8.24
        uint32_t vol = (uint32_t)(volume * (1 << 24));
@@ -11444,7 +11456,8 @@ NO_THREAD_SAFETY_ANALYSIS // access of track->processMuteEvent_l
                        false /*muteFromPlaybackRestricted*/,
                        false /*muteFromClientVolume*/,
                        false /*muteFromVolumeShaper*/,
                        false /*muteFromPortVolume*/});
                        false /*muteFromPortVolume*/,
                        shouldMutePlaybackHardening});
            } else {
                track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
                    /*muteState=*/{mMasterMute,
@@ -11454,8 +11467,12 @@ NO_THREAD_SAFETY_ANALYSIS // access of track->processMuteEvent_l
                                   false /*muteFromPlaybackRestricted*/,
                                   false /*muteFromClientVolume*/,
                                   false /*muteFromVolumeShaper*/,
                                   track->getPortMute()});
                                   track->getPortMute(),
                                   shouldMutePlaybackHardening});
            }
            track->maybeLogPlaybackHardening(
                    *mAfThreadCallback->getOrCreateAudioManager()->getNativeInterface());

        }
    }
}
+42 −3
Original line number Diff line number Diff line
@@ -1916,8 +1916,8 @@ void Track::maybeLogPlaybackHardening(media::IAudioManagerNative& am) const {
                                      !isPlaybackRestrictedControl());
        }
    }

}

// must be called with player thread lock held
void Track::processMuteEvent_l(const sp<
    IAudioManager>& audioManager, mute_state_t muteState)
@@ -3821,6 +3821,24 @@ MmapTrack::MmapTrack(IAfThreadBase* thread,
        mUid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid))),
            mSilenced(false), mSilencedNotified(false), mVolume(volume)
{
    using media::permission::ValidatedAttributionSourceState;
    using media::permission::Ops;
    if (hardening_impl()) {
        // Don't bother for trusted uids
        if (!media::permission::skipOpsForUid(attributionSource.uid)) {
            mOpControlSession.emplace(
                ValidatedAttributionSourceState::createFromTrustedSource(attributionSource),
                Ops { .attributedOp = AppOpsManager::OP_CONTROL_AUDIO_PARTIAL },
                [this]
                (bool isPermitted) {
                    mHasOpControlPartial.store(isPermitted, std::memory_order_release);
                    signal();
                }
            );
            mIsExemptedFromOpControl = shouldExemptFromOpControl(attr.usage);
        }
    }

    mMutedFromPort = muted;
    // Once this item is logged by the server, the client can add properties.
    mTrackMetrics.logConstructor(creatorPid, uid(), id());
@@ -3844,6 +3862,10 @@ status_t MmapTrack::initCheck() const
status_t MmapTrack::start(AudioSystem::sync_event_t event __unused,
                                                    audio_session_t triggerSession __unused)
{
    if (mOpControlSession) {
        mHasOpControlPartial.store(mOpControlSession->beginDeliveryRequest(),
                            std::memory_order_release);
    }
    if (ATRACE_ENABLED()) [[unlikely]] {
        ATRACE_INSTANT_FOR_TRACK(mTraceActionId.c_str(), audio_utils::trace::Object{}
                .set(AUDIO_TRACE_OBJECT_KEY_EVENT, AUDIO_TRACE_EVENT_START)
@@ -3854,6 +3876,9 @@ status_t MmapTrack::start(AudioSystem::sync_event_t event __unused,

void MmapTrack::stop()
{
    if (mOpControlSession) {
        mOpControlSession->endDeliveryRequest();
    }
    if (ATRACE_ENABLED()) [[unlikely]] {
        ATRACE_INSTANT_FOR_TRACK(mTraceActionId.c_str(), audio_utils::trace::Object{}
                .set(AUDIO_TRACE_OBJECT_KEY_EVENT, AUDIO_TRACE_EVENT_STOP)
@@ -3883,6 +3908,20 @@ void MmapTrack::onTimestamp(const ExtendedTimestamp& timestamp __unused)
{
}

void MmapTrack::maybeLogPlaybackHardening(media::IAudioManagerNative& am) const {
    using media::IAudioManagerNative::HardeningType::PARTIAL;
    // 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
    if (!hasOpControlPartial()) {
        if (!mPlaybackHardeningLogged.exchange(true, std::memory_order_acq_rel)) {
            am.playbackHardeningEvent(uid(), PARTIAL,
                                      /* bypassed= */
                                      !isPlaybackRestrictedControl());
        }
    }
}

void MmapTrack::processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState)
{
    if (mMuteState == muteState) {