commit
72a4fb082d
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
|
@ -96,7 +96,6 @@ class PlaybackService : MediaLibraryService() {
|
||||
|
||||
val item = MediaItemTree.getItemFromTitle(mediaTitle) ?: MediaItemTree.getRandomItem()
|
||||
player.setMediaItem(item)
|
||||
player.prepare()
|
||||
}
|
||||
|
||||
override fun onSetMediaUri(
|
||||
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
3
gradle/wrapper/gradle-wrapper.properties
vendored
3
gradle/wrapper/gradle-wrapper.properties
vendored
@ -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
298
gradlew
vendored
@ -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
53
gradlew.bat
vendored
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 {}
|
||||
|
@ -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,
|
||||
|
@ -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(),
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 =
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user