diff options
Diffstat (limited to 'media/java')
| -rw-r--r-- | media/java/android/media/AudioService.java | 8 | ||||
| -rw-r--r-- | media/java/android/media/AudioTrack.java | 37 | ||||
| -rw-r--r-- | media/java/android/media/MediaPlayer.java | 59 | ||||
| -rw-r--r-- | media/java/android/media/SoundPool.java | 43 |
4 files changed, 137 insertions, 10 deletions
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 46b74da..fe510f6 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -258,7 +258,7 @@ public class AudioService extends IAudioService.Stub { private final boolean mUseFixedVolume; // stream names used by dumpStreamStates() - private final String[] STREAM_NAMES = new String[] { + private static final String[] STREAM_NAMES = new String[] { "STREAM_VOICE_CALL", "STREAM_SYSTEM", "STREAM_RING", @@ -614,6 +614,12 @@ public class AudioService extends IAudioService.Stub { pw.println(Integer.toHexString(mMuteAffectedStreams)); } + /** @hide */ + public static String streamToString(int stream) { + if (stream >= 0 && stream < STREAM_NAMES.length) return STREAM_NAMES[stream]; + if (stream == AudioManager.USE_DEFAULT_STREAM_TYPE) return "USE_DEFAULT_STREAM_TYPE"; + return "UNKNOWN_STREAM_" + stream; + } private void updateStreamVolumeAlias(boolean updateVolumes) { int dtmfStreamAlias; diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index 5611efb..dee8705 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -23,11 +23,20 @@ import java.nio.ByteBuffer; import java.nio.NioUtils; import android.annotation.IntDef; +import android.app.ActivityThread; +import android.app.AppOpsManager; +import android.content.Context; import android.os.Handler; +import android.os.IBinder; import android.os.Looper; import android.os.Message; +import android.os.Process; +import android.os.RemoteException; +import android.os.ServiceManager; import android.util.Log; +import com.android.internal.app.IAppOpsService; + /** * The AudioTrack class manages and plays a single audio resource for Java applications. @@ -239,7 +248,10 @@ public class AudioTrack * Audio session ID */ private int mSessionId = AudioSystem.AUDIO_SESSION_ALLOCATE; - + /** + * Reference to the app-ops service. + */ + private final IAppOpsService mAppOps; //-------------------------------- // Used exclusively by native code @@ -343,6 +355,9 @@ public class AudioTrack audioBuffSizeCheck(bufferSizeInBytes); + IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE); + mAppOps = IAppOpsService.Stub.asInterface(b); + if (sessionId < 0) { throw new IllegalArgumentException("Invalid audio session ID: "+sessionId); } @@ -841,6 +856,9 @@ public class AudioTrack * {@link #ERROR_INVALID_OPERATION} */ public int setStereoVolume(float leftVolume, float rightVolume) { + if (isRestricted()) { + return SUCCESS; + } if (mState == STATE_UNINITIALIZED) { return ERROR_INVALID_OPERATION; } @@ -1014,13 +1032,25 @@ public class AudioTrack if (mState != STATE_INITIALIZED) { throw new IllegalStateException("play() called on uninitialized AudioTrack."); } - + if (isRestricted()) { + setVolume(0); + } synchronized(mPlayStateLock) { native_start(); mPlayState = PLAYSTATE_PLAYING; } } + private boolean isRestricted() { + try { + final int mode = mAppOps.checkAudioOperation(AppOpsManager.OP_PLAY_AUDIO, mStreamType, + Process.myUid(), ActivityThread.currentPackageName()); + return mode != AppOpsManager.MODE_ALLOWED; + } catch (RemoteException e) { + return false; + } + } + /** * Stops playing the audio data. * When used on an instance created in {@link #MODE_STREAM} mode, audio will stop playing @@ -1296,6 +1326,9 @@ public class AudioTrack * {@link #ERROR_INVALID_OPERATION} */ public int setAuxEffectSendLevel(float level) { + if (isRestricted()) { + return SUCCESS; + } if (mState == STATE_UNINITIALIZED) { return ERROR_INVALID_OPERATION; } diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index e20a4af..1b92410 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -16,6 +16,8 @@ package android.media; +import android.app.ActivityThread; +import android.app.AppOpsManager; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; @@ -32,6 +34,8 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.Process; import android.os.PowerManager; +import android.os.RemoteException; +import android.os.ServiceManager; import android.util.Log; import android.view.Surface; import android.view.SurfaceHolder; @@ -42,6 +46,8 @@ import android.media.MediaTimeProvider; import android.media.SubtitleController; import android.media.SubtitleData; +import com.android.internal.app.IAppOpsService; + import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; @@ -576,6 +582,8 @@ public class MediaPlayer implements SubtitleController.Listener private PowerManager.WakeLock mWakeLock = null; private boolean mScreenOnWhilePlaying; private boolean mStayAwake; + private final IAppOpsService mAppOps; + private int mStreamType = AudioManager.USE_DEFAULT_STREAM_TYPE; /** * Default constructor. Consider using one of the create() methods for @@ -599,6 +607,8 @@ public class MediaPlayer implements SubtitleController.Listener mOutOfBandSubtitleTracks = new Vector<SubtitleTrack>(); mOpenSubtitleSources = new Vector<InputStream>(); mInbandSubtitleTracks = new SubtitleTrack[0]; + IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE); + mAppOps = IAppOpsService.Stub.asInterface(b); /* Native setup requires a weak reference to our object. * It's easier to create it here than in C++. @@ -1055,13 +1065,35 @@ public class MediaPlayer implements SubtitleController.Listener * * @throws IllegalStateException if it is called in an invalid state */ - public void start() throws IllegalStateException { + public void start() throws IllegalStateException { + if (isRestricted()) { + _setVolume(0, 0); + } stayAwake(true); _start(); } private native void _start() throws IllegalStateException; + private boolean isRestricted() { + try { + final int mode = mAppOps.checkAudioOperation(AppOpsManager.OP_PLAY_AUDIO, + getAudioStreamType(), Process.myUid(), ActivityThread.currentPackageName()); + return mode != AppOpsManager.MODE_ALLOWED; + } catch (RemoteException e) { + return false; + } + } + + private int getAudioStreamType() { + if (mStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) { + mStreamType = _getAudioStreamType(); + } + return mStreamType; + } + + private native int _getAudioStreamType() throws IllegalStateException; + /** * Stops playback after playback has been stopped or paused. * @@ -1402,7 +1434,12 @@ public class MediaPlayer implements SubtitleController.Listener * @param streamtype the audio stream type * @see android.media.AudioManager */ - public native void setAudioStreamType(int streamtype); + public void setAudioStreamType(int streamtype) { + _setAudioStreamType(streamtype); + mStreamType = streamtype; + } + + private native void _setAudioStreamType(int streamtype); /** * Sets the player to be looping or non-looping. @@ -1435,7 +1472,14 @@ public class MediaPlayer implements SubtitleController.Listener * The single parameter form below is preferred if the channel volumes don't need * to be set independently. */ - public native void setVolume(float leftVolume, float rightVolume); + public void setVolume(float leftVolume, float rightVolume) { + if (isRestricted()) { + return; + } + _setVolume(leftVolume, rightVolume); + } + + private native void _setVolume(float leftVolume, float rightVolume); /** * Similar, excepts sets volume of all channels to same value. @@ -1500,7 +1544,14 @@ public class MediaPlayer implements SubtitleController.Listener * 0 < x <= R -> level = 10^(72*(x-R)/20/R) * @param level send level scalar */ - public native void setAuxEffectSendLevel(float level); + public void setAuxEffectSendLevel(float level) { + if (isRestricted()) { + return; + } + _setAuxEffectSendLevel(level); + } + + private native void _setAuxEffectSendLevel(float level); /* * @param request Parcel destinated to the media player. The diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java index f1b256e..14f0c69 100644 --- a/media/java/android/media/SoundPool.java +++ b/media/java/android/media/SoundPool.java @@ -20,16 +20,24 @@ import java.io.File; import java.io.FileDescriptor; import java.lang.ref.WeakReference; +import android.app.ActivityThread; +import android.app.AppOpsManager; import android.content.Context; import android.content.res.AssetFileDescriptor; import android.os.Handler; +import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.ParcelFileDescriptor; +import android.os.Process; +import android.os.RemoteException; +import android.os.ServiceManager; import android.os.SystemProperties; import android.util.AndroidRuntimeException; import android.util.Log; +import com.android.internal.app.IAppOpsService; + /** * The SoundPool class manages and plays audio resources for applications. @@ -449,6 +457,8 @@ public class SoundPool { private SoundPool mProxy; private final Object mLock; + private final int mStreamType; + private final IAppOpsService mAppOps; // SoundPool messages // @@ -463,6 +473,9 @@ public class SoundPool { } mLock = new Object(); mProxy = proxy; + mStreamType = streamType; + IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE); + mAppOps = IAppOpsService.Stub.asInterface(b); } public int load(String path, int priority) @@ -522,9 +535,27 @@ public class SoundPool { public native final boolean unload(int soundID); - public native final int play(int soundID, float leftVolume, float rightVolume, + public final int play(int soundID, float leftVolume, float rightVolume, + int priority, int loop, float rate) { + if (isRestricted()) { + leftVolume = rightVolume = 0; + } + return _play(soundID, leftVolume, rightVolume, priority, loop, rate); + } + + public native final int _play(int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate); + private boolean isRestricted() { + try { + final int mode = mAppOps.checkAudioOperation(AppOpsManager.OP_PLAY_AUDIO, + mStreamType, Process.myUid(), ActivityThread.currentPackageName()); + return mode != AppOpsManager.MODE_ALLOWED; + } catch (RemoteException e) { + return false; + } + } + public native final void pause(int streamID); public native final void resume(int streamID); @@ -535,8 +566,14 @@ public class SoundPool { public native final void stop(int streamID); - public native final void setVolume(int streamID, - float leftVolume, float rightVolume); + public final void setVolume(int streamID, float leftVolume, float rightVolume) { + if (isRestricted()) { + return; + } + _setVolume(streamID, leftVolume, rightVolume); + } + + private native final void _setVolume(int streamID, float leftVolume, float rightVolume); public void setVolume(int streamID, float volume) { setVolume(streamID, volume, volume); |
