Merge "VideoView: option for audio focus, support for AudioAttributes"
This commit is contained in:
committed by
Android (Google) Code Review
commit
4bc511cb66
@@ -20798,6 +20798,7 @@ package android.media {
|
||||
field public static final int AUDIOFOCUS_LOSS = -1; // 0xffffffff
|
||||
field public static final int AUDIOFOCUS_LOSS_TRANSIENT = -2; // 0xfffffffe
|
||||
field public static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK = -3; // 0xfffffffd
|
||||
field public static final int AUDIOFOCUS_NONE = 0; // 0x0
|
||||
field public static final int AUDIOFOCUS_REQUEST_FAILED = 0; // 0x0
|
||||
field public static final int AUDIOFOCUS_REQUEST_GRANTED = 1; // 0x1
|
||||
field public static final int AUDIO_SESSION_ID_GENERATE = 0; // 0x0
|
||||
@@ -50825,6 +50826,8 @@ package android.widget {
|
||||
method public int resolveAdjustedSize(int, int);
|
||||
method public void resume();
|
||||
method public void seekTo(int);
|
||||
method public void setAudioAttributes(android.media.AudioAttributes);
|
||||
method public void setAudioFocusRequest(int);
|
||||
method public void setMediaController(android.widget.MediaController);
|
||||
method public void setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener);
|
||||
method public void setOnErrorListener(android.media.MediaPlayer.OnErrorListener);
|
||||
|
||||
@@ -22465,6 +22465,7 @@ package android.media {
|
||||
field public static final int AUDIOFOCUS_LOSS = -1; // 0xffffffff
|
||||
field public static final int AUDIOFOCUS_LOSS_TRANSIENT = -2; // 0xfffffffe
|
||||
field public static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK = -3; // 0xfffffffd
|
||||
field public static final int AUDIOFOCUS_NONE = 0; // 0x0
|
||||
field public static final int AUDIOFOCUS_REQUEST_FAILED = 0; // 0x0
|
||||
field public static final int AUDIOFOCUS_REQUEST_GRANTED = 1; // 0x1
|
||||
field public static final int AUDIO_SESSION_ID_GENERATE = 0; // 0x0
|
||||
@@ -54734,6 +54735,8 @@ package android.widget {
|
||||
method public int resolveAdjustedSize(int, int);
|
||||
method public void resume();
|
||||
method public void seekTo(int);
|
||||
method public void setAudioAttributes(android.media.AudioAttributes);
|
||||
method public void setAudioFocusRequest(int);
|
||||
method public void setMediaController(android.widget.MediaController);
|
||||
method public void setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener);
|
||||
method public void setOnErrorListener(android.media.MediaPlayer.OnErrorListener);
|
||||
|
||||
@@ -20894,6 +20894,7 @@ package android.media {
|
||||
field public static final int AUDIOFOCUS_LOSS = -1; // 0xffffffff
|
||||
field public static final int AUDIOFOCUS_LOSS_TRANSIENT = -2; // 0xfffffffe
|
||||
field public static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK = -3; // 0xfffffffd
|
||||
field public static final int AUDIOFOCUS_NONE = 0; // 0x0
|
||||
field public static final int AUDIOFOCUS_REQUEST_FAILED = 0; // 0x0
|
||||
field public static final int AUDIOFOCUS_REQUEST_GRANTED = 1; // 0x1
|
||||
field public static final int AUDIO_SESSION_ID_GENERATE = 0; // 0x0
|
||||
@@ -51204,6 +51205,8 @@ package android.widget {
|
||||
method public int resolveAdjustedSize(int, int);
|
||||
method public void resume();
|
||||
method public void seekTo(int);
|
||||
method public void setAudioAttributes(android.media.AudioAttributes);
|
||||
method public void setAudioFocusRequest(int);
|
||||
method public void setMediaController(android.widget.MediaController);
|
||||
method public void setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener);
|
||||
method public void setOnErrorListener(android.media.MediaPlayer.OnErrorListener);
|
||||
|
||||
@@ -16,11 +16,13 @@
|
||||
|
||||
package android.widget;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
import android.media.AudioAttributes;
|
||||
import android.media.AudioManager;
|
||||
import android.media.Cea708CaptionRenderer;
|
||||
import android.media.ClosedCaptionRenderer;
|
||||
@@ -67,6 +69,14 @@ import java.util.Vector;
|
||||
* {@link android.app.Activity#onRestoreInstanceState}.<p>
|
||||
* Also note that the audio session id (from {@link #getAudioSessionId}) may
|
||||
* change from its previously returned value when the VideoView is restored.
|
||||
* <p>
|
||||
* By default, VideoView requests audio focus with {@link AudioManager#AUDIOFOCUS_GAIN}. Use
|
||||
* {@link #setAudioFocusRequest(int)} to change this behavior.
|
||||
* <p>
|
||||
* The default {@link AudioAttributes} used during playback have a usage of
|
||||
* {@link AudioAttributes#USAGE_MEDIA} and a content type of
|
||||
* {@link AudioAttributes#CONTENT_TYPE_MOVIE}, use {@link #setAudioAttributes(AudioAttributes)} to
|
||||
* modify them.
|
||||
*/
|
||||
public class VideoView extends SurfaceView
|
||||
implements MediaPlayerControl, SubtitleController.Anchor {
|
||||
@@ -113,6 +123,9 @@ public class VideoView extends SurfaceView
|
||||
private boolean mCanPause;
|
||||
private boolean mCanSeekBack;
|
||||
private boolean mCanSeekForward;
|
||||
private AudioManager mAudioManager;
|
||||
private int mAudioFocusType = AudioManager.AUDIOFOCUS_GAIN; // legacy focus gain
|
||||
private AudioAttributes mAudioAttributes;
|
||||
|
||||
/** Subtitle rendering widget overlaid on top of the video. */
|
||||
private RenderingWidget mSubtitleWidget;
|
||||
@@ -138,6 +151,10 @@ public class VideoView extends SurfaceView
|
||||
mVideoWidth = 0;
|
||||
mVideoHeight = 0;
|
||||
|
||||
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
|
||||
mAudioAttributes = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA)
|
||||
.setContentType(AudioAttributes.CONTENT_TYPE_MOVIE).build();
|
||||
|
||||
getHolder().addCallback(mSHCallback);
|
||||
getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
|
||||
|
||||
@@ -259,6 +276,41 @@ public class VideoView extends SurfaceView
|
||||
invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets which type of audio focus will be requested during the playback, or configures playback
|
||||
* to not request audio focus. Valid values for focus requests are
|
||||
* {@link AudioManager#AUDIOFOCUS_GAIN}, {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT},
|
||||
* {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK}, and
|
||||
* {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE}. Or use
|
||||
* {@link AudioManager#AUDIOFOCUS_NONE} to express that audio focus should not be
|
||||
* requested when playback starts. You can for instance use this when playing a silent animation
|
||||
* through this class, and you don't want to affect other audio applications playing in the
|
||||
* background.
|
||||
* @param focusGain the type of audio focus gain that will be requested, or
|
||||
* {@link AudioManager#AUDIOFOCUS_NONE} to disable the use audio focus during playback.
|
||||
*/
|
||||
public void setAudioFocusRequest(int focusGain) {
|
||||
if (focusGain != AudioManager.AUDIOFOCUS_NONE
|
||||
&& focusGain != AudioManager.AUDIOFOCUS_GAIN
|
||||
&& focusGain != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT
|
||||
&& focusGain != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
|
||||
&& focusGain != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE) {
|
||||
throw new IllegalArgumentException("Illegal audio focus type " + focusGain);
|
||||
}
|
||||
mAudioFocusType = focusGain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link AudioAttributes} to be used during the playback of the video.
|
||||
* @param attributes non-null <code>AudioAttributes</code>.
|
||||
*/
|
||||
public void setAudioAttributes(@NonNull AudioAttributes attributes) {
|
||||
if (attributes == null) {
|
||||
throw new IllegalArgumentException("Illegal null AudioAttributes");
|
||||
}
|
||||
mAudioAttributes = attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an external subtitle source file (from the provided input stream.)
|
||||
*
|
||||
@@ -301,8 +353,7 @@ public class VideoView extends SurfaceView
|
||||
mMediaPlayer = null;
|
||||
mCurrentState = STATE_IDLE;
|
||||
mTargetState = STATE_IDLE;
|
||||
AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
|
||||
am.abandonAudioFocus(null);
|
||||
mAudioManager.abandonAudioFocus(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -315,8 +366,10 @@ public class VideoView extends SurfaceView
|
||||
// called start() previously
|
||||
release(false);
|
||||
|
||||
AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
|
||||
am.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
|
||||
if (mAudioFocusType != AudioManager.AUDIOFOCUS_NONE) {
|
||||
// TODO this should have a focus listener
|
||||
mAudioManager.requestAudioFocus(null, mAudioAttributes, mAudioFocusType, 0 /*flags*/);
|
||||
}
|
||||
|
||||
try {
|
||||
mMediaPlayer = new MediaPlayer();
|
||||
@@ -345,7 +398,7 @@ public class VideoView extends SurfaceView
|
||||
mCurrentBufferPercentage = 0;
|
||||
mMediaPlayer.setDataSource(mContext, mUri, mHeaders);
|
||||
mMediaPlayer.setDisplay(mSurfaceHolder);
|
||||
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
||||
mMediaPlayer.setAudioAttributes(mAudioAttributes);
|
||||
mMediaPlayer.setScreenOnWhilePlaying(true);
|
||||
mMediaPlayer.prepareAsync();
|
||||
|
||||
@@ -482,6 +535,9 @@ public class VideoView extends SurfaceView
|
||||
if (mOnCompletionListener != null) {
|
||||
mOnCompletionListener.onCompletion(mMediaPlayer);
|
||||
}
|
||||
if (mAudioFocusType != AudioManager.AUDIOFOCUS_NONE) {
|
||||
mAudioManager.abandonAudioFocus(null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -644,8 +700,9 @@ public class VideoView extends SurfaceView
|
||||
if (cleartargetstate) {
|
||||
mTargetState = STATE_IDLE;
|
||||
}
|
||||
AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
|
||||
am.abandonAudioFocus(null);
|
||||
if (mAudioFocusType != AudioManager.AUDIOFOCUS_NONE) {
|
||||
mAudioManager.abandonAudioFocus(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1981,8 +1981,7 @@ public class AudioManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Used to indicate no audio focus has been gained or lost.
|
||||
* Used to indicate no audio focus has been gained or lost, or requested.
|
||||
*/
|
||||
public static final int AUDIOFOCUS_NONE = 0;
|
||||
|
||||
|
||||
@@ -366,11 +366,18 @@ public final class AudioPlaybackConfiguration implements Parcelable {
|
||||
* @param pw
|
||||
*/
|
||||
public void dump(PrintWriter pw) {
|
||||
pw.println(" ID:" + mPlayerIId
|
||||
+ " -- type:" + toLogFriendlyPlayerType(mPlayerType)
|
||||
+ " -- u/pid:" + mClientUid +"/" + mClientPid
|
||||
+ " -- state:" + toLogFriendlyPlayerState(mPlayerState)
|
||||
+ " -- attr:" + mPlayerAttr);
|
||||
pw.println(" " + toLogFriendlyString(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public static String toLogFriendlyString(AudioPlaybackConfiguration apc) {
|
||||
return new String("ID:" + apc.mPlayerIId
|
||||
+ " -- type:" + toLogFriendlyPlayerType(apc.mPlayerType)
|
||||
+ " -- u/pid:" + apc.mClientUid +"/" + apc.mClientPid
|
||||
+ " -- state:" + toLogFriendlyPlayerState(apc.mPlayerState)
|
||||
+ " -- attr:" + apc.mPlayerAttr);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<AudioPlaybackConfiguration> CREATOR
|
||||
|
||||
@@ -47,6 +47,7 @@ public final class PlaybackActivityMonitor
|
||||
implements AudioPlaybackConfiguration.PlayerDeathMonitor, PlayerFocusEnforcer {
|
||||
|
||||
public final static String TAG = "AudioService.PlaybackActivityMonitor";
|
||||
|
||||
private final static boolean DEBUG = false;
|
||||
private final static int VOLUME_SHAPER_SYSTEM_DUCK_ID = 1;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user