From aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ff Mon Sep 17 00:00:00 2001 From: Jean-Michel Trivi Date: Tue, 9 May 2017 16:19:36 -0700 Subject: 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 --- media/java/android/media/PlayerBase.java | 50 +++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java index 72be9f71d3a8..9bd93aa31abf 100644 --- a/media/java/android/media/PlayerBase.java +++ b/media/java/android/media/PlayerBase.java @@ -46,11 +46,11 @@ import java.util.Objects; */ public abstract class PlayerBase { - private final static String TAG = "PlayerBase"; - private final static boolean DEBUG = false; + private static final String TAG = "PlayerBase"; + private static final boolean DEBUG = false; private static IAudioService sService; //lazy initialization, use getService() /** 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 protected AudioAttributes mAttributes; @@ -95,19 +95,9 @@ public abstract class PlayerBase { IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE); mAppOps = IAppOpsService.Stub.asInterface(b); // initialize mHasAppOpsPlayAudio - synchronized (mLock) { - updateAppOpsPlayAudio_sync(); - } + updateAppOpsPlayAudio(); // register a callback to monitor whether the OP_PLAY_AUDIO is still allowed - mAppOpsCallback = new IAppOpsCallback.Stub() { - public void opChanged(int op, int uid, String packageName) { - synchronized (mLock) { - if (op == AppOpsManager.OP_PLAY_AUDIO) { - updateAppOpsPlayAudio_sync(); - } - } - } - }; + mAppOpsCallback = new IAppOpsCallbackWrapper(this); try { mAppOps.startWatchingMode(AppOpsManager.OP_PLAY_AUDIO, 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. * Must be called synchronized on mLock. @@ -404,6 +400,26 @@ public abstract class PlayerBase { abstract void playerPause(); abstract void playerStop(); + //===================================================================== + private static class IAppOpsCallbackWrapper extends IAppOpsCallback.Stub { + private final WeakReference mWeakPB; + + public IAppOpsCallbackWrapper(PlayerBase pb) { + mWeakPB = new WeakReference(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 @@ -482,8 +498,8 @@ public abstract class PlayerBase { public static class PlayerIdCard implements Parcelable { public final int mPlayerType; - public final static int AUDIO_ATTRIBUTES_NONE = 0; - public final static int AUDIO_ATTRIBUTES_DEFINED = 1; + public static final int AUDIO_ATTRIBUTES_NONE = 0; + public static final int AUDIO_ATTRIBUTES_DEFINED = 1; public final AudioAttributes mAttributes; public final IPlayer mIPlayer; -- cgit v1.2.3-59-g8ed1b