Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
SDK
/
exoplayer
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
a0843d0e
authored
Oct 21, 2019
by
aquilescanta
Committed by
Oliver Woodman
Oct 30, 2019
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Guard playWhenReady masking against regular status updates
PiperOrigin-RevId: 275863101
parent
dbfc101e
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
65 additions
and
18 deletions
extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java
extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java
View file @
a0843d0e
...
@@ -16,7 +16,6 @@
...
@@ -16,7 +16,6 @@
package
com
.
google
.
android
.
exoplayer2
.
ext
.
cast
;
package
com
.
google
.
android
.
exoplayer2
.
ext
.
cast
;
import
android.os.Looper
;
import
android.os.Looper
;
import
androidx.annotation.NonNull
;
import
androidx.annotation.Nullable
;
import
androidx.annotation.Nullable
;
import
com.google.android.exoplayer2.BasePlayer
;
import
com.google.android.exoplayer2.BasePlayer
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.C
;
...
@@ -99,6 +98,7 @@ public final class CastPlayer extends BasePlayer {
...
@@ -99,6 +98,7 @@ public final class CastPlayer extends BasePlayer {
@Nullable
private
SessionAvailabilityListener
sessionAvailabilityListener
;
@Nullable
private
SessionAvailabilityListener
sessionAvailabilityListener
;
// Internal state.
// Internal state.
private
final
StateHolder
<
Boolean
>
playWhenReady
;
@Nullable
private
RemoteMediaClient
remoteMediaClient
;
@Nullable
private
RemoteMediaClient
remoteMediaClient
;
private
CastTimeline
currentTimeline
;
private
CastTimeline
currentTimeline
;
private
TrackGroupArray
currentTrackGroups
;
private
TrackGroupArray
currentTrackGroups
;
...
@@ -106,7 +106,6 @@ public final class CastPlayer extends BasePlayer {
...
@@ -106,7 +106,6 @@ public final class CastPlayer extends BasePlayer {
@Player
.
State
private
int
playbackState
;
@Player
.
State
private
int
playbackState
;
private
int
repeatMode
;
private
int
repeatMode
;
private
int
currentWindowIndex
;
private
int
currentWindowIndex
;
private
boolean
playWhenReady
;
private
long
lastReportedPositionMs
;
private
long
lastReportedPositionMs
;
private
int
pendingSeekCount
;
private
int
pendingSeekCount
;
private
int
pendingSeekWindowIndex
;
private
int
pendingSeekWindowIndex
;
...
@@ -131,6 +130,7 @@ public final class CastPlayer extends BasePlayer {
...
@@ -131,6 +130,7 @@ public final class CastPlayer extends BasePlayer {
CastSession
session
=
sessionManager
.
getCurrentCastSession
();
CastSession
session
=
sessionManager
.
getCurrentCastSession
();
remoteMediaClient
=
session
!=
null
?
session
.
getRemoteMediaClient
()
:
null
;
remoteMediaClient
=
session
!=
null
?
session
.
getRemoteMediaClient
()
:
null
;
playWhenReady
=
new
StateHolder
<>(
false
);
playbackState
=
STATE_IDLE
;
playbackState
=
STATE_IDLE
;
repeatMode
=
REPEAT_MODE_OFF
;
repeatMode
=
REPEAT_MODE_OFF
;
currentTimeline
=
CastTimeline
.
EMPTY_CAST_TIMELINE
;
currentTimeline
=
CastTimeline
.
EMPTY_CAST_TIMELINE
;
...
@@ -357,18 +357,22 @@ public final class CastPlayer extends BasePlayer {
...
@@ -357,18 +357,22 @@ public final class CastPlayer extends BasePlayer {
flushNotifications
();
flushNotifications
();
PendingResult
<
MediaChannelResult
>
pendingResult
=
PendingResult
<
MediaChannelResult
>
pendingResult
=
playWhenReady
?
remoteMediaClient
.
play
()
:
remoteMediaClient
.
pause
();
playWhenReady
?
remoteMediaClient
.
play
()
:
remoteMediaClient
.
pause
();
pendingResult
.
setResultCallback
(
this
.
playWhenReady
.
pendingResultCallback
=
mediaChannelResult
->
{
new
ResultCallback
<
MediaChannelResult
>()
{
if
(
remoteMediaClient
!=
null
)
{
@Override
updatePlayerStateAndNotifyIfChanged
();
public
void
onResult
(
MediaChannelResult
mediaChannelResult
)
{
flushNotifications
();
if
(
remoteMediaClient
!=
null
)
{
updatePlayerStateAndNotifyIfChanged
(
this
);
flushNotifications
();
}
}
}
});
};
pendingResult
.
setResultCallback
(
this
.
playWhenReady
.
pendingResultCallback
);
}
}
@Override
@Override
public
boolean
getPlayWhenReady
()
{
public
boolean
getPlayWhenReady
()
{
return
playWhenReady
;
return
playWhenReady
.
value
;
}
}
@Override
@Override
...
@@ -571,9 +575,9 @@ public final class CastPlayer extends BasePlayer {
...
@@ -571,9 +575,9 @@ public final class CastPlayer extends BasePlayer {
// There is no session. We leave the state of the player as it is now.
// There is no session. We leave the state of the player as it is now.
return
;
return
;
}
}
boolean
wasPlaying
=
playbackState
==
Player
.
STATE_READY
&&
playWhenReady
;
boolean
wasPlaying
=
playbackState
==
Player
.
STATE_READY
&&
playWhenReady
.
value
;
updatePlayerStateAndNotifyIfChanged
();
updatePlayerStateAndNotifyIfChanged
(
/* resultCallback= */
null
);
boolean
isPlaying
=
playbackState
==
Player
.
STATE_READY
&&
playWhenReady
;
boolean
isPlaying
=
playbackState
==
Player
.
STATE_READY
&&
playWhenReady
.
value
;
if
(
wasPlaying
!=
isPlaying
)
{
if
(
wasPlaying
!=
isPlaying
)
{
notificationsBatch
.
add
(
notificationsBatch
.
add
(
new
ListenerNotificationTask
(
listener
->
listener
.
onIsPlayingChanged
(
isPlaying
)));
new
ListenerNotificationTask
(
listener
->
listener
.
onIsPlayingChanged
(
isPlaying
)));
...
@@ -605,10 +609,22 @@ public final class CastPlayer extends BasePlayer {
...
@@ -605,10 +609,22 @@ public final class CastPlayer extends BasePlayer {
flushNotifications
();
flushNotifications
();
}
}
/**
* Updates {@link #playWhenReady} and {@link #playbackState} to match the Cast {@code
* remoteMediaClient} state, and notifies listeners of any state changes.
*
* <p>This method will only update values whose {@link StateHolder#pendingResultCallback} matches
* the given {@code resultCallback}.
*/
@RequiresNonNull
(
"remoteMediaClient"
)
@RequiresNonNull
(
"remoteMediaClient"
)
private
void
updatePlayerStateAndNotifyIfChanged
()
{
private
void
updatePlayerStateAndNotifyIfChanged
(
ResultCallback
<?>
resultCallback
)
{
setPlayerStateAndNotifyIfChanged
(
boolean
newPlayWhenReadyValue
=
playWhenReady
.
value
;
!
remoteMediaClient
.
isPaused
(),
fetchPlaybackState
(
remoteMediaClient
));
if
(
playWhenReady
.
acceptsUpdate
(
resultCallback
))
{
newPlayWhenReadyValue
=
!
remoteMediaClient
.
isPaused
();
playWhenReady
.
clearPendingResultCallback
();
}
// We do not mask the playback state, so try setting it regardless of the playWhenReady masking.
setPlayerStateAndNotifyIfChanged
(
newPlayWhenReadyValue
,
fetchPlaybackState
(
remoteMediaClient
));
}
}
@RequiresNonNull
(
"remoteMediaClient"
)
@RequiresNonNull
(
"remoteMediaClient"
)
...
@@ -700,8 +716,8 @@ public final class CastPlayer extends BasePlayer {
...
@@ -700,8 +716,8 @@ public final class CastPlayer extends BasePlayer {
private
void
setPlayerStateAndNotifyIfChanged
(
private
void
setPlayerStateAndNotifyIfChanged
(
boolean
playWhenReady
,
@Player
.
State
int
playbackState
)
{
boolean
playWhenReady
,
@Player
.
State
int
playbackState
)
{
if
(
this
.
playWhenReady
!=
playWhenReady
||
this
.
playbackState
!=
playbackState
)
{
if
(
this
.
playWhenReady
.
value
!=
playWhenReady
||
this
.
playbackState
!=
playbackState
)
{
this
.
playWhenReady
=
playWhenReady
;
this
.
playWhenReady
.
value
=
playWhenReady
;
this
.
playbackState
=
playbackState
;
this
.
playbackState
=
playbackState
;
notificationsBatch
.
add
(
notificationsBatch
.
add
(
new
ListenerNotificationTask
(
new
ListenerNotificationTask
(
...
@@ -918,7 +934,7 @@ public final class CastPlayer extends BasePlayer {
...
@@ -918,7 +934,7 @@ public final class CastPlayer extends BasePlayer {
private
final
class
SeekResultCallback
implements
ResultCallback
<
MediaChannelResult
>
{
private
final
class
SeekResultCallback
implements
ResultCallback
<
MediaChannelResult
>
{
@Override
@Override
public
void
onResult
(
@NonNull
MediaChannelResult
result
)
{
public
void
onResult
(
MediaChannelResult
result
)
{
int
statusCode
=
result
.
getStatus
().
getStatusCode
();
int
statusCode
=
result
.
getStatus
().
getStatusCode
();
if
(
statusCode
!=
CastStatusCodes
.
SUCCESS
&&
statusCode
!=
CastStatusCodes
.
REPLACED
)
{
if
(
statusCode
!=
CastStatusCodes
.
SUCCESS
&&
statusCode
!=
CastStatusCodes
.
REPLACED
)
{
Log
.
e
(
TAG
,
"Seek failed. Error code "
+
statusCode
+
": "
Log
.
e
(
TAG
,
"Seek failed. Error code "
+
statusCode
+
": "
...
@@ -933,6 +949,37 @@ public final class CastPlayer extends BasePlayer {
...
@@ -933,6 +949,37 @@ public final class CastPlayer extends BasePlayer {
}
}
}
}
/** Holds the value and the masking status of a specific part of the {@link CastPlayer} state. */
private
static
final
class
StateHolder
<
T
>
{
/** The user-facing value of a specific part of the {@link CastPlayer} state. */
public
T
value
;
/**
* If {@link #value} is being masked, holds the result callback for the operation that triggered
* the masking. Or null if {@link #value} is not being masked.
*/
@Nullable
public
ResultCallback
<
MediaChannelResult
>
pendingResultCallback
;
public
StateHolder
(
T
initialValue
)
{
value
=
initialValue
;
}
public
void
clearPendingResultCallback
()
{
pendingResultCallback
=
null
;
}
/**
* Returns whether {@link #value} is being masked by the operation associated to the given
* result callback.
*
* @param resultCallback A result callback.
*/
public
boolean
acceptsUpdate
(
ResultCallback
<?>
resultCallback
)
{
return
pendingResultCallback
==
resultCallback
;
}
}
private
final
class
ListenerNotificationTask
{
private
final
class
ListenerNotificationTask
{
private
final
Iterator
<
ListenerHolder
>
listenersSnapshot
;
private
final
Iterator
<
ListenerHolder
>
listenersSnapshot
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment