From 5c768f4c8584d93fae3f5e87c8fdcc88ecfba002 Mon Sep 17 00:00:00 2001 From: Jean-Michel Trivi Date: Tue, 9 Jun 2015 18:06:05 -0700 Subject: SoundPool monitors AppOps for OP_PLAY_AUDIO Fix performance regression in SoundPool by not checking SoundPool can play audio everytime it's about to play. Instead check for permission in constructor and register a listener for changes on OP_PLAY_AUDIO. Bug 20018833 Change-Id: I4e7a633d23b98653a149681d18a387cd560efe4d --- media/java/android/media/SoundPool.java | 40 +++++++++++++++++++++++-- media/jni/soundpool/android_media_SoundPool.cpp | 2 +- 2 files changed, 38 insertions(+), 4 deletions(-) (limited to 'media') diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java index 64863c2..1355635 100644 --- a/media/java/android/media/SoundPool.java +++ b/media/java/android/media/SoundPool.java @@ -35,6 +35,7 @@ import android.os.ServiceManager; import android.util.AndroidRuntimeException; import android.util.Log; +import com.android.internal.app.IAppOpsCallback; import com.android.internal.app.IAppOpsService; @@ -125,10 +126,12 @@ public class SoundPool { private EventHandler mEventHandler; private SoundPool.OnLoadCompleteListener mOnLoadCompleteListener; + private boolean mHasAppOpsPlayAudio; private final Object mLock; private final AudioAttributes mAttributes; private final IAppOpsService mAppOps; + private final IAppOpsCallback mAppOpsCallback; /** * Constructor. Constructs a SoundPool object with the following @@ -159,6 +162,24 @@ public class SoundPool { mAttributes = attributes; IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE); mAppOps = IAppOpsService.Stub.asInterface(b); + // initialize mHasAppOpsPlayAudio + updateAppOpsPlayAudio(); + // register a callback to monitor whether the OP_PLAY_AUDIO is still allowed + mAppOpsCallback = new IAppOpsCallback.Stub() { + public void opChanged(int op, String packageName) { + synchronized (mLock) { + if (op == AppOpsManager.OP_PLAY_AUDIO) { + updateAppOpsPlayAudio(); + } + } + } + }; + try { + mAppOps.startWatchingMode(AppOpsManager.OP_PLAY_AUDIO, + ActivityThread.currentPackageName(), mAppOpsCallback); + } catch (RemoteException e) { + mHasAppOpsPlayAudio = false; + } } /** @@ -168,7 +189,16 @@ public class SoundPool { * object. The SoundPool can no longer be used and the reference * should be set to null. */ - public native final void release(); + public final void release() { + try { + mAppOps.stopWatchingMode(mAppOpsCallback); + } catch (RemoteException e) { + // nothing to do here, the SoundPool is being released anyway + } + native_release(); + } + + private native final void native_release(); protected void finalize() { release(); } @@ -466,13 +496,17 @@ public class SoundPool { if ((mAttributes.getAllFlags() & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0) { return false; } + return !mHasAppOpsPlayAudio; + } + + private void updateAppOpsPlayAudio() { try { final int mode = mAppOps.checkAudioOperation(AppOpsManager.OP_PLAY_AUDIO, mAttributes.getUsage(), Process.myUid(), ActivityThread.currentPackageName()); - return mode != AppOpsManager.MODE_ALLOWED; + mHasAppOpsPlayAudio = (mode == AppOpsManager.MODE_ALLOWED); } catch (RemoteException e) { - return false; + mHasAppOpsPlayAudio = false; } } diff --git a/media/jni/soundpool/android_media_SoundPool.cpp b/media/jni/soundpool/android_media_SoundPool.cpp index fc4cf05..ab3e340 100644 --- a/media/jni/soundpool/android_media_SoundPool.cpp +++ b/media/jni/soundpool/android_media_SoundPool.cpp @@ -286,7 +286,7 @@ static JNINativeMethod gMethods[] = { "(Ljava/lang/Object;ILjava/lang/Object;)I", (void*)android_media_SoundPool_native_setup }, - { "release", + { "native_release", "()V", (void*)android_media_SoundPool_release } -- cgit v1.1