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

Commit 9a375d71 authored by Atneya Nair's avatar Atneya Nair
Browse files

[audio] Refactor shared track logic

MMAP tracks currently don't inherit from the IAfTrack interface, so
there is duplication between MmapTrack and Track.

Pull out common logic into AfPlaybackCommon, which represents operations
associated with playback tracks which aren't tied to the audioflinger
mix/data-path implementation. The track interfaces directly inherit from
this class (virtually) so that these operations are accessible from the
associated threads.

 - playback hardening
 - port volumes/port mute
 - mute event notifications to AudioService

Bug: 241533526
Flag: EXEMPT mechanical refactor
Test: Oboe tester playback hardening MMAP and legacy
Test: dumpsys audio for mute events
Change-Id: I8de2d48b94b46fa0111622fb6856153ec067db25
parent 8623bbd9
Loading
Loading
Loading
Loading
+75 −31
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <audio_utils/mutex.h>
#include <audiomanager/IAudioManager.h>
#include <binder/IMemory.h>
#include <media/AppOpsSession.h>
#include <datapath/VolumePortInterface.h>
#include <fastpath/FastMixerDumpState.h>
#include <media/AudioSystem.h>
@@ -259,8 +260,79 @@ public:
    virtual bool isStopping_2() const = 0;
};

// Common interface for Playback tracks.
class IAfTrack : public virtual IAfTrackBase, public virtual VolumePortInterface {
// Functionality shared between MMAP and audioflinger datapath playback tracks. Note that MMAP
// tracks don't implement the IAfTrack, just IAfTrackBase
// Not a pure interface since no forward declaration necessary.
class AfPlaybackCommon : public virtual VolumePortInterface {
    using AppOpsSession = media::permission::AppOpsSession<media::permission::DefaultAppOpsFacade>;

  public:
    AfPlaybackCommon(
            IAfTrackBase & self, float volume, bool muted, const audio_attributes_t& attr,
            const AttributionSourceState& attributionSource, bool shouldPlaybackHarden = true);

    /**
     * Updates the mute state and notifies the audio service. Call this only when holding player
     * thread lock.
     */
    void processMuteEvent_l(
            const sp<IAudioManager>& audioManager, mute_state_t muteState);

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

    // Restricted due to OP_AUDIO_CONTROL_PARTIAL
    bool hasOpControlPartial() const {
        return mOpControlSession ? mHasOpControlPartial.load(std::memory_order_acquire) : true;
    }

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

    // VolumePortInterface implementation
    // for now the secondary patch tracks will always be not muted
    // TODO(b/388241142): use volume capture rules to forward the vol/mute to patch tracks

    void setPortVolume(float volume) final { mVolume = volume; }

    void setPortMute(bool muted) final {
        mMutedFromPort = muted;
    }

    float getPortVolume() const final { return mVolume; }

    bool getPortMute() const final { return mMutedFromPort; }

  protected:
    // The following methods are for notifying that sonifying playback intends to begin/end
    // for playback hardening purposes.
    // TODO(b/385417236) once mute logic is centralized, the delivery request session should be
    // tied to sonifying playback instead of track start->pause
    void startPlaybackDelivery();
    void endPlaybackDelivery();

  private:
    // non-const for signal
    IAfTrackBase& mSelf;
    // TODO: replace PersistableBundle with own struct
    // access these two variables only when holding player thread lock.
    std::unique_ptr<os::PersistableBundle> mMuteEventExtras;
    // TODO: atomic necessary if underneath thread lock?
    std::atomic<mute_state_t> mMuteState;
    std::atomic<bool> mMutedFromPort;
    // associated with port
    std::atomic<float> mVolume = 0.0f;

    const bool mIsExemptedFromOpControl;

    std::atomic<bool> mHasOpControlPartial {true};
    mutable std::atomic<bool> mPlaybackHardeningLogged {false};
    // the ref behind the optional is const
    std::optional<AppOpsSession> mOpControlSession;
};

// Common interface for audioflinger Playback tracks.
class IAfTrack : public virtual IAfTrackBase, public virtual AfPlaybackCommon {
public:
    // FillingStatus is used for suppressing volume ramp at begin of playing
    enum FillingStatus { FS_INVALID, FS_FILLING, FS_FILLED, FS_ACTIVE };
@@ -382,21 +454,6 @@ public:
    virtual audio_output_flags_t getOutputFlags() const = 0;
    virtual float getSpeed() const = 0;

    /**
     * Inform AudioService of any potential playback restriction due to fg state.
     * Should be called when evaluating playback restrictions due to fg state
     * (see {@link isPlaybackRestrictedControl()}). This function
     * internally checks the OP state and dispatches to AudioService for metrics
     */
    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.
     */
    virtual void processMuteEvent_l(
            const sp<IAudioManager>& audioManager, mute_state_t muteState) = 0;

    virtual void triggerEvents(AudioSystem::sync_event_t type) = 0;

    virtual void disable() = 0;
@@ -407,8 +464,6 @@ public:
    // Restricted due to OP_PLAY_AUDIO
    virtual bool isPlaybackRestrictedOp() const = 0;

    // Restricted due to OP_AUDIO_CONTROL_PARTIAL
    virtual bool isPlaybackRestrictedControl() const = 0;
    virtual bool isPlaybackRestricted() const = 0;

    // Used by thread only
@@ -483,7 +538,7 @@ public:
    virtual ExtendedTimestamp getClientProxyTimestamp() const = 0;
};

class IAfMmapTrack : public virtual IAfTrackBase, public virtual VolumePortInterface {
class IAfMmapTrack : public virtual IAfTrackBase, public virtual AfPlaybackCommon {
public:
    static sp<IAfMmapTrack> create(IAfThreadBase* thread,
            const audio_attributes_t& attr,
@@ -510,17 +565,6 @@ public:
    virtual bool isSilenced_l() const = 0;
    // 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.
     */
    virtual void processMuteEvent_l(  // see IAfTrack
            const sp<IAudioManager>& audioManager, mute_state_t muteState) = 0;
};

class RecordBufferConverter;
+0 −50
Original line number Diff line number Diff line
@@ -61,36 +61,6 @@ 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.
     */
    void processMuteEvent_l(const sp<IAudioManager>& audioManager,
                            mute_state_t muteState)
                            /* REQUIRES(MmapPlaybackThread::mLock) */ final;

    // VolumePortInterface implementation
    void setPortVolume(float volume) override {
        mVolume = volume;
    }
    void setPortMute(bool muted) override {
        mMutedFromPort = muted;
    }
    float getPortVolume() const override { return mVolume; }
    bool getPortMute() const override { return mMutedFromPort; }

    std::string trackFlagsAsString() const final { return {}; }
private:
    DISALLOW_COPY_AND_ASSIGN(MmapTrack);
@@ -108,26 +78,6 @@ private:
    const uid_t mUid;
    bool  mSilenced;            // protected by MMapThread::mLock
    bool  mSilencedNotified;    // protected by MMapThread::mLock

    // TODO: replace PersistableBundle with own struct
    // access these two variables only when holding player thread lock.
    std::unique_ptr<os::PersistableBundle> mMuteEventExtras
            /* GUARDED_BY(MmapPlaybackThread::mLock) */;
    mute_state_t mMuteState
            /* GUARDED_BY(MmapPlaybackThread::mLock) */;
    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
+0 −38
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@
#include <audio_utils/mutex.h>
#include <audio_utils/LinearMap.h>
#include <binder/AppOpsManager.h>
#include <media/AppOpsSession.h>
#include <utils/RWLock.h>

namespace android {
@@ -216,22 +215,9 @@ public:
    bool isSpatialized() const final { return mIsSpatialized; }
    bool isBitPerfect() const final { return mIsBitPerfect; }

    void maybeLogPlaybackHardening(media::IAudioManagerNative& am) const final;
    /**
     * Updates the mute state and notifies the audio service. Call this only when holding player
     * thread lock.
     */
    void processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState) final;

    bool getInternalMute() const final { return mInternalMute; }
    void setInternalMute(bool muted) final { mInternalMute = muted; }

    // VolumePortInterface implementation
    void setPortVolume(float volume) override;
    void setPortMute(bool muted) override;
    float getPortVolume() const override { return mVolume; }
    bool getPortMute() const override { return mMutedFromPort; }

    std::string trackFlagsAsString() const final { return toString(mFlags); }

protected:
@@ -300,14 +286,6 @@ protected:
                       : false;
    }

    bool hasOpControlPartial() const {
        return mOpControlSession ? mHasOpControlPartial.load(std::memory_order_acquire) : true;
    }

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

    bool isPlaybackRestricted() const final {
        return isPlaybackRestrictedOp() || isPlaybackRestrictedControl();
    }
@@ -360,16 +338,6 @@ protected:

    sp<OpPlayAudioMonitor>  mOpPlayAudioMonitor;

    // 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};

    bool                mHapticPlaybackEnabled = false; // indicates haptic playback enabled or not
    // scale to play haptic data
    os::HapticScale mHapticScale = os::HapticScale::mute();
@@ -439,13 +407,7 @@ private:
    const bool          mIsSpatialized;
    const bool          mIsBitPerfect;

    // TODO: replace PersistableBundle with own struct
    // access these two variables only when holding player thread lock.
    std::unique_ptr<os::PersistableBundle> mMuteEventExtras;
    std::atomic<mute_state_t> mMuteState;
    std::atomic<bool>         mMutedFromPort;
    bool                      mInternalMute = false;
    std::atomic<float>        mVolume = 0.0f;
};  // end of Track


+130 −195

File changed.

Preview size limit exceeded, changes collapsed.