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
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user