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

Commit b6ff015c authored by Atneya Nair's avatar Atneya Nair
Browse files

Add partial audio playback hardening

Silence tracks who don't have OP_CONTROL_AUDIO_PARTIAL, which requires
MODE_FOREGROUND.

Test: CtsMediaAudioPermissionTestCases
Bug: 376481063
Flag: com.android.media.audio.hardening_impl
Change-Id: I5a07d8d8400c19252cabb0cdd70ccb4a02cb0657
parent a079029b
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <audio_utils/mutex.h>
#include <audio_utils/LinearMap.h>
#include <binder/AppOpsManager.h>
#include <media/AppOpsSession.h>
#include <utils/RWLock.h>

namespace android {
@@ -298,8 +299,7 @@ protected:
    }

    bool isPlaybackRestrictedControl() const final {
        return false;
        // return mOpAudioControlSoftMonitor ? !mOpAudioControlSoftMonitor->hasOp() : false;
        return mOpControlSession ? !mHasOpControl.load(std::memory_order_acquire) : false;
    }

    bool isPlaybackRestricted() const final {
@@ -354,6 +354,12 @@ protected:

    sp<OpPlayAudioMonitor>  mOpPlayAudioMonitor;

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

    std::atomic<bool> mHasOpControl {true};

    bool                mHapticPlaybackEnabled = false; // indicates haptic playback enabled or not
    // scale to play haptic data
    os::HapticScale mHapticScale = os::HapticScale::mute();
+45 −0
Original line number Diff line number Diff line
@@ -30,7 +30,9 @@

#include <audio_utils/StringUtils.h>
#include <audio_utils/minifloat.h>
#include <com_android_media_audio.h>
#include <media/AudioValidator.h>
#include <media/AppOpsSession.h>
#include <media/RecordBufferConverter.h>
#include <media/nbaio/Pipe.h>
#include <media/nbaio/PipeReader.h>
@@ -71,8 +73,10 @@ namespace android {

using ::android::aidl_utils::binderStatusFromStatusT;
using binder::Status;
using ::com::android::media::audio::hardening_impl;
using content::AttributionSourceState;
using media::VolumeShaper;

// ----------------------------------------------------------------------------
//      TrackBase
// ----------------------------------------------------------------------------
@@ -926,6 +930,26 @@ Track::Track(
        return;
    }

    using media::permission::ValidatedAttributionSourceState;
    using media::permission::Ops;

    if (hardening_impl()) {
        // Don't bother for non-output tracks and server uids
        if (!media::permission::skipOpsForUid(attributionSource.uid) && type != TYPE_PATCH) {
            mOpControlSession.emplace(
                ValidatedAttributionSourceState::createFromTrustedSource(attributionSource),
                Ops { .attributedOp = AppOpsManager::OP_CONTROL_AUDIO_PARTIAL },
                [this]
                (bool isPermitted) {
                    mHasOpControl.store(isPermitted, std::memory_order_release);
                    if (isOffloaded()) {
                        signal();
                    }
                }
            );
        }
    }

    if (sharedBuffer == 0) {
        mAudioTrackServerProxy = new AudioTrackServerProxy(mCblk, mBuffer, frameCount,
                mFrameSize, !isExternalTrack(), sampleRate);
@@ -1493,6 +1517,13 @@ status_t Track::start(AudioSystem::sync_event_t event __unused,
        status = BAD_VALUE;
    }
    if (status == NO_ERROR) {
        // start OP_AUDIO_CONTROL session for track
        // TODO(b/385417236) once mute logic is centralized, the delivery request session should be
        // tied to sonifying playback instead of track start->pause
        if (mOpControlSession) {
            mHasOpControl.store(mOpControlSession->beginDeliveryRequest(),
                                std::memory_order_release);
        }
        // send format to AudioManager for playback activity monitoring
        const sp<IAudioManager> audioManager =
                thread->afThreadCallback()->getOrCreateAudioManager();
@@ -1554,6 +1585,15 @@ void Track::stop()
        }
        forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->stop(); });
    }
    // TODO(b/385417236)
    // Due to the complexity of state management for offload we do not call endDeliveryRequest().
    // For offload tracks, sonification may continue significantly after the STOP
    // phase begins. Leave the session on-going until the track is eventually
    // destroyed. We continue to allow appop callbacks during STOPPING and STOPPED state.
    // This is suboptimal but harmless.
    if (mOpControlSession && !isOffloaded()) {
        mOpControlSession->endDeliveryRequest();
    }
}

void Track::pause()
@@ -1598,6 +1638,11 @@ void Track::pause()
        // Pausing the TeePatch to avoid a glitch on underrun, at the cost of buffered audio loss.
        forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->pause(); });
    }
    // When stopping a paused track, there will be two endDeliveryRequests. This is tolerated by
    // the implementation.
    if (mOpControlSession) {
        mOpControlSession->endDeliveryRequest();
    }
}

void Track::flush()