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

Commit f7e3a3a2 authored by Mikhail Naganov's avatar Mikhail Naganov
Browse files

audioflinger: Fix reference counting protocol in OpPlayAudioMonitor

OpPlayAudioMonitor was constructing a weak pointer to itself
in the constructor. This practice can lead to crashes due to
race conditions vs object destruction. This code is now moved
to onFirstRef method which is called when at least one strong
reference exists.

This change also reduces the number of created OpPlayAudioMonitor
objects by using a factory method.

Bug: 130038586
Test: enable / disable DND mode
Change-Id: I22e63a883ebaa25b9c96e79271bb9693b5ed75cd
parent 3208826f
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -22,11 +22,16 @@
// Checks and monitors OP_PLAY_AUDIO
class OpPlayAudioMonitor : public RefBase {
public:
    OpPlayAudioMonitor(uid_t uid, audio_usage_t usage, int id, audio_stream_type_t streamType);
    ~OpPlayAudioMonitor() override;
    bool hasOpPlayAudio() const;

    static sp<OpPlayAudioMonitor> createIfNeeded(
            uid_t uid, audio_usage_t usage, int id, audio_stream_type_t streamType);

private:
    OpPlayAudioMonitor(uid_t uid, audio_usage_t usage, int id);
    void onFirstRef() override;

    AppOpsManager mAppOpsManager;

    class PlayAudioOpCallback : public BnAppOpsCallback {
@@ -209,7 +214,9 @@ public:

    int fastIndex() const { return mFastIndex; }

    bool isPlaybackRestricted() const { return !mOpPlayAudioMonitor->hasOpPlayAudio(); }
    bool isPlaybackRestricted() const {
        // The monitor is only created for tracks that can be silenced.
        return mOpPlayAudioMonitor ? !mOpPlayAudioMonitor->hasOpPlayAudio() : false; }

protected:

+28 −15
Original line number Diff line number Diff line
@@ -381,26 +381,28 @@ status_t AudioFlinger::TrackHandle::onTransact(
// ----------------------------------------------------------------------------
//      AppOp for audio playback
// -------------------------------
AudioFlinger::PlaybackThread::OpPlayAudioMonitor::OpPlayAudioMonitor(uid_t uid, audio_usage_t usage,
        int id, audio_stream_type_t streamType)
            : mHasOpPlayAudio(true), mUid(uid), mUsage((int32_t) usage), mId(id)

// static
sp<AudioFlinger::PlaybackThread::OpPlayAudioMonitor>
AudioFlinger::PlaybackThread::OpPlayAudioMonitor::createIfNeeded(
            uid_t uid, audio_usage_t usage, int id, audio_stream_type_t streamType)
{
    if (isAudioServerOrRootUid(uid)) {
        ALOGD("OpPlayAudio: not muting track:%d usage:%d root or audioserver", mId, usage);
        return;
        ALOGD("OpPlayAudio: not muting track:%d usage:%d root or audioserver", id, usage);
        return nullptr;
    }
    // stream type has been filtered by audio policy to indicate whether it can be muted
    if (streamType == AUDIO_STREAM_ENFORCED_AUDIBLE) {
        ALOGD("OpPlayAudio: not muting track:%d usage:%d ENFORCED_AUDIBLE", mId, usage);
        return;
        ALOGD("OpPlayAudio: not muting track:%d usage:%d ENFORCED_AUDIBLE", id, usage);
        return nullptr;
    }
    PermissionController permissionController;
    permissionController.getPackagesForUid(uid, mPackages);
    checkPlayAudioForUsage();
    if (!mPackages.isEmpty()) {
        mOpCallback = new PlayAudioOpCallback(this);
        mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO, mPackages[0], mOpCallback);
    return new OpPlayAudioMonitor(uid, usage, id);
}

AudioFlinger::PlaybackThread::OpPlayAudioMonitor::OpPlayAudioMonitor(
        uid_t uid, audio_usage_t usage, int id)
        : mHasOpPlayAudio(true), mUid(uid), mUsage((int32_t) usage), mId(id)
{
}

AudioFlinger::PlaybackThread::OpPlayAudioMonitor::~OpPlayAudioMonitor()
@@ -411,6 +413,17 @@ AudioFlinger::PlaybackThread::OpPlayAudioMonitor::~OpPlayAudioMonitor()
    mOpCallback.clear();
}

void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::onFirstRef()
{
    PermissionController permissionController;
    permissionController.getPackagesForUid(mUid, mPackages);
    checkPlayAudioForUsage();
    if (!mPackages.isEmpty()) {
        mOpCallback = new PlayAudioOpCallback(this);
        mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO, mPackages[0], mOpCallback);
    }
}

bool AudioFlinger::PlaybackThread::OpPlayAudioMonitor::hasOpPlayAudio() const {
    return mHasOpPlayAudio.load();
}
@@ -492,7 +505,7 @@ AudioFlinger::PlaybackThread::Track::Track(
    mPresentationCompleteFrames(0),
    mFrameMap(16 /* sink-frame-to-track-frame map memory */),
    mVolumeHandler(new media::VolumeHandler(sampleRate)),
    mOpPlayAudioMonitor(new OpPlayAudioMonitor(uid, attr.usage, id(), streamType)),
    mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(uid, attr.usage, id(), streamType)),
    // mSinkTimestamp
    mFastIndex(-1),
    mCachedVolume(1.0),