Loading media/java/android/media/AudioTrack.java +5 −5 Original line number Diff line number Diff line Loading @@ -1513,9 +1513,9 @@ public class AudioTrack extends PlayerBase } @Override void playerSetVolume(float leftVolume, float rightVolume) { leftVolume = clampGainOrLevel(leftVolume); rightVolume = clampGainOrLevel(rightVolume); void playerSetVolume(boolean muting, float leftVolume, float rightVolume) { leftVolume = clampGainOrLevel(muting ? 0.0f : leftVolume); rightVolume = clampGainOrLevel(muting ? 0.0f : rightVolume); native_setVolume(leftVolume, rightVolume); } Loading Loading @@ -2393,8 +2393,8 @@ public class AudioTrack extends PlayerBase } @Override int playerSetAuxEffectSendLevel(float level) { level = clampGainOrLevel(level); int playerSetAuxEffectSendLevel(boolean muting, float level) { level = clampGainOrLevel(muting ? 0.0f : level); int err = native_setAuxEffectSendLevel(level); return err == 0 ? SUCCESS : ERROR; } Loading media/java/android/media/MediaPlayer.java +4 −4 Original line number Diff line number Diff line Loading @@ -1826,8 +1826,8 @@ public class MediaPlayer extends PlayerBase } @Override void playerSetVolume(float leftVolume, float rightVolume) { _setVolume(leftVolume, rightVolume); void playerSetVolume(boolean muting, float leftVolume, float rightVolume) { _setVolume(muting ? 0.0f : leftVolume, muting ? 0.0f : rightVolume); } private native void _setVolume(float leftVolume, float rightVolume); Loading Loading @@ -1900,8 +1900,8 @@ public class MediaPlayer extends PlayerBase } @Override int playerSetAuxEffectSendLevel(float level) { _setAuxEffectSendLevel(level); int playerSetAuxEffectSendLevel(boolean muting, float level) { _setAuxEffectSendLevel(muting ? 0.0f : level); return AudioSystem.SUCCESS; } Loading media/java/android/media/PlayerBase.java +52 −11 Original line number Diff line number Diff line Loading @@ -39,6 +39,11 @@ import com.android.internal.app.IAppOpsService; */ public abstract class PlayerBase { private final static String TAG = "PlayerBase"; private static IAudioService sService; //lazy initialization, use getService() /** Debug app ops */ protected static final boolean DEBUG_APP_OPS = Log.isLoggable(TAG + ".AO", Log.DEBUG); // parameters of the player that affect AppOps protected AudioAttributes mAttributes; protected float mLeftVolume = 1.0f; Loading @@ -51,7 +56,6 @@ public abstract class PlayerBase { private boolean mHasAppOpsPlayAudio = true; private final Object mAppOpsLock = new Object(); /** * Constructor. Must be given audio attributes, as they are required for AppOps. * @param attr non-null audio attributes Loading Loading @@ -101,7 +105,7 @@ public abstract class PlayerBase { void baseStart() { synchronized (mAppOpsLock) { if (isRestricted_sync()) { playerSetVolume(0, 0); playerSetVolume(true/*muting*/,0, 0); } } } Loading @@ -114,7 +118,7 @@ public abstract class PlayerBase { return; } } playerSetVolume(leftVolume, rightVolume); playerSetVolume(false/*muting*/,leftVolume, rightVolume); } int baseSetAuxEffectSendLevel(float level) { Loading @@ -124,7 +128,7 @@ public abstract class PlayerBase { return AudioSystem.SUCCESS; } } return playerSetAuxEffectSendLevel(level); return playerSetAuxEffectSendLevel(false/*muting*/, level); } /** Loading Loading @@ -159,11 +163,18 @@ public abstract class PlayerBase { try { if (oldHasAppOpsPlayAudio != mHasAppOpsPlayAudio) { if (mHasAppOpsPlayAudio) { playerSetVolume(mLeftVolume, mRightVolume); playerSetAuxEffectSendLevel(mAuxEffectSendLevel); if (DEBUG_APP_OPS) { Log.v(TAG, "updateAppOpsPlayAudio: unmuting player, vol=" + mLeftVolume + "/" + mRightVolume); } playerSetVolume(false/*muting*/, mLeftVolume, mRightVolume); playerSetAuxEffectSendLevel(false/*muting*/, mAuxEffectSendLevel); } else { playerSetVolume(0.0f, 0.0f); playerSetAuxEffectSendLevel(0.0f); if (DEBUG_APP_OPS) { Log.v(TAG, "updateAppOpsPlayAudio: muting player"); } playerSetVolume(true/*muting*/, 0.0f, 0.0f); playerSetAuxEffectSendLevel(true/*muting*/, 0.0f); } } } catch (Exception e) { Loading @@ -171,7 +182,6 @@ public abstract class PlayerBase { } } /** * To be called by the subclass whenever an operation is potentially restricted. * As the media player-common behavior are incorporated into this class, the subclass's need Loading @@ -189,10 +199,41 @@ public abstract class PlayerBase { if ((mAttributes.getAllFlags() & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0) { return false; } // check force audibility flag and camera restriction if (((mAttributes.getAllFlags() & AudioAttributes.FLAG_AUDIBILITY_ENFORCED) != 0) && (mAttributes.getUsage() == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)) { boolean cameraSoundForced = false; try { cameraSoundForced = getService().isCameraSoundForced(); } catch (RemoteException e) { Log.e(TAG, "Cannot access AudioService in isRestricted_sync()"); } catch (NullPointerException e) { Log.e(TAG, "Null AudioService in isRestricted_sync()"); } if (cameraSoundForced) { return false; } } return true; } private static IAudioService getService() { if (sService != null) { return sService; } IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE); sService = IAudioService.Stub.asInterface(b); return sService; } // Abstract methods a subclass needs to implement abstract void playerSetVolume(float leftVolume, float rightVolume); abstract int playerSetAuxEffectSendLevel(float level); /** * Abstract method for the subclass behavior's for volume and muting commands * @param muting if true, the player is to be muted, and the volume values can be ignored * @param leftVolume the left volume to use if muting is false * @param rightVolume the right volume to use if muting is false */ abstract void playerSetVolume(boolean muting, float leftVolume, float rightVolume); abstract int playerSetAuxEffectSendLevel(boolean muting, float level); } media/java/android/media/SoundPool.java +24 −88 Original line number Diff line number Diff line Loading @@ -35,9 +35,6 @@ import android.os.ServiceManager; import android.util.AndroidRuntimeException; import android.util.Log; import com.android.internal.app.IAppOpsCallback; import com.android.internal.app.IAppOpsService; /** * The SoundPool class manages and plays audio resources for applications. Loading Loading @@ -111,7 +108,7 @@ import com.android.internal.app.IAppOpsService; * another level, a new SoundPool is created, sounds are loaded, and play * resumes.</p> */ public class SoundPool { public class SoundPool extends PlayerBase { static { System.loadLibrary("soundpool"); } // SoundPool messages Loading @@ -130,10 +127,6 @@ public class SoundPool { private final Object mLock; private final AudioAttributes mAttributes; private final IAppOpsService mAppOps; private final IAppOpsCallback mAppOpsCallback; private static IAudioService sService; /** * Constructor. Constructs a SoundPool object with the following Loading @@ -156,32 +149,14 @@ public class SoundPool { } private SoundPool(int maxStreams, AudioAttributes attributes) { super(attributes); // do native setup if (native_setup(new WeakReference<SoundPool>(this), maxStreams, attributes) != 0) { throw new RuntimeException("Native setup failed"); } mLock = new Object(); 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, int uid, 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; } } /** Loading @@ -192,11 +167,7 @@ public class SoundPool { * should be set to null. */ public final void release() { try { mAppOps.stopWatchingMode(mAppOpsCallback); } catch (RemoteException e) { // nothing to do here, the SoundPool is being released anyway } baseRelease(); native_release(); } Loading Loading @@ -333,9 +304,7 @@ public class SoundPool { */ public final int play(int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate) { if (isRestricted()) { leftVolume = rightVolume = 0; } baseStart(); return _play(soundID, leftVolume, rightVolume, priority, loop, rate); } Loading Loading @@ -408,12 +377,26 @@ public class SoundPool { * @param rightVolume right volume value (range = 0.0 to 1.0) */ public final void setVolume(int streamID, float leftVolume, float rightVolume) { if (isRestricted()) { return; } // unlike other subclasses of PlayerBase, we are not calling // baseSetVolume(leftVolume, rightVolume) as we need to keep track of each // volume separately for each player, so we still send the command, but // handle mute/unmute separately through playerSetVolume() _setVolume(streamID, leftVolume, rightVolume); } @Override void playerSetVolume(boolean muting, float leftVolume, float rightVolume) { // not used here to control the player volume directly, but used to mute/unmute _mute(muting); } @Override int playerSetAuxEffectSendLevel(boolean muting, float level) { // no aux send functionality so no-op return AudioSystem.SUCCESS; } /** * Similar, except set volume of all channels to same value. * @hide Loading Loading @@ -494,55 +477,6 @@ public class SoundPool { } } private static IAudioService getService() { if (sService != null) { return sService; } IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE); sService = IAudioService.Stub.asInterface(b); return sService; } private boolean isRestricted() { // check app ops if (mHasAppOpsPlayAudio) { return false; } // check bypass flag if ((mAttributes.getAllFlags() & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0) { return false; } // check force audibility flag and camera restriction if ((mAttributes.getAllFlags() & AudioAttributes.FLAG_AUDIBILITY_ENFORCED) != 0) { // FIXME: should also check usage when set properly by camera app // && (mAttributes.getUsage() == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) boolean cameraSoundForced = false; try { cameraSoundForced = getService().isCameraSoundForced(); } catch (RemoteException e) { Log.e(TAG, "Cannot access AudioService in isRestricted()"); } catch (NullPointerException e) { Log.e(TAG, "Null AudioService in isRestricted()"); } if (cameraSoundForced) { return false; } } return true; } private void updateAppOpsPlayAudio() { try { final int mode = mAppOps.checkAudioOperation(AppOpsManager.OP_PLAY_AUDIO, mAttributes.getUsage(), Process.myUid(), ActivityThread.currentPackageName()); mHasAppOpsPlayAudio = (mode == AppOpsManager.MODE_ALLOWED); } catch (RemoteException e) { mHasAppOpsPlayAudio = false; } } private native final int _load(FileDescriptor fd, long offset, long length, int priority); private native final int native_setup(Object weakRef, int maxStreams, Loading @@ -553,6 +487,8 @@ public class SoundPool { private native final void _setVolume(int streamID, float leftVolume, float rightVolume); private native final void _mute(boolean muting); // post event from native code to message handler @SuppressWarnings("unchecked") private static void postEventFromNative(Object ref, int msg, int arg1, int arg2, Object obj) { Loading media/jni/soundpool/SoundPool.cpp +28 −1 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ SoundPool::SoundPool(int maxChannels, const audio_attributes_t* pAttributes) ALOGW_IF(maxChannels != mMaxChannels, "App requested %d channels", maxChannels); mQuit = false; mMuted = false; mDecodeThread = 0; memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t)); mAllocated = 0; Loading Loading @@ -366,6 +367,19 @@ void SoundPool::resume(int channelID) } } void SoundPool::mute(bool muting) { ALOGV("mute(%d)", muting); Mutex::Autolock lock(&mLock); mMuted = muting; if (!mChannels.empty()) { for (List<SoundChannel*>::iterator iter = mChannels.begin(); iter != mChannels.end(); ++iter) { (*iter)->mute(muting); } } } void SoundPool::autoResume() { ALOGV("autoResume()"); Loading Loading @@ -1032,7 +1046,7 @@ void SoundChannel::setVolume_l(float leftVolume, float rightVolume) { mLeftVolume = leftVolume; mRightVolume = rightVolume; if (mAudioTrack != NULL) if (mAudioTrack != NULL && !mMuted) mAudioTrack->setVolume(leftVolume, rightVolume); } Loading @@ -1042,6 +1056,19 @@ void SoundChannel::setVolume(float leftVolume, float rightVolume) setVolume_l(leftVolume, rightVolume); } void SoundChannel::mute(bool muting) { Mutex::Autolock lock(&mLock); mMuted = muting; if (mAudioTrack != NULL) { if (mMuted) { mAudioTrack->setVolume(0.0f, 0.0f); } else { mAudioTrack->setVolume(mLeftVolume, mRightVolume); } } } void SoundChannel::setLoop(int loop) { Mutex::Autolock lock(&mLock); Loading Loading
media/java/android/media/AudioTrack.java +5 −5 Original line number Diff line number Diff line Loading @@ -1513,9 +1513,9 @@ public class AudioTrack extends PlayerBase } @Override void playerSetVolume(float leftVolume, float rightVolume) { leftVolume = clampGainOrLevel(leftVolume); rightVolume = clampGainOrLevel(rightVolume); void playerSetVolume(boolean muting, float leftVolume, float rightVolume) { leftVolume = clampGainOrLevel(muting ? 0.0f : leftVolume); rightVolume = clampGainOrLevel(muting ? 0.0f : rightVolume); native_setVolume(leftVolume, rightVolume); } Loading Loading @@ -2393,8 +2393,8 @@ public class AudioTrack extends PlayerBase } @Override int playerSetAuxEffectSendLevel(float level) { level = clampGainOrLevel(level); int playerSetAuxEffectSendLevel(boolean muting, float level) { level = clampGainOrLevel(muting ? 0.0f : level); int err = native_setAuxEffectSendLevel(level); return err == 0 ? SUCCESS : ERROR; } Loading
media/java/android/media/MediaPlayer.java +4 −4 Original line number Diff line number Diff line Loading @@ -1826,8 +1826,8 @@ public class MediaPlayer extends PlayerBase } @Override void playerSetVolume(float leftVolume, float rightVolume) { _setVolume(leftVolume, rightVolume); void playerSetVolume(boolean muting, float leftVolume, float rightVolume) { _setVolume(muting ? 0.0f : leftVolume, muting ? 0.0f : rightVolume); } private native void _setVolume(float leftVolume, float rightVolume); Loading Loading @@ -1900,8 +1900,8 @@ public class MediaPlayer extends PlayerBase } @Override int playerSetAuxEffectSendLevel(float level) { _setAuxEffectSendLevel(level); int playerSetAuxEffectSendLevel(boolean muting, float level) { _setAuxEffectSendLevel(muting ? 0.0f : level); return AudioSystem.SUCCESS; } Loading
media/java/android/media/PlayerBase.java +52 −11 Original line number Diff line number Diff line Loading @@ -39,6 +39,11 @@ import com.android.internal.app.IAppOpsService; */ public abstract class PlayerBase { private final static String TAG = "PlayerBase"; private static IAudioService sService; //lazy initialization, use getService() /** Debug app ops */ protected static final boolean DEBUG_APP_OPS = Log.isLoggable(TAG + ".AO", Log.DEBUG); // parameters of the player that affect AppOps protected AudioAttributes mAttributes; protected float mLeftVolume = 1.0f; Loading @@ -51,7 +56,6 @@ public abstract class PlayerBase { private boolean mHasAppOpsPlayAudio = true; private final Object mAppOpsLock = new Object(); /** * Constructor. Must be given audio attributes, as they are required for AppOps. * @param attr non-null audio attributes Loading Loading @@ -101,7 +105,7 @@ public abstract class PlayerBase { void baseStart() { synchronized (mAppOpsLock) { if (isRestricted_sync()) { playerSetVolume(0, 0); playerSetVolume(true/*muting*/,0, 0); } } } Loading @@ -114,7 +118,7 @@ public abstract class PlayerBase { return; } } playerSetVolume(leftVolume, rightVolume); playerSetVolume(false/*muting*/,leftVolume, rightVolume); } int baseSetAuxEffectSendLevel(float level) { Loading @@ -124,7 +128,7 @@ public abstract class PlayerBase { return AudioSystem.SUCCESS; } } return playerSetAuxEffectSendLevel(level); return playerSetAuxEffectSendLevel(false/*muting*/, level); } /** Loading Loading @@ -159,11 +163,18 @@ public abstract class PlayerBase { try { if (oldHasAppOpsPlayAudio != mHasAppOpsPlayAudio) { if (mHasAppOpsPlayAudio) { playerSetVolume(mLeftVolume, mRightVolume); playerSetAuxEffectSendLevel(mAuxEffectSendLevel); if (DEBUG_APP_OPS) { Log.v(TAG, "updateAppOpsPlayAudio: unmuting player, vol=" + mLeftVolume + "/" + mRightVolume); } playerSetVolume(false/*muting*/, mLeftVolume, mRightVolume); playerSetAuxEffectSendLevel(false/*muting*/, mAuxEffectSendLevel); } else { playerSetVolume(0.0f, 0.0f); playerSetAuxEffectSendLevel(0.0f); if (DEBUG_APP_OPS) { Log.v(TAG, "updateAppOpsPlayAudio: muting player"); } playerSetVolume(true/*muting*/, 0.0f, 0.0f); playerSetAuxEffectSendLevel(true/*muting*/, 0.0f); } } } catch (Exception e) { Loading @@ -171,7 +182,6 @@ public abstract class PlayerBase { } } /** * To be called by the subclass whenever an operation is potentially restricted. * As the media player-common behavior are incorporated into this class, the subclass's need Loading @@ -189,10 +199,41 @@ public abstract class PlayerBase { if ((mAttributes.getAllFlags() & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0) { return false; } // check force audibility flag and camera restriction if (((mAttributes.getAllFlags() & AudioAttributes.FLAG_AUDIBILITY_ENFORCED) != 0) && (mAttributes.getUsage() == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)) { boolean cameraSoundForced = false; try { cameraSoundForced = getService().isCameraSoundForced(); } catch (RemoteException e) { Log.e(TAG, "Cannot access AudioService in isRestricted_sync()"); } catch (NullPointerException e) { Log.e(TAG, "Null AudioService in isRestricted_sync()"); } if (cameraSoundForced) { return false; } } return true; } private static IAudioService getService() { if (sService != null) { return sService; } IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE); sService = IAudioService.Stub.asInterface(b); return sService; } // Abstract methods a subclass needs to implement abstract void playerSetVolume(float leftVolume, float rightVolume); abstract int playerSetAuxEffectSendLevel(float level); /** * Abstract method for the subclass behavior's for volume and muting commands * @param muting if true, the player is to be muted, and the volume values can be ignored * @param leftVolume the left volume to use if muting is false * @param rightVolume the right volume to use if muting is false */ abstract void playerSetVolume(boolean muting, float leftVolume, float rightVolume); abstract int playerSetAuxEffectSendLevel(boolean muting, float level); }
media/java/android/media/SoundPool.java +24 −88 Original line number Diff line number Diff line Loading @@ -35,9 +35,6 @@ import android.os.ServiceManager; import android.util.AndroidRuntimeException; import android.util.Log; import com.android.internal.app.IAppOpsCallback; import com.android.internal.app.IAppOpsService; /** * The SoundPool class manages and plays audio resources for applications. Loading Loading @@ -111,7 +108,7 @@ import com.android.internal.app.IAppOpsService; * another level, a new SoundPool is created, sounds are loaded, and play * resumes.</p> */ public class SoundPool { public class SoundPool extends PlayerBase { static { System.loadLibrary("soundpool"); } // SoundPool messages Loading @@ -130,10 +127,6 @@ public class SoundPool { private final Object mLock; private final AudioAttributes mAttributes; private final IAppOpsService mAppOps; private final IAppOpsCallback mAppOpsCallback; private static IAudioService sService; /** * Constructor. Constructs a SoundPool object with the following Loading @@ -156,32 +149,14 @@ public class SoundPool { } private SoundPool(int maxStreams, AudioAttributes attributes) { super(attributes); // do native setup if (native_setup(new WeakReference<SoundPool>(this), maxStreams, attributes) != 0) { throw new RuntimeException("Native setup failed"); } mLock = new Object(); 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, int uid, 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; } } /** Loading @@ -192,11 +167,7 @@ public class SoundPool { * should be set to null. */ public final void release() { try { mAppOps.stopWatchingMode(mAppOpsCallback); } catch (RemoteException e) { // nothing to do here, the SoundPool is being released anyway } baseRelease(); native_release(); } Loading Loading @@ -333,9 +304,7 @@ public class SoundPool { */ public final int play(int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate) { if (isRestricted()) { leftVolume = rightVolume = 0; } baseStart(); return _play(soundID, leftVolume, rightVolume, priority, loop, rate); } Loading Loading @@ -408,12 +377,26 @@ public class SoundPool { * @param rightVolume right volume value (range = 0.0 to 1.0) */ public final void setVolume(int streamID, float leftVolume, float rightVolume) { if (isRestricted()) { return; } // unlike other subclasses of PlayerBase, we are not calling // baseSetVolume(leftVolume, rightVolume) as we need to keep track of each // volume separately for each player, so we still send the command, but // handle mute/unmute separately through playerSetVolume() _setVolume(streamID, leftVolume, rightVolume); } @Override void playerSetVolume(boolean muting, float leftVolume, float rightVolume) { // not used here to control the player volume directly, but used to mute/unmute _mute(muting); } @Override int playerSetAuxEffectSendLevel(boolean muting, float level) { // no aux send functionality so no-op return AudioSystem.SUCCESS; } /** * Similar, except set volume of all channels to same value. * @hide Loading Loading @@ -494,55 +477,6 @@ public class SoundPool { } } private static IAudioService getService() { if (sService != null) { return sService; } IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE); sService = IAudioService.Stub.asInterface(b); return sService; } private boolean isRestricted() { // check app ops if (mHasAppOpsPlayAudio) { return false; } // check bypass flag if ((mAttributes.getAllFlags() & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0) { return false; } // check force audibility flag and camera restriction if ((mAttributes.getAllFlags() & AudioAttributes.FLAG_AUDIBILITY_ENFORCED) != 0) { // FIXME: should also check usage when set properly by camera app // && (mAttributes.getUsage() == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) boolean cameraSoundForced = false; try { cameraSoundForced = getService().isCameraSoundForced(); } catch (RemoteException e) { Log.e(TAG, "Cannot access AudioService in isRestricted()"); } catch (NullPointerException e) { Log.e(TAG, "Null AudioService in isRestricted()"); } if (cameraSoundForced) { return false; } } return true; } private void updateAppOpsPlayAudio() { try { final int mode = mAppOps.checkAudioOperation(AppOpsManager.OP_PLAY_AUDIO, mAttributes.getUsage(), Process.myUid(), ActivityThread.currentPackageName()); mHasAppOpsPlayAudio = (mode == AppOpsManager.MODE_ALLOWED); } catch (RemoteException e) { mHasAppOpsPlayAudio = false; } } private native final int _load(FileDescriptor fd, long offset, long length, int priority); private native final int native_setup(Object weakRef, int maxStreams, Loading @@ -553,6 +487,8 @@ public class SoundPool { private native final void _setVolume(int streamID, float leftVolume, float rightVolume); private native final void _mute(boolean muting); // post event from native code to message handler @SuppressWarnings("unchecked") private static void postEventFromNative(Object ref, int msg, int arg1, int arg2, Object obj) { Loading
media/jni/soundpool/SoundPool.cpp +28 −1 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ SoundPool::SoundPool(int maxChannels, const audio_attributes_t* pAttributes) ALOGW_IF(maxChannels != mMaxChannels, "App requested %d channels", maxChannels); mQuit = false; mMuted = false; mDecodeThread = 0; memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t)); mAllocated = 0; Loading Loading @@ -366,6 +367,19 @@ void SoundPool::resume(int channelID) } } void SoundPool::mute(bool muting) { ALOGV("mute(%d)", muting); Mutex::Autolock lock(&mLock); mMuted = muting; if (!mChannels.empty()) { for (List<SoundChannel*>::iterator iter = mChannels.begin(); iter != mChannels.end(); ++iter) { (*iter)->mute(muting); } } } void SoundPool::autoResume() { ALOGV("autoResume()"); Loading Loading @@ -1032,7 +1046,7 @@ void SoundChannel::setVolume_l(float leftVolume, float rightVolume) { mLeftVolume = leftVolume; mRightVolume = rightVolume; if (mAudioTrack != NULL) if (mAudioTrack != NULL && !mMuted) mAudioTrack->setVolume(leftVolume, rightVolume); } Loading @@ -1042,6 +1056,19 @@ void SoundChannel::setVolume(float leftVolume, float rightVolume) setVolume_l(leftVolume, rightVolume); } void SoundChannel::mute(bool muting) { Mutex::Autolock lock(&mLock); mMuted = muting; if (mAudioTrack != NULL) { if (mMuted) { mAudioTrack->setVolume(0.0f, 0.0f); } else { mAudioTrack->setVolume(mLeftVolume, mRightVolume); } } } void SoundChannel::setLoop(int loop) { Mutex::Autolock lock(&mLock); Loading