Merge pull request #52 from androidx/release-1.0

r1.0.0-alpha03
This commit is contained in:
Ian Baker 2022-03-15 15:37:28 +00:00 committed by GitHub
commit 72a4fb082d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 1050 additions and 746 deletions

View File

@ -94,15 +94,13 @@ to prevent build errors.
Cloning the repository and depending on the modules locally is required when
using some libraries. It's also a suitable approach if you want to make local
changes, or if you want to use the main branch.
changes, or if you want to use the `main` branch.
First, clone the repository into a local directory and checkout the desired
branch:
First, clone the repository into a local directory:
```sh
git clone https://github.com/androidx/media.git
cd media
git checkout main
```
Next, add the following to your project's `settings.gradle` file, replacing
@ -129,7 +127,7 @@ implementation project(':media-lib-ui')
Development work happens on the `main` branch. Pull requests should normally be
made to this branch.
We plan to add a release branch soon.
The `release` branch holds the most recent stable release.
#### Using Android Studio

View File

@ -1,6 +1,30 @@
# Release notes
### 1.0.0-alpha02 (2022-03-09)
### 1.0.0-alpha03 (2022-03-14)
This release corresponds to the
[ExoPlayer 2.17.1 release](https://github.com/google/ExoPlayer/releases/tag/r2.17.1).
* Audio:
* Fix error checking audio capabilities for Dolby Atmos (E-AC3-JOC) in
HLS.
* Extractors:
* FMP4: Fix issue where emsg sample metadata could be output in the wrong
order for streams containing both v0 and v1 emsg atoms
([#9996](https://github.com/google/ExoPlayer/issues/9996)).
* Text:
* Fix the interaction of `SingleSampleMediaSource.Factory.setTrackId` and
`MediaItem.SubtitleConfiguration.Builder.setId` to prioritise the
`SubtitleConfiguration` field and fall back to the `Factory` value if
it's not set
([#10016](https://github.com/google/ExoPlayer/issues/10016)).
* Ad playback:
* Fix audio underruns between ad periods in live HLS SSAI streams.
### 1.0.0-alpha02 (2022-03-02)
This release corresponds to the
[ExoPlayer 2.17.0 release](https://github.com/google/ExoPlayer/releases/tag/r2.17.0).
* Core Library:
* Add protected method `DefaultRenderersFactory.getCodecAdapterFactory()`
@ -18,7 +42,7 @@
from a secure codec to another codec
([#8696](https://github.com/google/ExoPlayer/issues/8696)).
* Add `MediaCodecAdapter.getMetrics()` to allow users obtain metrics data
from `MediaCodec`.
from `MediaCodec`
([#9766](https://github.com/google/ExoPlayer/issues/9766)).
* Fix Maven dependency resolution
([#8353](https://github.com/google/ExoPlayer/issues/8353)).
@ -63,17 +87,17 @@
under sufficient network bandwidth even if playback is very close to the
live edge ([#9784](https://github.com/google/ExoPlayer/issues/9784)).
* Video:
* Fix decoder fallback logic for Dolby Vision
to use a compatible H264/H265 decoder if needed.
* Fix decoder fallback logic for Dolby Vision to use a compatible
H264/H265 decoder if needed.
* Audio:
* Fix decoder fallback logic for Dolby Atmos (E-AC3-JOC)
to use a compatible E-AC3 decoder if needed.
* Fix decoder fallback logic for Dolby Atmos (E-AC3-JOC) to use a
compatible E-AC3 decoder if needed.
* Change `AudioCapabilities` APIs to require passing explicitly
`AudioCapabilities.DEFAULT_AUDIO_CAPABILITIES` instead of `null`.
* Allow customization of the `AudioTrack` buffer size calculation by
injecting an `AudioTrackBufferSizeProvider` to `DefaultAudioSink`.
injecting an `AudioTrackBufferSizeProvider` to `DefaultAudioSink`
([#8891](https://github.com/google/ExoPlayer/issues/8891)).
* Retry `AudioTrack` creation if the requested buffer size was > 1MB.
* Retry `AudioTrack` creation if the requested buffer size was > 1MB
([#9712](https://github.com/google/ExoPlayer/issues/9712)).
* Extractors:
* WAV: Add support for RF64 streams
@ -120,7 +144,8 @@
* Support the `forced-subtitle` track role
([#9727](https://github.com/google/ExoPlayer/issues/9727)).
* Stop interpreting the `main` track role as `C.SELECTION_FLAG_DEFAULT`.
* Fix base URL exclusion logic for manifests that do not declare the DVB namespace ([#9856](https://github.com/google/ExoPlayer/issues/9856)).
* Fix base URL exclusion logic for manifests that do not declare the DVB
namespace ([#9856](https://github.com/google/ExoPlayer/issues/9856)).
* Support relative `MPD.Location` URLs
([#9939](https://github.com/google/ExoPlayer/issues/9939)).
* HLS:
@ -133,8 +158,6 @@
`HlsMediaSource.Factory.setAllowChunklessPreparation(false)`.
* Support key-frame accurate seeking in HLS
([#2882](https://github.com/google/ExoPlayer/issues/2882)).
* Correctly populate `Format.label` for audio only HLS streams
([#9608](https://github.com/google/ExoPlayer/issues/9608)).
* RTSP:
* Provide a client API to override the `SocketFactory` used for any server
connection ([#9606](https://github.com/google/ExoPlayer/pull/9606)).
@ -154,12 +177,10 @@
* Fix potential NPE in `Transformer.getProgress` when releasing the muxer
throws.
* Add a demo app for applying transformations.
* The transformer module is no longer included by depending on
`com.google.android.exoplayer:exoplayer`. To continue using transformer,
add an additional dependency on
`com.google.android.exoplayer:exoplayer-transformer`.
* MediaSession extension:
* By default, `MediaSessionConnector` now clears the playlist on stop. Apps that want the playlist to be retained can call `setClearMediaItemsOnStop(false)` on the connector.
* By default, `MediaSessionConnector` now clears the playlist on stop.
Apps that want the playlist to be retained can call
`setClearMediaItemsOnStop(false)` on the connector.
* Cast extension:
* Fix bug that prevented `CastPlayer` from calling `onIsPlayingChanged`
correctly ([#9792](https://github.com/google/ExoPlayer/issues/9792)).
@ -178,38 +199,38 @@
([#9528](https://github.com/google/ExoPlayer/issues/9528)).
* Remove deprecated symbols:
* Remove `Player.EventLister`. Use `Player.Listener` instead.
* Remove `MediaSourceFactory#setDrmSessionManager`,
`MediaSourceFactory#setDrmHttpDataSourceFactory`, and
`MediaSourceFactory#setDrmUserAgent`. Use
`MediaSourceFactory#setDrmSessionManagerProvider` instead.
* Remove `MediaSourceFactory#setStreamKeys`. Use
`MediaItem.Builder#setStreamKeys` instead.
* Remove `MediaSourceFactory#createMediaSource(Uri)`. Use
`MediaSourceFactory#createMediaSource(MediaItem)` instead.
* Remove `MediaSourceFactory.setDrmSessionManager`,
`MediaSourceFactory.setDrmHttpDataSourceFactory`, and
`MediaSourceFactory.setDrmUserAgent`. Use
`MediaSourceFactory.setDrmSessionManagerProvider` instead.
* Remove `MediaSourceFactory.setStreamKeys`. Use
`MediaItem.Builder.setStreamKeys` instead.
* Remove `MediaSourceFactory.createMediaSource(Uri)`. Use
`MediaSourceFactory.createMediaSource(MediaItem)` instead.
* Remove `setTag` from `DashMediaSource`, `HlsMediaSource` and
`SsMediaSource`. Use `MediaItem.Builder#setTag` instead.
* Remove `DashMediaSource#setLivePresentationDelayMs(long, boolean)`. Use
`MediaItem.Builder#setLiveConfiguration` and
`MediaItem.LiveConfiguration.Builder#setTargetOffsetMs` to override the
manifest, or `DashMediaSource#setFallbackTargetLiveOffsetMs` to provide
`SsMediaSource`. Use `MediaItem.Builder.setTag` instead.
* Remove `DashMediaSource.setLivePresentationDelayMs(long, boolean)`. Use
`MediaItem.Builder.setLiveConfiguration` and
`MediaItem.LiveConfiguration.Builder.setTargetOffsetMs` to override the
manifest, or `DashMediaSource.setFallbackTargetLiveOffsetMs` to provide
a fallback value.
* Remove `(Simple)ExoPlayer.setThrowsWhenUsingWrongThread`. Opting out of
the thread enforcement is no longer possible.
* Remove `ActionFile` and `ActionFileUpgradeUtil`. Use ExoPlayer 2.16.1 or
before to use `ActionFileUpgradeUtil` to merge legacy action files into
`DefaultDownloadIndex`.
* Remove `ProgressiveMediaSource#setExtractorsFactory`. Use
* Remove `ProgressiveMediaSource.setExtractorsFactory`. Use
`ProgressiveMediaSource.Factory(DataSource.Factory, ExtractorsFactory)`
constructor instead.
* Remove `ProgressiveMediaSource.Factory#setTag` and, and
`ProgressiveMediaSource.Factory#setCustomCacheKey`. Use
`MediaItem.Builder#setTag` and `MediaItem.Builder#setCustomCacheKey`
* Remove `ProgressiveMediaSource.Factory.setTag` and
`ProgressiveMediaSource.Factory.setCustomCacheKey`. Use
`MediaItem.Builder.setTag` and `MediaItem.Builder.setCustomCacheKey`
instead.
* Remove `DefaultRenderersFactory(Context, @ExtensionRendererMode int)`
and `DefaultRenderersFactory(Context, @ExtensionRendererMode int, long)`
constructors. Use the `DefaultRenderersFactory(Context)` constructor,
`DefaultRenderersFactory#setExtensionRendererMode`, and
`DefaultRenderersFactory#setAllowedVideoJoiningTimeMs` instead.
`DefaultRenderersFactory.setExtensionRendererMode`, and
`DefaultRenderersFactory.setAllowedVideoJoiningTimeMs` instead.
* Remove all public `CronetDataSource` constructors. Use
`CronetDataSource.Factory` instead.
* Change the following `IntDefs` to `@Target(TYPE_USE)` only. This may break

View File

@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
project.ext {
releaseVersion = '1.0.0-alpha02'
releaseVersionCode = 1_000_000_0_02
releaseVersion = '1.0.0-alpha03'
releaseVersionCode = 1_000_000_0_03
minSdkVersion = 16
appTargetSdkVersion = 29
// Upgrading this requires [Internal ref: b/193254928] to be fixed, or some

View File

@ -30,6 +30,7 @@ import android.widget.ListView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.media3.common.MediaItem
import androidx.media3.common.Player
import androidx.media3.session.MediaBrowser
import androidx.media3.session.SessionToken
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
@ -179,6 +180,9 @@ class PlayableFolderActivity : AppCompatActivity() {
returnConvertView.findViewById<TextView>(R.id.add_button).setOnClickListener {
val browser = this@PlayableFolderActivity.browser ?: return@setOnClickListener
browser.addMediaItem(mediaItem)
if (browser.playbackState == Player.STATE_IDLE) {
browser.prepare()
}
Snackbar.make(
findViewById<LinearLayout>(R.id.linear_layout),
getString(R.string.added_media_item_format, mediaItem.mediaMetadata.title),

View File

@ -96,7 +96,6 @@ class PlaybackService : MediaLibraryService() {
val item = MediaItemTree.getItemFromTitle(mediaTitle) ?: MediaItemTree.getRandomItem()
player.setMediaItem(item)
player.prepare()
}
override fun onSetMediaUri(

Binary file not shown.

View File

@ -1,6 +1,5 @@
#Wed Mar 04 12:41:50 GMT 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https://services.gradle.org/distributions/gradle-7.3.3-all.zip

298
gradlew vendored
View File

@ -1,79 +1,129 @@
#!/usr/bin/env bash
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
MAX_FD=maximum
warn () {
echo "$*"
}
} >&2
die () {
echo
echo "$*"
echo
exit 1
}
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@ -82,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
@ -90,75 +140,95 @@ location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

53
gradlew.bat vendored
View File

@ -1,3 +1,19 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@ -8,20 +24,23 @@
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@ -35,7 +54,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@ -45,34 +64,14 @@ echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell

View File

@ -29,11 +29,11 @@ public final class MediaLibraryInfo {
/** The version of the library expressed as a string, for example "1.2.3" or "1.2.3-beta01". */
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION_INT) or vice versa.
public static final String VERSION = "1.0.0-alpha02";
public static final String VERSION = "1.0.0-alpha03";
/** The version of the library expressed as {@code TAG + "/" + VERSION}. */
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa.
public static final String VERSION_SLASHY = "AndroidXMedia3/1.0.0-alpha02";
public static final String VERSION_SLASHY = "AndroidXMedia3/1.0.0-alpha03";
/**
* The version of the library expressed as an integer, for example 1002003300.
@ -47,7 +47,7 @@ public final class MediaLibraryInfo {
* (123-045-006-3-00).
*/
// Intentionally hardcoded. Do not derive from other constants (e.g. VERSION) or vice versa.
public static final int VERSION_INT = 1_000_000_0_02;
public static final int VERSION_INT = 1_000_000_0_03;
/** Whether the library was compiled with {@link Assertions} checks enabled. */
public static final boolean ASSERTIONS_ENABLED = true;

View File

@ -56,6 +56,7 @@ import androidx.media3.exoplayer.DefaultMediaClock.PlaybackParametersListener;
import androidx.media3.exoplayer.analytics.AnalyticsCollector;
import androidx.media3.exoplayer.analytics.PlayerId;
import androidx.media3.exoplayer.drm.DrmSession;
import androidx.media3.exoplayer.metadata.MetadataRenderer;
import androidx.media3.exoplayer.source.BehindLiveWindowException;
import androidx.media3.exoplayer.source.MediaPeriod;
import androidx.media3.exoplayer.source.MediaSource.MediaPeriodId;
@ -2228,6 +2229,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
return reading.info.isFollowedByTransitionToSameStream
&& nextPeriod.prepared
&& (renderer instanceof TextRenderer // [internal: b/181312195]
|| renderer instanceof MetadataRenderer
|| renderer.getReadingPositionUs() >= nextPeriod.getStartPositionRendererTime());
}

View File

@ -1739,8 +1739,11 @@ public final class DefaultAudioSink implements AudioSink {
// the channel count for this encoding, but before then there is no way to query it so we
// assume 6 channel audio is supported.
if (Util.SDK_INT >= 29) {
// Default to 48 kHz if the format doesn't have a sample rate (for example, for chunkless
// HLS preparation). See [Internal: b/222127949].
int sampleRate = format.sampleRate != Format.NO_VALUE ? format.sampleRate : 48000;
channelCount =
getMaxSupportedChannelCountForPassthroughV29(C.ENCODING_E_AC3_JOC, format.sampleRate);
getMaxSupportedChannelCountForPassthroughV29(C.ENCODING_E_AC3_JOC, sampleRate);
if (channelCount == 0) {
Log.w(TAG, "E-AC3 JOC encoding supported but no channel count supported");
return null;

View File

@ -24,6 +24,8 @@ import static java.lang.annotation.ElementType.TYPE_USE;
import androidx.annotation.IntDef;
import androidx.media3.common.util.UnstableApi;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** Thrown when the requested DRM scheme is not supported. */
@ -35,8 +37,9 @@ public final class UnsupportedDrmException extends Exception {
* #REASON_INSTANTIATION_ERROR}.
*/
// @Target list includes both 'default' targets and TYPE_USE, to ensure backwards compatibility
// with Kotlin usages from before TYPE_USE was added. @Retention(RetentionPolicy.SOURCE)
// with Kotlin usages from before TYPE_USE was added.
@Documented
@Retention(RetentionPolicy.SOURCE)
@Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, TYPE_USE})
@IntDef({REASON_UNSUPPORTED_SCHEME, REASON_INSTANTIATION_ERROR})
public @interface Reason {}

View File

@ -74,11 +74,12 @@ public final class SingleSampleMediaSource extends BaseMediaSource {
}
/**
* Sets an optional track id to be used.
*
* @param trackId An optional track id.
* @return This factory, for convenience.
* @deprecated Use {@link MediaItem.SubtitleConfiguration.Builder#setId(String)} instead (on the
* {@link MediaItem.SubtitleConfiguration} passed to {@link
* #createMediaSource(MediaItem.SubtitleConfiguration, long)}). {@code trackId} will only be
* used if {@link MediaItem.SubtitleConfiguration#id} is {@code null}.
*/
@Deprecated
public Factory setTrackId(@Nullable String trackId) {
this.trackId = trackId;
return this;
@ -157,29 +158,28 @@ public final class SingleSampleMediaSource extends BaseMediaSource {
this.durationUs = durationUs;
this.loadErrorHandlingPolicy = loadErrorHandlingPolicy;
this.treatLoadErrorsAsEndOfStream = treatLoadErrorsAsEndOfStream;
mediaItem =
this.mediaItem =
new MediaItem.Builder()
.setUri(Uri.EMPTY)
.setMediaId(subtitleConfiguration.uri.toString())
.setSubtitleConfigurations(ImmutableList.of(subtitleConfiguration))
.setTag(tag)
.build();
format =
this.format =
new Format.Builder()
.setId(trackId)
.setSampleMimeType(firstNonNull(subtitleConfiguration.mimeType, MimeTypes.TEXT_UNKNOWN))
.setLanguage(subtitleConfiguration.language)
.setSelectionFlags(subtitleConfiguration.selectionFlags)
.setRoleFlags(subtitleConfiguration.roleFlags)
.setLabel(subtitleConfiguration.label)
.setId(subtitleConfiguration.id)
.setId(subtitleConfiguration.id != null ? subtitleConfiguration.id : trackId)
.build();
dataSpec =
this.dataSpec =
new DataSpec.Builder()
.setUri(subtitleConfiguration.uri)
.setFlags(DataSpec.FLAG_ALLOW_GZIP)
.build();
timeline =
this.timeline =
new SinglePeriodTimeline(
durationUs,
/* isSeekable= */ true,

View File

@ -105,11 +105,7 @@ import java.util.Map;
import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* MediaSource for IMA server side inserted ad streams.
*
* <p>TODO(bachinger) add code snippet from PlayerActivity
*/
/** MediaSource for IMA server side inserted ad streams. */
@UnstableApi
public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSource<Void> {
@ -119,8 +115,6 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
*
* <p>Apps can use the {@link ImaServerSideAdInsertionMediaSource.Factory} to customized the
* {@link DefaultMediaSourceFactory} that is used to build a player:
*
* <p>TODO(bachinger) add code snippet from PlayerActivity
*/
public static final class Factory implements MediaSource.Factory {
@ -461,6 +455,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
@Nullable private IOException loadError;
private @MonotonicNonNull Timeline contentTimeline;
private AdPlaybackState adPlaybackState;
private int firstSeenAdIndexInAdGroup;
private ImaServerSideAdInsertionMediaSource(
MediaItem mediaItem,
@ -698,18 +693,21 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
return adPlaybackState;
}
private static AdPlaybackState addLiveAdBreak(
private AdPlaybackState addLiveAdBreak(
Ad ad, long currentPeriodPositionUs, AdPlaybackState adPlaybackState) {
AdPodInfo adPodInfo = ad.getAdPodInfo();
long adDurationUs = secToUs(ad.getDuration());
int adIndexInAdGroup = adPodInfo.getAdPosition() - 1;
// TODO(b/208398934) Support seeking backwards.
if (adIndexInAdGroup == 0 || adPlaybackState.adGroupCount == 1) {
firstSeenAdIndexInAdGroup = adIndexInAdGroup;
// Adjust count and ad index in case we joined the live stream within an ad group.
int adCount = adPodInfo.getTotalAds() - firstSeenAdIndexInAdGroup;
adIndexInAdGroup -= firstSeenAdIndexInAdGroup;
// First ad of group. Create a new group with all ads.
long[] adDurationsUs =
updateAdDurationAndPropagate(
new long[adPodInfo.getTotalAds()],
new long[adCount],
adIndexInAdGroup,
adDurationUs,
secToUs(adPodInfo.getMaxDuration()));
@ -721,6 +719,11 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
/* adDurationsUs...= */ adDurationsUs);
} else {
int adGroupIndex = adPlaybackState.adGroupCount - 2;
adIndexInAdGroup -= firstSeenAdIndexInAdGroup;
if (adPodInfo.getTotalAds() == adPodInfo.getAdPosition()) {
// Reset the ad index whe we are at the last ad in the group.
firstSeenAdIndexInAdGroup = 0;
}
adPlaybackState =
updateAdDurationInAdGroup(adGroupIndex, adIndexInAdGroup, adDurationUs, adPlaybackState);
AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(adGroupIndex);
@ -857,7 +860,7 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
long positionInWindowUs =
timeline.getPeriod(player.getCurrentPeriodIndex(), new Timeline.Period())
.positionInWindowUs;
long currentPeriodPosition = msToUs(player.getCurrentPosition()) - positionInWindowUs;
long currentPeriodPosition = msToUs(player.getContentPosition()) - positionInWindowUs;
newAdPlaybackState =
addLiveAdBreak(
event.getAd(),

View File

@ -666,14 +666,23 @@ public class FragmentedMp4Extractor implements Extractor {
emsgTrackOutput.sampleData(encodedEventMessage, sampleSize);
}
// Output the sample metadata. This is made a little complicated because emsg-v0 atoms
// have presentation time *delta* while v1 atoms have absolute presentation time.
// Output the sample metadata.
if (sampleTimeUs == C.TIME_UNSET) {
// We need the first sample timestamp in the segment before we can output the metadata.
// We're processing a v0 emsg atom, which contains a presentation time delta, and cannot yet
// calculate its absolute sample timestamp. Defer outputting the metadata until we can.
pendingMetadataSampleInfos.addLast(
new MetadataSampleInfo(presentationTimeDeltaUs, sampleSize));
new MetadataSampleInfo(
presentationTimeDeltaUs, /* sampleTimeIsRelative= */ true, sampleSize));
pendingMetadataSampleBytes += sampleSize;
} else if (!pendingMetadataSampleInfos.isEmpty()) {
// We also need to defer outputting metadata if pendingMetadataSampleInfos is non-empty, else
// we will output metadata for samples in the wrong order. See:
// https://github.com/google/ExoPlayer/issues/9996.
pendingMetadataSampleInfos.addLast(
new MetadataSampleInfo(sampleTimeUs, /* sampleTimeIsRelative= */ false, sampleSize));
pendingMetadataSampleBytes += sampleSize;
} else {
// We can output the sample metadata immediately.
if (timestampAdjuster != null) {
sampleTimeUs = timestampAdjuster.adjustSampleTimestamp(sampleTimeUs);
}
@ -1459,19 +1468,30 @@ public class FragmentedMp4Extractor implements Extractor {
return true;
}
/**
* Called immediately after outputting a non-metadata sample, to output any pending metadata
* samples.
*
* @param sampleTimeUs The timestamp of the non-metadata sample that was just output.
*/
private void outputPendingMetadataSamples(long sampleTimeUs) {
while (!pendingMetadataSampleInfos.isEmpty()) {
MetadataSampleInfo sampleInfo = pendingMetadataSampleInfos.removeFirst();
pendingMetadataSampleBytes -= sampleInfo.size;
long metadataTimeUs = sampleTimeUs + sampleInfo.presentationTimeDeltaUs;
MetadataSampleInfo metadataSampleInfo = pendingMetadataSampleInfos.removeFirst();
pendingMetadataSampleBytes -= metadataSampleInfo.size;
long metadataSampleTimeUs = metadataSampleInfo.sampleTimeUs;
if (metadataSampleInfo.sampleTimeIsRelative) {
// The metadata sample timestamp is relative to the timestamp of the non-metadata sample
// that was just output. Make it absolute.
metadataSampleTimeUs += sampleTimeUs;
}
if (timestampAdjuster != null) {
metadataTimeUs = timestampAdjuster.adjustSampleTimestamp(metadataTimeUs);
metadataSampleTimeUs = timestampAdjuster.adjustSampleTimestamp(metadataSampleTimeUs);
}
for (TrackOutput emsgTrackOutput : emsgTrackOutputs) {
emsgTrackOutput.sampleMetadata(
metadataTimeUs,
metadataSampleTimeUs,
C.BUFFER_FLAG_KEY_FRAME,
sampleInfo.size,
metadataSampleInfo.size,
pendingMetadataSampleBytes,
null);
}
@ -1577,11 +1597,13 @@ public class FragmentedMp4Extractor implements Extractor {
/** Holds data corresponding to a metadata sample. */
private static final class MetadataSampleInfo {
public final long presentationTimeDeltaUs;
public final long sampleTimeUs;
public final boolean sampleTimeIsRelative;
public final int size;
public MetadataSampleInfo(long presentationTimeDeltaUs, int size) {
this.presentationTimeDeltaUs = presentationTimeDeltaUs;
public MetadataSampleInfo(long sampleTimeUs, boolean sampleTimeIsRelative, int size) {
this.sampleTimeUs = sampleTimeUs;
this.sampleTimeIsRelative = sampleTimeIsRelative;
this.size = size;
}
}

View File

@ -27,6 +27,7 @@ import android.os.Bundle;
import androidx.core.app.NotificationCompat;
import androidx.core.graphics.drawable.IconCompat;
import androidx.media3.common.MediaMetadata;
import androidx.media3.common.Player;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util;
@ -93,20 +94,21 @@ import androidx.media3.common.util.Util;
IconCompat.createWithResource(context, R.drawable.media3_notification_seek_to_previous),
context.getString(R.string.media3_controls_seek_to_previous_description),
MediaNotification.ActionFactory.COMMAND_SKIP_TO_PREVIOUS));
if (mediaController.getPlayWhenReady()) {
// Pause action.
builder.addAction(
actionFactory.createMediaAction(
IconCompat.createWithResource(context, R.drawable.media3_notification_pause),
context.getString(R.string.media3_controls_pause_description),
MediaNotification.ActionFactory.COMMAND_PAUSE));
} else {
if (mediaController.getPlaybackState() == Player.STATE_ENDED
|| !mediaController.getPlayWhenReady()) {
// Play action.
builder.addAction(
actionFactory.createMediaAction(
IconCompat.createWithResource(context, R.drawable.media3_notification_play),
context.getString(R.string.media3_controls_play_description),
MediaNotification.ActionFactory.COMMAND_PLAY));
} else {
// Pause action.
builder.addAction(
actionFactory.createMediaAction(
IconCompat.createWithResource(context, R.drawable.media3_notification_pause),
context.getString(R.string.media3_controls_pause_description),
MediaNotification.ActionFactory.COMMAND_PAUSE));
}
// Skip to next action.
builder.addAction(

View File

@ -198,7 +198,7 @@ import java.util.concurrent.atomic.AtomicReference;
try {
int page = options.getInt(EXTRA_PAGE);
int pageSize = options.getInt(EXTRA_PAGE_SIZE);
if (page > 0 && pageSize > 0) {
if (page >= 0 && pageSize > 0) {
// Requesting the list of children through pagination.
@Nullable
LibraryParams params =
@ -223,7 +223,7 @@ import java.util.concurrent.atomic.AtomicReference;
parentId,
/* page= */ 0,
/* pageSize= */ Integer.MAX_VALUE,
/* extras= */ null);
/* params= */ null);
sendLibraryResultWithMediaItemsWhenReady(result, future);
});
}

View File

@ -196,7 +196,9 @@ import java.util.concurrent.TimeoutException;
@Override
public void onEvents(Player player, Player.Events events) {
if (events.containsAny(
Player.EVENT_PLAY_WHEN_READY_CHANGED, Player.EVENT_MEDIA_METADATA_CHANGED)) {
Player.EVENT_PLAYBACK_STATE_CHANGED,
Player.EVENT_PLAY_WHEN_READY_CHANGED,
Player.EVENT_MEDIA_METADATA_CHANGED)) {
updateNotification(session);
}
}

View File

@ -28,6 +28,8 @@ import static androidx.media3.common.Player.COMMAND_SET_REPEAT_MODE;
import static androidx.media3.common.Player.COMMAND_SET_SHUFFLE_MODE;
import static androidx.media3.common.Player.COMMAND_SET_SPEED_AND_PITCH;
import static androidx.media3.common.Player.COMMAND_STOP;
import static androidx.media3.common.Player.STATE_ENDED;
import static androidx.media3.common.Player.STATE_IDLE;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Assertions.checkStateNotNull;
import static androidx.media3.common.util.Util.postOrRun;
@ -231,7 +233,17 @@ import org.checkerframework.checker.initialization.qual.Initialized;
} else {
dispatchSessionTaskWithPlayerCommand(
COMMAND_PLAY_PAUSE,
(controller) -> sessionImpl.getPlayerWrapper().play(),
(controller) -> {
PlayerWrapper playerWrapper = sessionImpl.getPlayerWrapper();
@Player.State int playbackState = playerWrapper.getPlaybackState();
if (playbackState == STATE_IDLE) {
playerWrapper.prepare();
} else if (playbackState == STATE_ENDED) {
playerWrapper.seekTo(
playerWrapper.getCurrentMediaItemIndex(), /* positionMs= */ C.TIME_UNSET);
}
playerWrapper.play();
},
remoteUserInfo);
}
}
@ -285,7 +297,17 @@ import org.checkerframework.checker.initialization.qual.Initialized;
public void onPlay() {
dispatchSessionTaskWithPlayerCommand(
COMMAND_PLAY_PAUSE,
controller -> sessionImpl.getPlayerWrapper().play(),
controller -> {
PlayerWrapper playerWrapper = sessionImpl.getPlayerWrapper();
@Player.State int playbackState = playerWrapper.getPlaybackState();
if (playbackState == Player.STATE_IDLE) {
playerWrapper.prepare();
} else if (playbackState == Player.STATE_ENDED) {
playerWrapper.seekTo(
playerWrapper.getCurrentMediaItemIndex(), /* positionMs= */ C.TIME_UNSET);
}
playerWrapper.play();
},
sessionCompat.getCurrentControllerInfo());
}
@ -321,7 +343,15 @@ import org.checkerframework.checker.initialization.qual.Initialized;
if (sessionImpl.onSetMediaUriOnHandler(
controller, mediaUri, extras == null ? Bundle.EMPTY : extras)
== RESULT_SUCCESS) {
sessionImpl.getPlayerWrapper().play();
PlayerWrapper playerWrapper = sessionImpl.getPlayerWrapper();
@Player.State int playbackState = playerWrapper.getPlaybackState();
if (playbackState == Player.STATE_IDLE) {
playerWrapper.prepare();
} else if (playbackState == STATE_ENDED) {
playerWrapper.seekTo(
playerWrapper.getCurrentMediaItemIndex(), /* positionMs= */ C.TIME_UNSET);
}
playerWrapper.play();
}
});
}

View File

@ -181,7 +181,6 @@ public class MediaSessionAndControllerTest {
MockPlayer player =
new MockPlayer.Builder()
.setApplicationLooper(threadTestRule.getHandler().getLooper())
.setLatchCount(1)
.build();
MediaSession session =
sessionTestRule.ensureReleaseAfterTest(
@ -190,8 +189,7 @@ public class MediaSessionAndControllerTest {
threadTestRule.getHandler().postAndSync(controller::play);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.playCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
}
@Test

View File

@ -74,7 +74,6 @@ public class MediaSessionCallbackTest {
context = ApplicationProvider.getApplicationContext();
player =
new MockPlayer.Builder()
.setLatchCount(1)
.setApplicationLooper(threadTestRule.getHandler().getLooper())
.build();
}
@ -157,15 +156,14 @@ public class MediaSessionCallbackTest {
controllerTestRule.createRemoteController(session.getToken());
controller.prepare();
assertThat(player.countDownLatch.await(NO_RESPONSE_TIMEOUT_MS, MILLISECONDS)).isFalse();
assertThat(player.prepareCalled).isFalse();
Thread.sleep(NO_RESPONSE_TIMEOUT_MS);
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isFalse();
assertThat(commands).hasSize(1);
assertThat(commands.get(0)).isEqualTo(Player.COMMAND_PREPARE);
controller.play();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.playCalled).isTrue();
assertThat(player.prepareCalled).isFalse();
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isFalse();
assertThat(commands).hasSize(2);
assertThat(commands.get(1)).isEqualTo(Player.COMMAND_PLAY_PAUSE);
}

View File

@ -94,8 +94,7 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
public void setUp() {
context = ApplicationProvider.getApplicationContext();
handler = threadTestRule.getHandler();
player =
new MockPlayer.Builder().setLatchCount(1).setApplicationLooper(handler.getLooper()).build();
player = new MockPlayer.Builder().setApplicationLooper(handler.getLooper()).build();
audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
}
@ -206,8 +205,8 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
controller.getTransportControls().play();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.playCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
}
@Test
@ -222,8 +221,8 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
controller.getTransportControls().pause();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.pauseCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_PAUSE, TIMEOUT_MS);
}
@Test
@ -238,8 +237,8 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
controller.getTransportControls().stop();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.stopCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_STOP, TIMEOUT_MS);
}
@Test
@ -254,8 +253,8 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
controller.getTransportControls().prepare();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.prepareCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_PREPARE, TIMEOUT_MS);
}
@Test
@ -271,8 +270,8 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
long seekPosition = 12125L;
controller.getTransportControls().seekTo(seekPosition);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.seekToCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO, TIMEOUT_MS);
assertThat(player.seekPositionMs).isEqualTo(seekPosition);
}
@ -289,8 +288,8 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
float testSpeed = 2.0f;
controller.getTransportControls().setPlaybackSpeed(testSpeed);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.setPlaybackSpeedCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SET_PLAYBACK_SPEED, TIMEOUT_MS);
assertThat(player.playbackParameters.speed).isEqualTo(testSpeed);
}
@ -316,8 +315,7 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
MediaDescriptionCompat desc = new MediaDescriptionCompat.Builder().setMediaId(mediaId).build();
controller.addQueueItem(desc);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.addMediaItemCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_ADD_MEDIA_ITEM, TIMEOUT_MS);
assertThat(player.mediaItem.mediaId).isEqualTo(mediaId);
}
@ -344,8 +342,7 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
MediaDescriptionCompat desc = new MediaDescriptionCompat.Builder().setMediaId(mediaId).build();
controller.addQueueItem(desc, testIndex);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.addMediaItemWithIndexCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_ADD_MEDIA_ITEM_WITH_INDEX, TIMEOUT_MS);
assertThat(player.index).isEqualTo(testIndex);
assertThat(player.mediaItem.mediaId).isEqualTo(mediaId);
}
@ -375,8 +372,7 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
new MediaDescriptionCompat.Builder().setMediaId(targetItem.mediaId).build();
controller.removeQueueItem(desc);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.removeMediaItemCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_REMOVE_MEDIA_ITEM, TIMEOUT_MS);
assertThat(player.index).isEqualTo(targetIndex);
}
@ -392,8 +388,8 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
controller.getTransportControls().skipToPrevious();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.seekToPreviousCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_PREVIOUS, TIMEOUT_MS);
}
@Test
@ -408,8 +404,8 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
controller.getTransportControls().skipToNext();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.seekToNextCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_NEXT, TIMEOUT_MS);
}
@Test
@ -434,8 +430,8 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
int targetIndex = 3;
controller.getTransportControls().skipToQueueItem(queue.get(targetIndex).getQueueId());
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.seekToDefaultPositionWithMediaItemIndexCalled).isTrue();
player.awaitMethodCalled(
MockPlayer.METHOD_SEEK_TO_DEFAULT_POSITION_WITH_MEDIA_ITEM_INDEX, TIMEOUT_MS);
assertThat(player.seekMediaItemIndex).isEqualTo(targetIndex);
}
@ -452,9 +448,8 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
@PlaybackStateCompat.ShuffleMode int testShuffleMode = PlaybackStateCompat.SHUFFLE_MODE_GROUP;
controller.getTransportControls().setShuffleMode(testShuffleMode);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.setShuffleModeCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SET_SHUFFLE_MODE, TIMEOUT_MS);
assertThat(player.shuffleModeEnabled).isTrue();
}
@ -471,9 +466,8 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
int testRepeatMode = Player.REPEAT_MODE_ALL;
controller.getTransportControls().setRepeatMode(testRepeatMode);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.setRepeatModeCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SET_REPEAT_MODE, TIMEOUT_MS);
assertThat(player.repeatMode).isEqualTo(testRepeatMode);
}
@ -488,7 +482,7 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
new RemoteMediaControllerCompat(
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
MockPlayer remotePlayer =
new MockPlayer.Builder().setLatchCount(1).setApplicationLooper(handler.getLooper()).build();
new MockPlayer.Builder().setApplicationLooper(handler.getLooper()).build();
handler.postAndSync(
() -> {
remotePlayer.deviceInfo =
@ -501,8 +495,7 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
int targetVolume = 50;
controller.setVolumeTo(targetVolume, /* flags= */ 0);
assertThat(remotePlayer.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(remotePlayer.setDeviceVolumeCalled).isTrue();
remotePlayer.awaitMethodCalled(MockPlayer.METHOD_SET_DEVICE_VOLUME, TIMEOUT_MS);
assertThat(remotePlayer.deviceVolume).isEqualTo(targetVolume);
}
@ -517,7 +510,7 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
new RemoteMediaControllerCompat(
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
MockPlayer remotePlayer =
new MockPlayer.Builder().setLatchCount(1).setApplicationLooper(handler.getLooper()).build();
new MockPlayer.Builder().setApplicationLooper(handler.getLooper()).build();
handler.postAndSync(
() -> {
remotePlayer.deviceInfo =
@ -529,8 +522,7 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
controller.adjustVolume(AudioManager.ADJUST_RAISE, /* flags= */ 0);
assertThat(remotePlayer.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(remotePlayer.increaseDeviceVolumeCalled).isTrue();
remotePlayer.awaitMethodCalled(MockPlayer.METHOD_INCREASE_DEVICE_VOLUME, TIMEOUT_MS);
}
@Test
@ -544,7 +536,7 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
new RemoteMediaControllerCompat(
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
MockPlayer remotePlayer =
new MockPlayer.Builder().setLatchCount(1).setApplicationLooper(handler.getLooper()).build();
new MockPlayer.Builder().setApplicationLooper(handler.getLooper()).build();
handler.postAndSync(
() -> {
remotePlayer.deviceInfo =
@ -556,8 +548,7 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
controller.adjustVolume(AudioManager.ADJUST_LOWER, /* flags= */ 0);
assertThat(remotePlayer.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(remotePlayer.decreaseDeviceVolumeCalled).isTrue();
remotePlayer.awaitMethodCalled(MockPlayer.METHOD_DECREASE_DEVICE_VOLUME, TIMEOUT_MS);
}
@Test
@ -704,7 +695,9 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
controller =
new RemoteMediaControllerCompat(
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
controller.sendCommand(testCommand, testArgs, /* cb= */ null);
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
}
@ -723,13 +716,15 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
.setId("controllerCallback_sessionRejects")
.setSessionCallback(sessionCallback)
.build();
// Session will not accept the controller's commands.
controller =
new RemoteMediaControllerCompat(
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
controller.getTransportControls().play();
assertThat(player.countDownLatch.await(NO_RESPONSE_TIMEOUT_MS, MILLISECONDS)).isFalse();
Thread.sleep(NO_RESPONSE_TIMEOUT_MS);
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PLAY)).isFalse();
}
@Test
@ -757,10 +752,11 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
controller =
new RemoteMediaControllerCompat(
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
controller.getTransportControls().prepareFromUri(mediaUri, bundle);
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.prepareCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_PREPARE, TIMEOUT_MS);
}
@Test
@ -788,10 +784,11 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
controller =
new RemoteMediaControllerCompat(
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
controller.getTransportControls().playFromUri(request, bundle);
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.playCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
}
@Test
@ -820,10 +817,11 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
controller =
new RemoteMediaControllerCompat(
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
controller.getTransportControls().prepareFromMediaId(request, bundle);
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.prepareCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_PREPARE, TIMEOUT_MS);
}
@Test
@ -852,10 +850,11 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
controller =
new RemoteMediaControllerCompat(
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
controller.getTransportControls().playFromMediaId(mediaId, bundle);
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.playCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
}
@Test
@ -884,10 +883,11 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
controller =
new RemoteMediaControllerCompat(
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
controller.getTransportControls().prepareFromSearch(query, bundle);
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.prepareCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_PREPARE, TIMEOUT_MS);
}
@Test
@ -916,10 +916,11 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
controller =
new RemoteMediaControllerCompat(
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
controller.getTransportControls().playFromSearch(query, bundle);
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.playCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
}
@Test
@ -944,7 +945,6 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
return Futures.immediateFuture(new SessionResult(RESULT_SUCCESS));
}
};
handler.postAndSync(
() -> {
List<MediaItem> mediaItems = MediaTestUtils.createMediaItems(mediaId);
@ -958,7 +958,9 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
controller =
new RemoteMediaControllerCompat(
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
controller.getTransportControls().setRating(rating);
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
}
@ -991,16 +993,17 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
context, session.getSessionCompat().getSessionToken(), /* waitForConnection= */ true);
controller.getTransportControls().pause();
assertThat(latchForPause.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.countDownLatch.await(NO_RESPONSE_TIMEOUT_MS, MILLISECONDS)).isFalse();
assertThat(player.pauseCalled).isFalse();
Thread.sleep(NO_RESPONSE_TIMEOUT_MS);
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PAUSE)).isFalse();
assertThat(commands).hasSize(1);
assertThat(commands.get(0)).isEqualTo(COMMAND_PLAY_PAUSE);
controller.getTransportControls().prepare();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.prepareCalled).isTrue();
assertThat(player.pauseCalled).isFalse();
player.awaitMethodCalled(MockPlayer.METHOD_PREPARE, TIMEOUT_MS);
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PAUSE)).isFalse();
assertThat(commands).hasSize(2);
assertThat(commands.get(1)).isEqualTo(COMMAND_PREPARE);
}
@ -1056,7 +1059,8 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
session = null;
controller.getTransportControls().play();
assertThat(player.countDownLatch.await(NO_RESPONSE_TIMEOUT_MS, MILLISECONDS)).isFalse();
Thread.sleep(NO_RESPONSE_TIMEOUT_MS);
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PLAY)).isFalse();
// Ensure that the controller cannot use newly create session with the same ID.
// Recreated session has different session stub, so previously created controller
@ -1068,7 +1072,8 @@ public class MediaSessionCallbackWithMediaControllerCompatTest {
.build();
controller.getTransportControls().play();
assertThat(player.countDownLatch.await(NO_RESPONSE_TIMEOUT_MS, MILLISECONDS)).isFalse();
Thread.sleep(NO_RESPONSE_TIMEOUT_MS);
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PLAY)).isFalse();
}
private static class TestSessionCallback implements SessionCallback {

View File

@ -89,8 +89,7 @@ public class MediaSessionKeyEventTest {
Context context = ApplicationProvider.getApplicationContext();
audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
handler = threadTestRule.getHandler();
player =
new MockPlayer.Builder().setLatchCount(1).setApplicationLooper(handler.getLooper()).build();
player = new MockPlayer.Builder().setApplicationLooper(handler.getLooper()).build();
sessionCallback = new TestSessionCallback();
session = new MediaSession.Builder(context, player).setSessionCallback(sessionCallback).build();
@ -120,7 +119,7 @@ public class MediaSessionKeyEventTest {
}
@After
public void cleanUp() throws Exception {
public void tearDown() throws Exception {
handler.postAndSync(
() -> {
if (mediaPlayer != null) {
@ -131,55 +130,46 @@ public class MediaSessionKeyEventTest {
session.release();
}
private void dispatchMediaKeyEvent(int keyCode, boolean doubleTap) {
audioManager.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
audioManager.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, keyCode));
if (doubleTap) {
audioManager.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
audioManager.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, keyCode));
}
}
@Test
public void playKeyEvent() throws Exception {
dispatchMediaKeyEvent(KeyEvent.KEYCODE_MEDIA_PLAY, false);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.playCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
}
@Test
public void pauseKeyEvent() throws Exception {
dispatchMediaKeyEvent(KeyEvent.KEYCODE_MEDIA_PAUSE, false);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.pauseCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_PAUSE, TIMEOUT_MS);
}
@Test
public void nextKeyEvent() throws Exception {
dispatchMediaKeyEvent(KeyEvent.KEYCODE_MEDIA_NEXT, false);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.seekToNextCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_NEXT, TIMEOUT_MS);
}
@Test
public void previousKeyEvent() throws Exception {
dispatchMediaKeyEvent(KeyEvent.KEYCODE_MEDIA_PREVIOUS, false);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.seekToPreviousCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_PREVIOUS, TIMEOUT_MS);
}
@Test
public void stopKeyEvent() throws Exception {
dispatchMediaKeyEvent(KeyEvent.KEYCODE_MEDIA_STOP, false);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.stopCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_STOP, TIMEOUT_MS);
}
@Test
public void playPauseKeyEvent_play() throws Exception {
dispatchMediaKeyEvent(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, false);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.playCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
}
@Test
@ -188,18 +178,28 @@ public class MediaSessionKeyEventTest {
() -> {
player.playWhenReady = true;
});
dispatchMediaKeyEvent(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, false);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.pauseCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_PAUSE, TIMEOUT_MS);
}
@Test
public void playPauseKeyEvent_doubleTapIsTranslatedToSkipToNext() throws Exception {
dispatchMediaKeyEvent(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, true);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.seekToNextCalled).isTrue();
assertThat(player.playCalled).isFalse();
assertThat(player.pauseCalled).isFalse();
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_NEXT, TIMEOUT_MS);
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PLAY)).isFalse();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PAUSE)).isFalse();
}
private void dispatchMediaKeyEvent(int keyCode, boolean doubleTap) {
audioManager.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
audioManager.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, keyCode));
if (doubleTap) {
audioManager.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
audioManager.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, keyCode));
}
}
private static class TestSessionCallback implements MediaSession.SessionCallback {

View File

@ -88,7 +88,7 @@ public class MediaSessionPermissionTest {
}
@After
public void cleanUp() {
public void tearDown() {
if (session != null) {
session.release();
session = null;
@ -97,55 +97,6 @@ public class MediaSessionPermissionTest {
callback = null;
}
private void createSessionWithAvailableCommands(
SessionCommands sessionCommands, Player.Commands playerCommands) {
player =
new MockPlayer.Builder()
.setLatchCount(1)
.setApplicationLooper(threadTestRule.getHandler().getLooper())
.build();
callback =
new MySessionCallback() {
@Override
public MediaSession.ConnectionResult onConnect(
MediaSession session, ControllerInfo controller) {
if (!TextUtils.equals(SUPPORT_APP_PACKAGE_NAME, controller.getPackageName())) {
return MediaSession.ConnectionResult.reject();
}
return MediaSession.ConnectionResult.accept(sessionCommands, playerCommands);
}
};
if (this.session != null) {
this.session.release();
}
this.session =
new MediaSession.Builder(context, player)
.setId(SESSION_ID)
.setSessionCallback(callback)
.build();
}
private SessionCommands createSessionCommandsWith(SessionCommand command) {
return new SessionCommands.Builder().add(command).build();
}
private void testOnCommandRequest(int commandCode, PermissionTestTask runnable) throws Exception {
createSessionWithAvailableCommands(
SessionCommands.EMPTY, createPlayerCommandsWith(commandCode));
runnable.run(controllerTestRule.createRemoteController(session.getToken()));
assertThat(callback.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(callback.onCommandRequestCalled).isTrue();
assertThat(callback.command).isEqualTo(commandCode);
createSessionWithAvailableCommands(
SessionCommands.EMPTY, createPlayerCommandsWithout(commandCode));
runnable.run(controllerTestRule.createRemoteController(session.getToken()));
assertThat(callback.countDownLatch.await(NO_RESPONSE_TIMEOUT_MS, MILLISECONDS)).isFalse();
assertThat(callback.onCommandRequestCalled).isFalse();
}
@Test
public void play() throws Exception {
testOnCommandRequest(COMMAND_PLAY_PAUSE, RemoteMediaController::play);
@ -409,4 +360,52 @@ public class MediaSessionPermissionTest {
return Futures.immediateFuture(new SessionResult(RESULT_SUCCESS));
}
}
private void createSessionWithAvailableCommands(
SessionCommands sessionCommands, Player.Commands playerCommands) {
player =
new MockPlayer.Builder()
.setApplicationLooper(threadTestRule.getHandler().getLooper())
.build();
callback =
new MySessionCallback() {
@Override
public MediaSession.ConnectionResult onConnect(
MediaSession session, ControllerInfo controller) {
if (!TextUtils.equals(SUPPORT_APP_PACKAGE_NAME, controller.getPackageName())) {
return MediaSession.ConnectionResult.reject();
}
return MediaSession.ConnectionResult.accept(sessionCommands, playerCommands);
}
};
if (this.session != null) {
this.session.release();
}
this.session =
new MediaSession.Builder(context, player)
.setId(SESSION_ID)
.setSessionCallback(callback)
.build();
}
private SessionCommands createSessionCommandsWith(SessionCommand command) {
return new SessionCommands.Builder().add(command).build();
}
private void testOnCommandRequest(int commandCode, PermissionTestTask runnable) throws Exception {
createSessionWithAvailableCommands(
SessionCommands.EMPTY, createPlayerCommandsWith(commandCode));
runnable.run(controllerTestRule.createRemoteController(session.getToken()));
assertThat(callback.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(callback.onCommandRequestCalled).isTrue();
assertThat(callback.command).isEqualTo(commandCode);
createSessionWithAvailableCommands(
SessionCommands.EMPTY, createPlayerCommandsWithout(commandCode));
runnable.run(controllerTestRule.createRemoteController(session.getToken()));
assertThat(callback.countDownLatch.await(NO_RESPONSE_TIMEOUT_MS, MILLISECONDS)).isFalse();
assertThat(callback.onCommandRequestCalled).isFalse();
}
}

View File

@ -16,10 +16,8 @@
package androidx.media3.session;
import static androidx.media3.test.session.common.CommonConstants.SUPPORT_APP_PACKAGE_NAME;
import static androidx.media3.test.session.common.TestUtils.LONG_TIMEOUT_MS;
import static androidx.media3.test.session.common.TestUtils.TIMEOUT_MS;
import static com.google.common.truth.Truth.assertThat;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import androidx.media3.common.DeviceInfo;
import androidx.media3.common.MediaItem;
@ -63,7 +61,6 @@ public class MediaSessionPlayerTest {
public void setUp() throws Exception {
player =
new MockPlayer.Builder()
.setLatchCount(1)
.setApplicationLooper(threadTestRule.getHandler().getLooper())
.setMediaItems(/* itemCount= */ 5)
.build();
@ -87,62 +84,64 @@ public class MediaSessionPlayerTest {
}
@After
public void cleanUp() {
if (session != null) {
public void tearDown() throws Exception {
controller.release();
session.release();
}
}
@Test
public void play() throws Exception {
controller.play();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.playCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_PLAY, TIMEOUT_MS);
}
@Test
public void pause() throws Exception {
controller.pause();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.pauseCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_PAUSE, TIMEOUT_MS);
}
@Test
public void prepare() throws Exception {
controller.prepare();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.prepareCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_PREPARE, TIMEOUT_MS);
}
@Test
public void stop() throws Exception {
controller.stop();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.stopCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_STOP, TIMEOUT_MS);
}
@Test
public void setPlayWhenReady() throws Exception {
boolean testPlayWhenReady = true;
controller.setPlayWhenReady(testPlayWhenReady);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.setPlayWhenReadyCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SET_PLAY_WHEN_READY, TIMEOUT_MS);
assertThat(player.playWhenReady).isEqualTo(testPlayWhenReady);
}
@Test
public void seekToDefaultPosition() throws Exception {
controller.seekToDefaultPosition();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.seekToDefaultPositionCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_DEFAULT_POSITION, TIMEOUT_MS);
}
@Test
public void seekToDefaultPosition_withMediaItemIndex() throws Exception {
int mediaItemIndex = 3;
controller.seekToDefaultPosition(mediaItemIndex);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.seekToDefaultPositionWithMediaItemIndexCalled).isTrue();
player.awaitMethodCalled(
MockPlayer.METHOD_SEEK_TO_DEFAULT_POSITION_WITH_MEDIA_ITEM_INDEX, TIMEOUT_MS);
assertThat(player.seekMediaItemIndex).isEqualTo(mediaItemIndex);
}
@ -150,8 +149,8 @@ public class MediaSessionPlayerTest {
public void seekTo() throws Exception {
long seekPositionMs = 12125L;
controller.seekTo(seekPositionMs);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.seekToCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO, TIMEOUT_MS);
assertThat(player.seekPositionMs).isEqualTo(seekPositionMs);
}
@ -159,9 +158,10 @@ public class MediaSessionPlayerTest {
public void seekTo_withMediaItemIndex() throws Exception {
int mediaItemIndex = 3;
long seekPositionMs = 12125L;
controller.seekTo(mediaItemIndex, seekPositionMs);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.seekToWithMediaItemIndexCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_WITH_MEDIA_ITEM_INDEX, TIMEOUT_MS);
assertThat(player.seekMediaItemIndex).isEqualTo(mediaItemIndex);
assertThat(player.seekPositionMs).isEqualTo(seekPositionMs);
}
@ -169,8 +169,10 @@ public class MediaSessionPlayerTest {
@Test
public void setPlaybackSpeed() throws Exception {
float testSpeed = 1.5f;
controller.setPlaybackSpeed(testSpeed);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SET_PLAYBACK_SPEED, TIMEOUT_MS);
assertThat(player.playbackParameters.speed).isEqualTo(testSpeed);
}
@ -178,9 +180,10 @@ public class MediaSessionPlayerTest {
public void setPlaybackParameters() throws Exception {
PlaybackParameters testPlaybackParameters =
new PlaybackParameters(/* speed= */ 1.4f, /* pitch= */ 2.3f);
controller.setPlaybackParameters(testPlaybackParameters);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.setPlaybackParametersCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SET_PLAYBACK_PARAMETERS, TIMEOUT_MS);
assertThat(player.playbackParameters).isEqualTo(testPlaybackParameters);
}
@ -194,8 +197,7 @@ public class MediaSessionPlayerTest {
controller.setMediaItem(item);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.setMediaItemCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEM, TIMEOUT_MS);
assertThat(player.mediaItem).isEqualTo(item);
assertThat(player.startPositionMs).isEqualTo(startPositionMs);
assertThat(player.resetPosition).isEqualTo(resetPosition);
@ -211,8 +213,7 @@ public class MediaSessionPlayerTest {
controller.setMediaItem(item);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.setMediaItemCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEM, TIMEOUT_MS);
assertThat(player.mediaItem).isEqualTo(item);
assertThat(player.startPositionMs).isEqualTo(startPositionMs);
assertThat(player.resetPosition).isEqualTo(resetPosition);
@ -228,8 +229,7 @@ public class MediaSessionPlayerTest {
controller.setMediaItem(item);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.setMediaItemCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEM, TIMEOUT_MS);
assertThat(player.mediaItem).isEqualTo(item);
assertThat(player.startPositionMs).isEqualTo(startPositionMs);
assertThat(player.resetPosition).isEqualTo(resetPosition);
@ -241,8 +241,7 @@ public class MediaSessionPlayerTest {
controller.setMediaItems(items);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.setMediaItemsCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS, TIMEOUT_MS);
assertThat(player.mediaItems).isEqualTo(items);
assertThat(player.resetPosition).isFalse();
}
@ -253,8 +252,7 @@ public class MediaSessionPlayerTest {
controller.setMediaItems(items, /* resetPosition= */ true);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.setMediaItemsWithResetPositionCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_RESET_POSITION, TIMEOUT_MS);
assertThat(player.mediaItems).isEqualTo(items);
assertThat(player.resetPosition).isTrue();
}
@ -267,8 +265,7 @@ public class MediaSessionPlayerTest {
controller.setMediaItems(items, startMediaItemIndex, startPositionMs);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.setMediaItemsWithStartIndexCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX, TIMEOUT_MS);
assertThat(player.mediaItems).isEqualTo(items);
assertThat(player.startMediaItemIndex).isEqualTo(startMediaItemIndex);
assertThat(player.startPositionMs).isEqualTo(startPositionMs);
@ -279,9 +276,10 @@ public class MediaSessionPlayerTest {
int listSize = 4;
List<MediaItem> list = MediaTestUtils.createMediaItems(listSize);
list.set(2, list.get(1));
controller.setMediaItems(list);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.setMediaItemsCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS, TIMEOUT_MS);
assertThat(player.mediaItems.size()).isEqualTo(listSize);
for (int i = 0; i < listSize; i++) {
assertThat(player.mediaItems.get(i).mediaId).isEqualTo(list.get(i).mediaId);
@ -293,9 +291,8 @@ public class MediaSessionPlayerTest {
int listSize = 5000;
// Make client app to generate a long list, and call setMediaItems() with it.
controller.createAndSetFakeMediaItems(listSize);
assertThat(player.countDownLatch.await(LONG_TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.setMediaItemsCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS, TIMEOUT_MS);
assertThat(player.mediaItems).isNotNull();
assertThat(player.mediaItems.size()).isEqualTo(listSize);
for (int i = 0; i < listSize; i++) {
@ -310,8 +307,7 @@ public class MediaSessionPlayerTest {
controller.setPlaylistMetadata(playlistMetadata);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.setPlaylistMetadataCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SET_PLAYLIST_METADATA, TIMEOUT_MS);
assertThat(player.playlistMetadata).isEqualTo(playlistMetadata);
}
@ -321,8 +317,7 @@ public class MediaSessionPlayerTest {
controller.addMediaItem(mediaItem);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.addMediaItemCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_ADD_MEDIA_ITEM, TIMEOUT_MS);
assertThat(player.mediaItem).isEqualTo(mediaItem);
}
@ -333,8 +328,7 @@ public class MediaSessionPlayerTest {
controller.addMediaItem(index, mediaItem);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.addMediaItemWithIndexCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_ADD_MEDIA_ITEM_WITH_INDEX, TIMEOUT_MS);
assertThat(player.index).isEqualTo(index);
assertThat(player.mediaItem).isEqualTo(mediaItem);
}
@ -346,8 +340,7 @@ public class MediaSessionPlayerTest {
controller.addMediaItems(mediaItems);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.addMediaItemsCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_ADD_MEDIA_ITEMS, TIMEOUT_MS);
assertThat(player.mediaItems).isEqualTo(mediaItems);
}
@ -359,8 +352,7 @@ public class MediaSessionPlayerTest {
controller.addMediaItems(index, mediaItems);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.addMediaItemsWithIndexCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_ADD_MEDIA_ITEMS_WITH_INDEX, TIMEOUT_MS);
assertThat(player.index).isEqualTo(index);
assertThat(player.mediaItems).isEqualTo(mediaItems);
}
@ -371,8 +363,7 @@ public class MediaSessionPlayerTest {
controller.removeMediaItem(index);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.removeMediaItemCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_REMOVE_MEDIA_ITEM, TIMEOUT_MS);
assertThat(player.index).isEqualTo(index);
}
@ -383,8 +374,7 @@ public class MediaSessionPlayerTest {
controller.removeMediaItems(fromIndex, toIndex);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.removeMediaItemsCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_REMOVE_MEDIA_ITEMS, TIMEOUT_MS);
assertThat(player.fromIndex).isEqualTo(fromIndex);
assertThat(player.toIndex).isEqualTo(toIndex);
}
@ -393,8 +383,7 @@ public class MediaSessionPlayerTest {
public void clearMediaItems() throws Exception {
controller.clearMediaItems();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.clearMediaItemsCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_CLEAR_MEDIA_ITEMS, TIMEOUT_MS);
}
@Test
@ -404,8 +393,7 @@ public class MediaSessionPlayerTest {
controller.moveMediaItem(index, newIndex);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.moveMediaItemCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_MOVE_MEDIA_ITEM, TIMEOUT_MS);
assertThat(player.index).isEqualTo(index);
assertThat(player.newIndex).isEqualTo(newIndex);
}
@ -418,8 +406,7 @@ public class MediaSessionPlayerTest {
controller.moveMediaItems(fromIndex, toIndex, newIndex);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.moveMediaItemsCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_MOVE_MEDIA_ITEMS, TIMEOUT_MS);
assertThat(player.fromIndex).isEqualTo(fromIndex);
assertThat(player.toIndex).isEqualTo(toIndex);
assertThat(player.newIndex).isEqualTo(newIndex);
@ -428,68 +415,69 @@ public class MediaSessionPlayerTest {
@Test
public void seekToPreviousMediaItem() throws Exception {
controller.seekToPreviousMediaItem();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.seekToPreviousMediaItemCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_PREVIOUS_MEDIA_ITEM, TIMEOUT_MS);
}
@Test
public void seekToNextMediaItem() throws Exception {
controller.seekToNextMediaItem();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.seekToNextMediaItemCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_NEXT_MEDIA_ITEM, TIMEOUT_MS);
}
@Test
public void seekToPrevious() throws Exception {
controller.seekToPrevious();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.seekToPreviousCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_PREVIOUS, TIMEOUT_MS);
}
@Test
public void seekToNext() throws Exception {
controller.seekToNext();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.seekToNextCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO_NEXT, TIMEOUT_MS);
}
@Test
public void setShuffleModeEnabled() throws Exception {
boolean testShuffleModeEnabled = true;
controller.setShuffleModeEnabled(testShuffleModeEnabled);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.setShuffleModeCalled).isTrue();
controller.setShuffleModeEnabled(testShuffleModeEnabled);
player.awaitMethodCalled(MockPlayer.METHOD_SET_SHUFFLE_MODE, TIMEOUT_MS);
assertThat(player.shuffleModeEnabled).isEqualTo(testShuffleModeEnabled);
}
@Test
public void setRepeatMode() throws Exception {
int testRepeatMode = Player.REPEAT_MODE_ALL;
controller.setRepeatMode(testRepeatMode);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.setRepeatModeCalled).isTrue();
controller.setRepeatMode(testRepeatMode);
player.awaitMethodCalled(MockPlayer.METHOD_SET_REPEAT_MODE, TIMEOUT_MS);
assertThat(player.repeatMode).isEqualTo(testRepeatMode);
}
@Test
public void setVolume() throws Exception {
float testVolume = .123f;
controller.setVolume(testVolume);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.setVolumeCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SET_VOLUME, TIMEOUT_MS);
assertThat(player.volume).isEqualTo(testVolume);
}
@Test
public void setDeviceVolume() throws Exception {
changePlaybackTypeToRemote();
int testVolume = 12;
controller.setDeviceVolume(testVolume);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.setDeviceVolumeCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SET_DEVICE_VOLUME, TIMEOUT_MS);
assertThat(player.deviceVolume).isEqualTo(testVolume);
}
@ -499,8 +487,7 @@ public class MediaSessionPlayerTest {
controller.increaseDeviceVolume();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.increaseDeviceVolumeCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_INCREASE_DEVICE_VOLUME, TIMEOUT_MS);
}
@Test
@ -509,16 +496,16 @@ public class MediaSessionPlayerTest {
controller.decreaseDeviceVolume();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.decreaseDeviceVolumeCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_DECREASE_DEVICE_VOLUME, TIMEOUT_MS);
}
@Test
public void setDeviceMuted() throws Exception {
player.deviceMuted = false;
controller.setDeviceMuted(true);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.setDeviceMutedCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SET_DEVICE_MUTED, TIMEOUT_MS);
assertThat(player.deviceMuted).isTrue();
}
@ -526,16 +513,14 @@ public class MediaSessionPlayerTest {
public void seekBack() throws Exception {
controller.seekBack();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.seekBackCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_BACK, TIMEOUT_MS);
}
@Test
public void seekForward() throws Exception {
controller.seekForward();
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.seekForwardCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_FORWARD, TIMEOUT_MS);
}
@Test
@ -545,8 +530,7 @@ public class MediaSessionPlayerTest {
controller.setTrackSelectionParameters(trackSelectionParameters);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.setTrackSelectionParametersCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SET_TRACK_SELECTION_PARAMETERS, TIMEOUT_MS);
assertThat(player.trackSelectionParameters).isEqualTo(trackSelectionParameters);
}

View File

@ -47,6 +47,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
@ -78,8 +79,7 @@ public class MediaSessionTest {
public void setUp() throws Exception {
context = ApplicationProvider.getApplicationContext();
handler = threadTestRule.getHandler();
player =
new MockPlayer.Builder().setLatchCount(1).setApplicationLooper(handler.getLooper()).build();
player = new MockPlayer.Builder().setApplicationLooper(handler.getLooper()).build();
session =
sessionTestRule.ensureReleaseAfterTest(
@ -107,6 +107,16 @@ public class MediaSessionTest {
.get(TIMEOUT_MS, MILLISECONDS);
}
@After
public void tearDown() throws Exception {
if ((controller != null)) {
threadTestRule.getHandler().postAndSync(() -> controller.release());
}
if (session != null) {
session.release();
}
}
@Test
public void builder() {
MediaSession.Builder builder;
@ -394,8 +404,7 @@ public class MediaSessionTest {
long testSeekPositionMs = 1234;
controllerCompat.getTransportControls().seekTo(testSeekPositionMs);
assertThat(player.countDownLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
assertThat(player.seekToCalled).isTrue();
player.awaitMethodCalled(MockPlayer.METHOD_SEEK_TO, TIMEOUT_MS);
assertThat(player.seekPositionMs).isEqualTo(testSeekPositionMs);
}

View File

@ -44,81 +44,98 @@ public class MockPlayerTest {
@Test
public void play() {
player.play();
assertThat(player.playCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PLAY)).isTrue();
}
@Test
public void pause() {
player.pause();
assertThat(player.pauseCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PAUSE)).isTrue();
}
@Test
public void prepare() {
player.prepare();
assertThat(player.prepareCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_PREPARE)).isTrue();
}
@Test
public void stop() {
player.stop();
assertThat(player.stopCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_STOP)).isTrue();
}
@Test
public void release() {
player.release();
assertThat(player.releaseCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_RELEASE)).isTrue();
}
@Test
public void setPlayWhenReady() {
boolean testPlayWhenReady = false;
player.setPlayWhenReady(testPlayWhenReady);
assertThat(player.setPlayWhenReadyCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_PLAY_WHEN_READY)).isTrue();
}
@Test
public void seekTo() {
long pos = 1004L;
player.seekTo(pos);
assertThat(player.seekToCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SEEK_TO)).isTrue();
assertThat(player.seekPositionMs).isEqualTo(pos);
}
@Test
public void seekBack() {
player.seekBack();
assertThat(player.seekBackCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SEEK_BACK)).isTrue();
}
@Test
public void seekForward() {
player.seekForward();
assertThat(player.seekForwardCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SEEK_FORWARD)).isTrue();
}
@Test
public void setPlaybackParameters() {
PlaybackParameters playbackParameters = new PlaybackParameters(/* speed= */ 1.5f);
player.setPlaybackParameters(playbackParameters);
assertThat(player.setPlaybackParametersCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_PLAYBACK_PARAMETERS)).isTrue();
assertThat(player.playbackParameters).isEqualTo(playbackParameters);
}
@Test
public void setPlaybackSpeed() {
float speed = 1.5f;
player.setPlaybackSpeed(speed);
assertThat(player.setPlaybackSpeedCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_PLAYBACK_SPEED)).isTrue();
assertThat(player.playbackParameters.speed).isEqualTo(speed);
}
@Test
public void setMediaItem() {
MediaItem mediaItem = MediaTestUtils.createMediaItem("setMediaItem");
player.setMediaItem(mediaItem);
assertThat(player.setMediaItemCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEM)).isTrue();
assertThat(player.mediaItem).isSameInstanceAs(mediaItem);
}
@ -126,8 +143,11 @@ public class MockPlayerTest {
public void setMediaItem_withStartPosition() {
MediaItem mediaItem = MediaTestUtils.createMediaItem("setMediaItem");
long startPositionMs = 321L;
player.setMediaItem(mediaItem, startPositionMs);
assertThat(player.setMediaItemWithStartPositionCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEM_WITH_START_POSITION))
.isTrue();
assertThat(player.startPositionMs).isEqualTo(startPositionMs);
assertThat(player.mediaItem).isSameInstanceAs(mediaItem);
}
@ -136,8 +156,11 @@ public class MockPlayerTest {
public void setMediaItem_withResetPosition() {
MediaItem mediaItem = MediaTestUtils.createMediaItem("setMediaItem");
boolean resetPosition = true;
player.setMediaItem(mediaItem, resetPosition);
assertThat(player.setMediaItemWithResetPositionCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEM_WITH_RESET_POSITION))
.isTrue();
assertThat(player.resetPosition).isEqualTo(resetPosition);
assertThat(player.mediaItem).isEqualTo(mediaItem);
}
@ -145,8 +168,10 @@ public class MockPlayerTest {
@Test
public void setMediaItems() {
List<MediaItem> list = MediaTestUtils.createMediaItems(/* size= */ 2);
player.setMediaItems(list);
assertThat(player.setMediaItemsCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS)).isTrue();
assertThat(player.mediaItems).isSameInstanceAs(list);
}
@ -154,8 +179,11 @@ public class MockPlayerTest {
public void setMediaItems_withResetPosition() {
List<MediaItem> list = MediaTestUtils.createMediaItems(/* size= */ 2);
boolean resetPosition = true;
player.setMediaItems(list, resetPosition);
assertThat(player.setMediaItemsWithResetPositionCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_RESET_POSITION))
.isTrue();
assertThat(player.resetPosition).isEqualTo(resetPosition);
assertThat(player.mediaItems).isSameInstanceAs(list);
}
@ -165,8 +193,11 @@ public class MockPlayerTest {
List<MediaItem> list = MediaTestUtils.createMediaItems(/* size= */ 2);
int startWindowIndex = 3;
long startPositionMs = 132L;
player.setMediaItems(list, startWindowIndex, startPositionMs);
assertThat(player.setMediaItemsWithStartIndexCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX))
.isTrue();
assertThat(player.startMediaItemIndex).isEqualTo(startWindowIndex);
assertThat(player.startPositionMs).isEqualTo(startPositionMs);
assertThat(player.mediaItems).isSameInstanceAs(list);
@ -176,8 +207,10 @@ public class MockPlayerTest {
public void setMediaItems_withDuplicatedItems() {
List<MediaItem> list = MediaTestUtils.createMediaItems(/* size= */ 4);
list.set(2, list.get(1));
player.setMediaItems(list);
assertThat(player.setMediaItemsCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_MEDIA_ITEMS)).isTrue();
assertThat(player.mediaItems).isSameInstanceAs(list);
}
@ -187,7 +220,7 @@ public class MockPlayerTest {
player.setPlaylistMetadata(playlistMetadata);
assertThat(player.setPlaylistMetadataCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_PLAYLIST_METADATA)).isTrue();
assertThat(player.playlistMetadata).isSameInstanceAs(playlistMetadata);
}
@ -197,7 +230,7 @@ public class MockPlayerTest {
player.addMediaItem(mediaItem);
assertThat(player.addMediaItemCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_ADD_MEDIA_ITEM)).isTrue();
assertThat(player.mediaItem).isSameInstanceAs(mediaItem);
}
@ -208,7 +241,7 @@ public class MockPlayerTest {
player.addMediaItem(index, mediaItem);
assertThat(player.addMediaItemWithIndexCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_ADD_MEDIA_ITEM_WITH_INDEX)).isTrue();
assertThat(player.index).isEqualTo(index);
assertThat(player.mediaItem).isSameInstanceAs(mediaItem);
}
@ -221,7 +254,7 @@ public class MockPlayerTest {
player.addMediaItems(index, mediaItems);
assertThat(player.addMediaItemsWithIndexCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_ADD_MEDIA_ITEMS_WITH_INDEX)).isTrue();
assertThat(player.index).isEqualTo(index);
assertThat(player.mediaItems).isSameInstanceAs(mediaItems);
}
@ -234,7 +267,7 @@ public class MockPlayerTest {
player.addMediaItems(index, mediaItems);
assertThat(player.addMediaItemsWithIndexCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_ADD_MEDIA_ITEMS_WITH_INDEX)).isTrue();
assertThat(player.index).isEqualTo(index);
assertThat(player.mediaItems).isSameInstanceAs(mediaItems);
}
@ -245,7 +278,7 @@ public class MockPlayerTest {
player.removeMediaItem(index);
assertThat(player.removeMediaItemCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_REMOVE_MEDIA_ITEM)).isTrue();
assertThat(player.index).isEqualTo(index);
}
@ -256,7 +289,7 @@ public class MockPlayerTest {
player.removeMediaItems(fromIndex, toIndex);
assertThat(player.removeMediaItemsCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_REMOVE_MEDIA_ITEMS)).isTrue();
assertThat(player.fromIndex).isEqualTo(fromIndex);
assertThat(player.toIndex).isEqualTo(toIndex);
}
@ -265,7 +298,7 @@ public class MockPlayerTest {
public void clearMediaItems() {
player.clearMediaItems();
assertThat(player.clearMediaItemsCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_CLEAR_MEDIA_ITEMS)).isTrue();
}
@Test
@ -275,7 +308,7 @@ public class MockPlayerTest {
player.moveMediaItem(index, newIndex);
assertThat(player.moveMediaItemCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_MOVE_MEDIA_ITEM)).isTrue();
assertThat(player.index).isEqualTo(index);
assertThat(player.newIndex).isEqualTo(newIndex);
}
@ -288,7 +321,7 @@ public class MockPlayerTest {
player.moveMediaItems(fromIndex, toIndex, newIndex);
assertThat(player.moveMediaItemsCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_MOVE_MEDIA_ITEMS)).isTrue();
assertThat(player.fromIndex).isEqualTo(fromIndex);
assertThat(player.toIndex).isEqualTo(toIndex);
assertThat(player.newIndex).isEqualTo(newIndex);
@ -297,76 +330,92 @@ public class MockPlayerTest {
@Test
public void seekToPreviousMediaItem() {
player.seekToPreviousMediaItem();
assertThat(player.seekToPreviousMediaItemCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SEEK_TO_PREVIOUS_MEDIA_ITEM)).isTrue();
}
@Test
public void seekToNextMediaItem() {
player.seekToNextMediaItem();
assertThat(player.seekToNextMediaItemCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SEEK_TO_NEXT_MEDIA_ITEM)).isTrue();
}
@Test
public void seekToPrevious() {
player.seekToPrevious();
assertThat(player.seekToPreviousCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SEEK_TO_PREVIOUS)).isTrue();
}
@Test
public void seekToNext() {
player.seekToNext();
assertThat(player.seekToNextCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SEEK_TO_NEXT)).isTrue();
}
@Test
public void setShuffleModeEnabled() {
boolean testShuffleModeEnabled = true;
player.setShuffleModeEnabled(testShuffleModeEnabled);
assertThat(player.setShuffleModeCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_SHUFFLE_MODE)).isTrue();
assertThat(player.shuffleModeEnabled).isEqualTo(testShuffleModeEnabled);
}
@Test
public void setRepeatMode() {
int testRepeatMode = Player.REPEAT_MODE_ALL;
player.setRepeatMode(testRepeatMode);
assertThat(player.setRepeatModeCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_REPEAT_MODE)).isTrue();
assertThat(player.repeatMode).isEqualTo(testRepeatMode);
}
@Test
public void setVolume() {
float testVolume = .123f;
player.setVolume(testVolume);
assertThat(player.setVolumeCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_VOLUME)).isTrue();
assertThat(player.volume).isEqualTo(testVolume);
}
@Test
public void setDeviceVolume() {
int testVolume = 12;
player.setDeviceVolume(testVolume);
assertThat(player.setDeviceVolumeCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_DEVICE_VOLUME)).isTrue();
assertThat(player.deviceVolume).isEqualTo(testVolume);
}
@Test
public void increaseDeviceVolume() {
player.increaseDeviceVolume();
assertThat(player.increaseDeviceVolumeCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_INCREASE_DEVICE_VOLUME)).isTrue();
}
@Test
public void decreaseDeviceVolume() {
player.decreaseDeviceVolume();
assertThat(player.decreaseDeviceVolumeCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_DECREASE_DEVICE_VOLUME)).isTrue();
}
@Test
public void setDeviceMuted() {
player.deviceMuted = false;
player.setDeviceMuted(true);
assertThat(player.setDeviceMutedCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_DEVICE_MUTED)).isTrue();
assertThat(player.deviceMuted).isTrue();
}
@ -377,7 +426,8 @@ public class MockPlayerTest {
player.setTrackSelectionParameters(trackSelectionParameters);
assertThat(player.setTrackSelectionParametersCalled).isTrue();
assertThat(player.hasMethodBeenCalled(MockPlayer.METHOD_SET_TRACK_SELECTION_PARAMETERS))
.isTrue();
assertThat(player.trackSelectionParameters).isSameInstanceAs(trackSelectionParameters);
}
}

View File

@ -134,8 +134,7 @@ public class MockMediaLibraryService extends MediaLibraryService {
return (MediaLibrarySession) onGetSessionHandler.onGetSession(controllerInfo);
}
MockPlayer player =
new MockPlayer.Builder().setLatchCount(1).setApplicationLooper(handler.getLooper()).build();
MockPlayer player = new MockPlayer.Builder().setApplicationLooper(handler.getLooper()).build();
MediaLibrarySessionCallback callback = registry.getSessionCallback();
session =

View File

@ -15,11 +15,15 @@
*/
package androidx.media3.session;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.os.Looper;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import androidx.collection.ArraySet;
import androidx.media3.common.AudioAttributes;
@ -37,20 +41,162 @@ import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.TracksInfo;
import androidx.media3.common.VideoSize;
import androidx.media3.common.text.Cue;
import androidx.media3.common.util.ConditionVariable;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeoutException;
/** A mock implementation of {@link Player} for testing. */
@UnstableApi
public class MockPlayer implements Player {
public final CountDownLatch countDownLatch;
/** Player methods. */
@Documented
@Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({
METHOD_ADD_MEDIA_ITEM,
METHOD_ADD_MEDIA_ITEMS,
METHOD_ADD_MEDIA_ITEM_WITH_INDEX,
METHOD_ADD_MEDIA_ITEMS_WITH_INDEX,
METHOD_CLEAR_MEDIA_ITEMS,
METHOD_DECREASE_DEVICE_VOLUME,
METHOD_INCREASE_DEVICE_VOLUME,
METHOD_MOVE_MEDIA_ITEM,
METHOD_MOVE_MEDIA_ITEMS,
METHOD_PAUSE,
METHOD_PLAY,
METHOD_PREPARE,
METHOD_RELEASE,
METHOD_REMOVE_MEDIA_ITEM,
METHOD_REMOVE_MEDIA_ITEMS,
METHOD_SEEK_BACK,
METHOD_SEEK_FORWARD,
METHOD_SEEK_TO,
METHOD_SEEK_TO_DEFAULT_POSITION,
METHOD_SEEK_TO_DEFAULT_POSITION_WITH_MEDIA_ITEM_INDEX,
METHOD_SEEK_TO_NEXT,
METHOD_SEEK_TO_NEXT_MEDIA_ITEM,
METHOD_SEEK_TO_PREVIOUS,
METHOD_SEEK_TO_PREVIOUS_MEDIA_ITEM,
METHOD_SEEK_TO_WITH_MEDIA_ITEM_INDEX,
METHOD_SET_DEVICE_MUTED,
METHOD_SET_DEVICE_VOLUME,
METHOD_SET_MEDIA_ITEM,
METHOD_SET_MEDIA_ITEM_WITH_RESET_POSITION,
METHOD_SET_MEDIA_ITEM_WITH_START_POSITION,
METHOD_SET_MEDIA_ITEMS,
METHOD_SET_MEDIA_ITEMS_WITH_RESET_POSITION,
METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX,
METHOD_SET_PLAY_WHEN_READY,
METHOD_SET_PLAYBACK_PARAMETERS,
METHOD_SET_PLAYBACK_SPEED,
METHOD_SET_PLAYLIST_METADATA,
METHOD_SET_REPEAT_MODE,
METHOD_SET_SHUFFLE_MODE,
METHOD_SET_TRACK_SELECTION_PARAMETERS,
METHOD_SET_VOLUME,
METHOD_STOP
})
public @interface Method {}
/** Maps to {@link Player#addMediaItem(MediaItem)}. */
public static final int METHOD_ADD_MEDIA_ITEM = 0;
/** Maps to {@link Player#addMediaItems(List)}. */
public static final int METHOD_ADD_MEDIA_ITEMS = 1;
/** Maps to {@link Player#addMediaItem(int, MediaItem)}. */
public static final int METHOD_ADD_MEDIA_ITEM_WITH_INDEX = 2;
/** Maps to {@link Player#addMediaItems(int, List)}. */
public static final int METHOD_ADD_MEDIA_ITEMS_WITH_INDEX = 3;
/** Maps to {@link Player#clearMediaItems()}. */
public static final int METHOD_CLEAR_MEDIA_ITEMS = 4;
/** Maps to {@link Player#decreaseDeviceVolume()}. */
public static final int METHOD_DECREASE_DEVICE_VOLUME = 5;
/** Maps to {@link Player#increaseDeviceVolume()}. */
public static final int METHOD_INCREASE_DEVICE_VOLUME = 6;
/** Maps to {@link Player#moveMediaItem(int, int)}. */
public static final int METHOD_MOVE_MEDIA_ITEM = 7;
/** Maps to {@link Player#moveMediaItems(int, int, int)}. */
public static final int METHOD_MOVE_MEDIA_ITEMS = 8;
/** Maps to {@link Player#pause()}. */
public static final int METHOD_PAUSE = 9;
/** Maps to {@link Player#play()}. */
public static final int METHOD_PLAY = 10;
/** Maps to {@link Player#prepare()}. */
public static final int METHOD_PREPARE = 11;
/** Maps to {@link Player#release()}. */
public static final int METHOD_RELEASE = 12;
/** Maps to {@link Player#removeMediaItem(int)}. */
public static final int METHOD_REMOVE_MEDIA_ITEM = 13;
/** Maps to {@link Player#removeMediaItems(int, int)}. */
public static final int METHOD_REMOVE_MEDIA_ITEMS = 14;
/** Maps to {@link Player#seekBack()}. */
public static final int METHOD_SEEK_BACK = 15;
/** Maps to {@link Player#seekForward()}. */
public static final int METHOD_SEEK_FORWARD = 16;
/** Maps to {@link Player#seekTo(long)}. */
public static final int METHOD_SEEK_TO = 17;
/** Maps to {@link Player#seekToDefaultPosition()}. */
public static final int METHOD_SEEK_TO_DEFAULT_POSITION = 18;
/** Maps to {@link Player#seekToDefaultPosition(int)}. */
public static final int METHOD_SEEK_TO_DEFAULT_POSITION_WITH_MEDIA_ITEM_INDEX = 19;
/** Maps to {@link Player#seekToNext()}. */
public static final int METHOD_SEEK_TO_NEXT = 20;
/** Maps to {@link Player#seekToNextMediaItem()}. */
public static final int METHOD_SEEK_TO_NEXT_MEDIA_ITEM = 21;
/** Maps to {@link Player#seekToPrevious()}. */
public static final int METHOD_SEEK_TO_PREVIOUS = 22;
/** Maps to {@link Player#seekToPreviousMediaItem()}. */
public static final int METHOD_SEEK_TO_PREVIOUS_MEDIA_ITEM = 23;
/** Maps to {@link Player#seekTo(int, long)}. */
public static final int METHOD_SEEK_TO_WITH_MEDIA_ITEM_INDEX = 24;
/** Maps to {@link Player#setDeviceMuted(boolean)}. */
public static final int METHOD_SET_DEVICE_MUTED = 25;
/** Maps to {@link Player#setDeviceVolume(int)}. */
public static final int METHOD_SET_DEVICE_VOLUME = 26;
/** Maps to {@link Player#setMediaItem(MediaItem)}. */
public static final int METHOD_SET_MEDIA_ITEM = 27;
/** Maps to {@link Player#setMediaItem(MediaItem, boolean)}. */
public static final int METHOD_SET_MEDIA_ITEM_WITH_RESET_POSITION = 28;
/** Maps to {@link Player#setMediaItem(MediaItem, long)}. */
public static final int METHOD_SET_MEDIA_ITEM_WITH_START_POSITION = 29;
/** Maps to {@link Player#setMediaItems(List)}. */
public static final int METHOD_SET_MEDIA_ITEMS = 30;
/** Maps to {@link Player#setMediaItems(List, boolean)}. */
public static final int METHOD_SET_MEDIA_ITEMS_WITH_RESET_POSITION = 31;
/** Maps to {@link Player#setMediaItems(List, int, long)}. */
public static final int METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX = 32;
/** Maps to {@link Player#setPlayWhenReady(boolean)}. */
public static final int METHOD_SET_PLAY_WHEN_READY = 33;
/** Maps to {@link Player#setPlaybackParameters(PlaybackParameters)}. */
public static final int METHOD_SET_PLAYBACK_PARAMETERS = 34;
/** Maps to {@link Player#setPlaybackSpeed(float)}. */
public static final int METHOD_SET_PLAYBACK_SPEED = 35;
/** Maps to {@link Player#setPlaylistMetadata(MediaMetadata)}. */
public static final int METHOD_SET_PLAYLIST_METADATA = 36;
/** Maps to {@link Player#setRepeatMode(int)}. */
public static final int METHOD_SET_REPEAT_MODE = 37;
/** Maps to {@link Player#setShuffleModeEnabled(boolean)}. */
public static final int METHOD_SET_SHUFFLE_MODE = 38;
/** Maps to {@link Player#setTrackSelectionParameters(TrackSelectionParameters)}. */
public static final int METHOD_SET_TRACK_SELECTION_PARAMETERS = 39;
/** Maps to {@link Player#setVolume(float)}. */
public static final int METHOD_SET_VOLUME = 40;
/** Maps to {@link Player#stop()}. */
public static final int METHOD_STOP = 41;
private final boolean changePlayerStateWithTransportControl;
private final Looper applicationLooper;
private final ArraySet<Listener> listeners = new ArraySet<>();
private final ImmutableMap<@Method Integer, ConditionVariable> conditionVariables =
createMethodConditionVariables();
@Nullable PlaybackException playerError;
public AudioAttributes audioAttributes;
@ -106,51 +252,7 @@ public class MockPlayer implements Player {
public long maxSeekToPreviousPositionMs;
public TrackSelectionParameters trackSelectionParameters;
public boolean playCalled;
public boolean pauseCalled;
public boolean prepareCalled;
public boolean stopCalled;
public boolean releaseCalled;
public boolean seekToDefaultPositionCalled;
public boolean seekToDefaultPositionWithMediaItemIndexCalled;
public boolean seekToCalled;
public boolean seekToWithMediaItemIndexCalled;
public boolean setPlaybackSpeedCalled;
public boolean setPlaybackParametersCalled;
public boolean setMediaItemCalled;
public boolean setMediaItemWithStartPositionCalled;
public boolean setMediaItemWithResetPositionCalled;
public boolean setMediaItemsCalled;
public boolean setMediaItemsWithResetPositionCalled;
public boolean setMediaItemsWithStartIndexCalled;
public boolean setPlaylistMetadataCalled;
public boolean addMediaItemCalled;
public boolean addMediaItemWithIndexCalled;
public boolean addMediaItemsCalled;
public boolean addMediaItemsWithIndexCalled;
public boolean removeMediaItemCalled;
public boolean removeMediaItemsCalled;
public boolean clearMediaItemsCalled;
public boolean moveMediaItemCalled;
public boolean moveMediaItemsCalled;
public boolean seekToPreviousMediaItemCalled;
public boolean seekToNextMediaItemCalled;
public boolean seekToPreviousCalled;
public boolean seekToNextCalled;
public boolean setRepeatModeCalled;
public boolean setShuffleModeCalled;
public boolean setVolumeCalled;
public boolean setDeviceVolumeCalled;
public boolean increaseDeviceVolumeCalled;
public boolean decreaseDeviceVolumeCalled;
public boolean setDeviceMutedCalled;
public boolean setPlayWhenReadyCalled;
public boolean seekBackCalled;
public boolean seekForwardCalled;
public boolean setTrackSelectionParametersCalled;
private MockPlayer(Builder builder) {
countDownLatch = new CountDownLatch(builder.latchCount);
changePlayerStateWithTransportControl = builder.changePlayerStateWithTransportControl;
applicationLooper = builder.applicationLooper;
@ -203,13 +305,12 @@ public class MockPlayer implements Player {
@Override
public void release() {
releaseCalled = true;
checkNotNull(conditionVariables.get(METHOD_RELEASE)).open();
}
@Override
public void stop() {
stopCalled = true;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_STOP)).open();
}
@Deprecated
@ -236,8 +337,7 @@ public class MockPlayer implements Player {
@Override
public void play() {
playCalled = true;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_PLAY)).open();
if (changePlayerStateWithTransportControl) {
notifyPlayWhenReadyChanged(
/* playWhenReady= */ true, Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST);
@ -246,8 +346,7 @@ public class MockPlayer implements Player {
@Override
public void pause() {
pauseCalled = true;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_PAUSE)).open();
if (changePlayerStateWithTransportControl) {
notifyPlayWhenReadyChanged(
/* playWhenReady= */ false, Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST);
@ -256,8 +355,7 @@ public class MockPlayer implements Player {
@Override
public void prepare() {
prepareCalled = true;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_PREPARE)).open();
if (changePlayerStateWithTransportControl) {
notifyPlaybackStateChanged(Player.STATE_READY);
}
@ -265,30 +363,27 @@ public class MockPlayer implements Player {
@Override
public void seekToDefaultPosition() {
seekToDefaultPositionCalled = true;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_SEEK_TO_DEFAULT_POSITION)).open();
}
@Override
public void seekToDefaultPosition(int mediaItemIndex) {
seekToDefaultPositionWithMediaItemIndexCalled = true;
seekMediaItemIndex = mediaItemIndex;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_SEEK_TO_DEFAULT_POSITION_WITH_MEDIA_ITEM_INDEX))
.open();
}
@Override
public void seekTo(long positionMs) {
seekToCalled = true;
seekPositionMs = positionMs;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_SEEK_TO)).open();
}
@Override
public void seekTo(int mediaItemIndex, long positionMs) {
seekToWithMediaItemIndexCalled = true;
seekMediaItemIndex = mediaItemIndex;
seekPositionMs = positionMs;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_SEEK_TO_WITH_MEDIA_ITEM_INDEX)).open();
}
@Override
@ -298,8 +393,7 @@ public class MockPlayer implements Player {
@Override
public void seekBack() {
seekBackCalled = true;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_SEEK_BACK)).open();
}
@Override
@ -309,8 +403,7 @@ public class MockPlayer implements Player {
@Override
public void seekForward() {
seekForwardCalled = true;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_SEEK_FORWARD)).open();
}
@Override
@ -508,16 +601,14 @@ public class MockPlayer implements Player {
@Override
public void setPlaybackParameters(PlaybackParameters playbackParameters) {
setPlaybackParametersCalled = true;
this.playbackParameters = playbackParameters;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_SET_PLAYBACK_PARAMETERS)).open();
}
@Override
public void setPlaybackSpeed(float speed) {
setPlaybackSpeedCalled = true;
playbackParameters = new PlaybackParameters(speed);
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_SET_PLAYBACK_SPEED)).open();
}
@Override
@ -527,9 +618,8 @@ public class MockPlayer implements Player {
@Override
public void setVolume(float volume) {
setVolumeCalled = true;
this.volume = volume;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_SET_VOLUME)).open();
}
@Override
@ -554,35 +644,30 @@ public class MockPlayer implements Player {
@Override
public void setDeviceVolume(int volume) {
setDeviceVolumeCalled = true;
deviceVolume = volume;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_SET_DEVICE_VOLUME)).open();
}
@Override
public void increaseDeviceVolume() {
increaseDeviceVolumeCalled = true;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_INCREASE_DEVICE_VOLUME)).open();
}
@Override
public void decreaseDeviceVolume() {
decreaseDeviceVolumeCalled = true;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_DECREASE_DEVICE_VOLUME)).open();
}
@Override
public void setDeviceMuted(boolean muted) {
setDeviceMutedCalled = true;
deviceMuted = muted;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_SET_DEVICE_MUTED)).open();
}
@Override
public void setPlayWhenReady(boolean playWhenReady) {
this.setPlayWhenReadyCalled = true;
this.playWhenReady = playWhenReady;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_SET_PLAY_WHEN_READY)).open();
}
@Override
@ -626,49 +711,43 @@ public class MockPlayer implements Player {
@Override
public void setMediaItem(MediaItem mediaItem) {
setMediaItemCalled = true;
this.mediaItem = mediaItem;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_SET_MEDIA_ITEM)).open();
}
@Override
public void setMediaItem(MediaItem mediaItem, long startPositionMs) {
setMediaItemWithStartPositionCalled = true;
this.mediaItem = mediaItem;
this.startPositionMs = startPositionMs;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_SET_MEDIA_ITEM_WITH_START_POSITION)).open();
}
@Override
public void setMediaItem(MediaItem mediaItem, boolean resetPosition) {
setMediaItemWithResetPositionCalled = true;
this.mediaItem = mediaItem;
this.resetPosition = resetPosition;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_SET_MEDIA_ITEM_WITH_RESET_POSITION)).open();
}
@Override
public void setMediaItems(List<MediaItem> mediaItems) {
setMediaItemsCalled = true;
this.mediaItems = mediaItems;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_SET_MEDIA_ITEMS)).open();
}
@Override
public void setMediaItems(List<MediaItem> mediaItems, boolean resetPosition) {
setMediaItemsWithResetPositionCalled = true;
this.mediaItems = mediaItems;
this.resetPosition = resetPosition;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_SET_MEDIA_ITEMS_WITH_RESET_POSITION)).open();
}
@Override
public void setMediaItems(List<MediaItem> mediaItems, int startIndex, long startPositionMs) {
setMediaItemsWithStartIndexCalled = true;
this.mediaItems = mediaItems;
this.startMediaItemIndex = startIndex;
this.startPositionMs = startPositionMs;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX)).open();
}
@Override
@ -678,9 +757,8 @@ public class MockPlayer implements Player {
@Override
public void setPlaylistMetadata(MediaMetadata playlistMetadata) {
setPlaylistMetadataCalled = true;
this.playlistMetadata = playlistMetadata;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_SET_PLAYLIST_METADATA)).open();
}
@Deprecated
@ -775,70 +853,61 @@ public class MockPlayer implements Player {
@Override
public void addMediaItem(MediaItem mediaItem) {
addMediaItemCalled = true;
this.mediaItem = mediaItem;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_ADD_MEDIA_ITEM)).open();
}
@Override
public void addMediaItem(int index, MediaItem mediaItem) {
addMediaItemWithIndexCalled = true;
this.index = index;
this.mediaItem = mediaItem;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_ADD_MEDIA_ITEM_WITH_INDEX)).open();
}
@Override
public void addMediaItems(List<MediaItem> mediaItems) {
addMediaItemsCalled = true;
this.mediaItems = mediaItems;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_ADD_MEDIA_ITEMS)).open();
}
@Override
public void addMediaItems(int index, List<MediaItem> mediaItems) {
addMediaItemsWithIndexCalled = true;
this.index = index;
this.mediaItems = mediaItems;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_ADD_MEDIA_ITEMS_WITH_INDEX)).open();
}
@Override
public void removeMediaItem(int index) {
removeMediaItemCalled = true;
this.index = index;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_REMOVE_MEDIA_ITEM)).open();
}
@Override
public void removeMediaItems(int fromIndex, int toIndex) {
removeMediaItemsCalled = true;
this.fromIndex = fromIndex;
this.toIndex = toIndex;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_REMOVE_MEDIA_ITEMS)).open();
}
@Override
public void clearMediaItems() {
clearMediaItemsCalled = true;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_CLEAR_MEDIA_ITEMS)).open();
}
@Override
public void moveMediaItem(int currentIndex, int newIndex) {
moveMediaItemCalled = true;
this.index = currentIndex;
this.newIndex = newIndex;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_MOVE_MEDIA_ITEM)).open();
}
@Override
public void moveMediaItems(int fromIndex, int toIndex, int newIndex) {
moveMediaItemsCalled = true;
this.fromIndex = fromIndex;
this.toIndex = toIndex;
this.newIndex = newIndex;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_MOVE_MEDIA_ITEMS)).open();
}
@Deprecated
@ -901,20 +970,17 @@ public class MockPlayer implements Player {
@Override
public void seekToPreviousMediaItem() {
seekToPreviousMediaItemCalled = true;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_SEEK_TO_PREVIOUS_MEDIA_ITEM)).open();
}
@Override
public void seekToNextMediaItem() {
seekToNextMediaItemCalled = true;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_SEEK_TO_NEXT_MEDIA_ITEM)).open();
}
@Override
public void seekToPrevious() {
seekToPreviousCalled = true;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_SEEK_TO_PREVIOUS)).open();
}
@Override
@ -924,8 +990,7 @@ public class MockPlayer implements Player {
@Override
public void seekToNext() {
seekToNextCalled = true;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_SEEK_TO_NEXT)).open();
}
@Override
@ -935,9 +1000,8 @@ public class MockPlayer implements Player {
@Override
public void setRepeatMode(int repeatMode) {
setRepeatModeCalled = true;
this.repeatMode = repeatMode;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_SET_REPEAT_MODE)).open();
}
@Override
@ -947,9 +1011,8 @@ public class MockPlayer implements Player {
@Override
public void setShuffleModeEnabled(boolean shuffleModeEnabled) {
setShuffleModeCalled = true;
this.shuffleModeEnabled = shuffleModeEnabled;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_SET_SHUFFLE_MODE)).open();
}
@Override
@ -1001,9 +1064,6 @@ public class MockPlayer implements Player {
@Override
public VideoSize getVideoSize() {
if (videoSize == null) {
videoSize = VideoSize.UNKNOWN;
}
return videoSize;
}
@ -1134,9 +1194,8 @@ public class MockPlayer implements Player {
@Override
public void setTrackSelectionParameters(TrackSelectionParameters parameters) {
setTrackSelectionParametersCalled = true;
trackSelectionParameters = parameters;
countDownLatch.countDown();
checkNotNull(conditionVariables.get(METHOD_SET_TRACK_SELECTION_PARAMETERS)).open();
}
@Override
@ -1144,10 +1203,73 @@ public class MockPlayer implements Player {
return applicationLooper;
}
/** Returns whether {@code method} has been called at least once. */
public boolean hasMethodBeenCalled(@Method int method) {
return checkNotNull(conditionVariables.get(method)).isOpen();
}
/**
* Awaits up to {@code timeOutMs} until {@code method} is called, otherwise throws a {@link
* TimeoutException}.
*/
public void awaitMethodCalled(@Method int method, long timeOutMs)
throws TimeoutException, InterruptedException {
if (!checkNotNull(conditionVariables.get(method)).block(timeOutMs)) {
throw new TimeoutException(
Util.formatInvariant("Method %d not called after %f ms", method, timeOutMs));
}
}
private static ImmutableMap<@Method Integer, ConditionVariable> createMethodConditionVariables() {
return new ImmutableMap.Builder<@Method Integer, ConditionVariable>()
.put(METHOD_ADD_MEDIA_ITEM, new ConditionVariable())
.put(METHOD_ADD_MEDIA_ITEMS, new ConditionVariable())
.put(METHOD_ADD_MEDIA_ITEM_WITH_INDEX, new ConditionVariable())
.put(METHOD_ADD_MEDIA_ITEMS_WITH_INDEX, new ConditionVariable())
.put(METHOD_CLEAR_MEDIA_ITEMS, new ConditionVariable())
.put(METHOD_DECREASE_DEVICE_VOLUME, new ConditionVariable())
.put(METHOD_INCREASE_DEVICE_VOLUME, new ConditionVariable())
.put(METHOD_MOVE_MEDIA_ITEM, new ConditionVariable())
.put(METHOD_MOVE_MEDIA_ITEMS, new ConditionVariable())
.put(METHOD_PAUSE, new ConditionVariable())
.put(METHOD_PLAY, new ConditionVariable())
.put(METHOD_PREPARE, new ConditionVariable())
.put(METHOD_RELEASE, new ConditionVariable())
.put(METHOD_REMOVE_MEDIA_ITEM, new ConditionVariable())
.put(METHOD_REMOVE_MEDIA_ITEMS, new ConditionVariable())
.put(METHOD_SEEK_BACK, new ConditionVariable())
.put(METHOD_SEEK_FORWARD, new ConditionVariable())
.put(METHOD_SEEK_TO, new ConditionVariable())
.put(METHOD_SEEK_TO_DEFAULT_POSITION, new ConditionVariable())
.put(METHOD_SEEK_TO_DEFAULT_POSITION_WITH_MEDIA_ITEM_INDEX, new ConditionVariable())
.put(METHOD_SEEK_TO_NEXT, new ConditionVariable())
.put(METHOD_SEEK_TO_NEXT_MEDIA_ITEM, new ConditionVariable())
.put(METHOD_SEEK_TO_PREVIOUS, new ConditionVariable())
.put(METHOD_SEEK_TO_PREVIOUS_MEDIA_ITEM, new ConditionVariable())
.put(METHOD_SEEK_TO_WITH_MEDIA_ITEM_INDEX, new ConditionVariable())
.put(METHOD_SET_DEVICE_MUTED, new ConditionVariable())
.put(METHOD_SET_DEVICE_VOLUME, new ConditionVariable())
.put(METHOD_SET_MEDIA_ITEM, new ConditionVariable())
.put(METHOD_SET_MEDIA_ITEM_WITH_RESET_POSITION, new ConditionVariable())
.put(METHOD_SET_MEDIA_ITEM_WITH_START_POSITION, new ConditionVariable())
.put(METHOD_SET_MEDIA_ITEMS, new ConditionVariable())
.put(METHOD_SET_MEDIA_ITEMS_WITH_RESET_POSITION, new ConditionVariable())
.put(METHOD_SET_MEDIA_ITEMS_WITH_START_INDEX, new ConditionVariable())
.put(METHOD_SET_PLAY_WHEN_READY, new ConditionVariable())
.put(METHOD_SET_PLAYBACK_PARAMETERS, new ConditionVariable())
.put(METHOD_SET_PLAYBACK_SPEED, new ConditionVariable())
.put(METHOD_SET_PLAYLIST_METADATA, new ConditionVariable())
.put(METHOD_SET_REPEAT_MODE, new ConditionVariable())
.put(METHOD_SET_SHUFFLE_MODE, new ConditionVariable())
.put(METHOD_SET_TRACK_SELECTION_PARAMETERS, new ConditionVariable())
.put(METHOD_SET_VOLUME, new ConditionVariable())
.put(METHOD_STOP, new ConditionVariable())
.buildOrThrow();
}
/** Builder for {@link MockPlayer}. */
public static final class Builder {
private int latchCount;
private boolean changePlayerStateWithTransportControl;
private Looper applicationLooper;
private int itemCount;
@ -1156,11 +1278,6 @@ public class MockPlayer implements Player {
applicationLooper = Util.getCurrentOrMainLooper();
}
public Builder setLatchCount(int latchCount) {
this.latchCount = latchCount;
return this;
}
public Builder setChangePlayerStateWithTransportControl(
boolean changePlayerStateWithTransportControl) {
this.changePlayerStateWithTransportControl = changePlayerStateWithTransportControl;

View File

@ -156,22 +156,10 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
* <li>Corresponding method: {@link #setKeepContentOnPlayerReset(boolean)}
* <li>Default: {@code false}
* </ul>
* <li><b>{@code player_layout_id}</b> - Specifies the id of the layout to be inflated. See below
* for more details.
* <ul>
* <li>Corresponding method: None
* <li>Default: {@code R.layout.exo_player_view}
* </ul>
* <li><b>{@code controller_layout_id}</b> - Specifies the id of the layout resource to be
* inflated by the child {@link PlayerControlView}. See below for more details.
* <ul>
* <li>Corresponding method: None
* <li>Default: {@code R.layout.exo_player_control_view}
* </ul>
* <li>All attributes that can be set on {@link PlayerControlView} and {@link DefaultTimeBar} can
* also be set on a PlayerView, and will be propagated to the inflated {@link
* PlayerControlView} unless the layout is overridden to specify a custom {@code
* exo_controller} (see below).
* exo_controller}.
* </ul>
*
* <h2>Overriding drawables</h2>