Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0f49f82e authored by Jean-Michel Trivi's avatar Jean-Michel Trivi
Browse files

VideoView: option for audio focus, support for AudioAttributes

Add API for VideoView to select whether it uses audio focus during
  playback, and how.
Add support for AudioAttributes

Test: cts-tradefed run cts -m CtsWidgetTestCases -t android.widget.cts.VideoViewTest
Bug 30955183
Bug 30258418

Change-Id: I581d32c79c78b8197ded2319e0d5bfdc35b93c5e
parent f7d364d8
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -20797,6 +20797,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
@@ -50802,6 +50803,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);
+3 −0
Original line number Diff line number Diff line
@@ -22461,6 +22461,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
@@ -54708,6 +54709,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);
+3 −0
Original line number Diff line number Diff line
@@ -20893,6 +20893,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
@@ -51181,6 +51182,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);
+64 −7
Original line number Diff line number Diff line
@@ -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);
            }
        }
    }

+1 −2
Original line number Diff line number Diff line
@@ -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;

Loading