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

Commit aee6ee94 authored by Jean-Michel Trivi's avatar Jean-Michel Trivi
Browse files

IAppOpsCallback has weak reference to PlayerBase

The implementation of the IAppOpsCallback interface was an inner class
  that implicitly held a strong reference to the PlayerBase
  instance, preventing subclasses of PlayerBase to be GC'd.
The fix consists in making the IAppOpsCallback implementation be a static
  class and hold a weak reference to PlayerBase.

Test: see bug
Bug: 35359144

Change-Id: Ic97d07dad0be2376eef160d01ff4e4a9e5ee0bcd
parent cf1b224a
Loading
Loading
Loading
Loading
+33 −17
Original line number Original line Diff line number Diff line
@@ -46,11 +46,11 @@ import java.util.Objects;
 */
 */
public abstract class PlayerBase {
public abstract class PlayerBase {


    private final static String TAG = "PlayerBase";
    private static final String TAG = "PlayerBase";
    private final static boolean DEBUG = false;
    private static final boolean DEBUG = false;
    private static IAudioService sService; //lazy initialization, use getService()
    private static IAudioService sService; //lazy initialization, use getService()
    /** Debug app ops */
    /** Debug app ops */
    protected static final boolean DEBUG_APP_OPS = Log.isLoggable(TAG + ".AO", Log.DEBUG);
    private static final boolean DEBUG_APP_OPS = false;


    // parameters of the player that affect AppOps
    // parameters of the player that affect AppOps
    protected AudioAttributes mAttributes;
    protected AudioAttributes mAttributes;
@@ -95,19 +95,9 @@ public abstract class PlayerBase {
        IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE);
        IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE);
        mAppOps = IAppOpsService.Stub.asInterface(b);
        mAppOps = IAppOpsService.Stub.asInterface(b);
        // initialize mHasAppOpsPlayAudio
        // initialize mHasAppOpsPlayAudio
        synchronized (mLock) {
        updateAppOpsPlayAudio();
            updateAppOpsPlayAudio_sync();
        }
        // register a callback to monitor whether the OP_PLAY_AUDIO is still allowed
        // register a callback to monitor whether the OP_PLAY_AUDIO is still allowed
        mAppOpsCallback = new IAppOpsCallback.Stub() {
        mAppOpsCallback = new IAppOpsCallbackWrapper(this);
            public void opChanged(int op, int uid, String packageName) {
                synchronized (mLock) {
                    if (op == AppOpsManager.OP_PLAY_AUDIO) {
                        updateAppOpsPlayAudio_sync();
                    }
                }
            }
        };
        try {
        try {
            mAppOps.startWatchingMode(AppOpsManager.OP_PLAY_AUDIO,
            mAppOps.startWatchingMode(AppOpsManager.OP_PLAY_AUDIO,
                    ActivityThread.currentPackageName(), mAppOpsCallback);
                    ActivityThread.currentPackageName(), mAppOpsCallback);
@@ -258,6 +248,12 @@ public abstract class PlayerBase {
        }
        }
    }
    }


    private void updateAppOpsPlayAudio() {
        synchronized (mLock) {
            updateAppOpsPlayAudio_sync();
        }
    }

    /**
    /**
     * To be called whenever a condition that might affect audibility of this player is updated.
     * To be called whenever a condition that might affect audibility of this player is updated.
     * Must be called synchronized on mLock.
     * Must be called synchronized on mLock.
@@ -404,6 +400,26 @@ public abstract class PlayerBase {
    abstract void playerPause();
    abstract void playerPause();
    abstract void playerStop();
    abstract void playerStop();


    //=====================================================================
    private static class IAppOpsCallbackWrapper extends IAppOpsCallback.Stub {
        private final WeakReference<PlayerBase> mWeakPB;

        public IAppOpsCallbackWrapper(PlayerBase pb) {
            mWeakPB = new WeakReference<PlayerBase>(pb);
        }

        @Override
        public void opChanged(int op, int uid, String packageName) {
            if (op == AppOpsManager.OP_PLAY_AUDIO) {
                if (DEBUG_APP_OPS) { Log.v(TAG, "opChanged: op=PLAY_AUDIO pack=" + packageName); }
                final PlayerBase pb = mWeakPB.get();
                if (pb != null) {
                    pb.updateAppOpsPlayAudio();
                }
            }
        }
    }

    //=====================================================================
    //=====================================================================
    /**
    /**
     * Wrapper around an implementation of IPlayer for all subclasses of PlayerBase
     * Wrapper around an implementation of IPlayer for all subclasses of PlayerBase
@@ -482,8 +498,8 @@ public abstract class PlayerBase {
    public static class PlayerIdCard implements Parcelable {
    public static class PlayerIdCard implements Parcelable {
        public final int mPlayerType;
        public final int mPlayerType;


        public final static int AUDIO_ATTRIBUTES_NONE = 0;
        public static final int AUDIO_ATTRIBUTES_NONE = 0;
        public final static int AUDIO_ATTRIBUTES_DEFINED = 1;
        public static final int AUDIO_ATTRIBUTES_DEFINED = 1;
        public final AudioAttributes mAttributes;
        public final AudioAttributes mAttributes;
        public final IPlayer mIPlayer;
        public final IPlayer mIPlayer;