mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Compare commits
6 Commits
abe836d9cd
...
4045acd13b
Author | SHA1 | Date | |
---|---|---|---|
![]() |
4045acd13b | ||
![]() |
90844f11e8 | ||
![]() |
f1c62c1239 | ||
![]() |
4b991ad42f | ||
![]() |
75ac9cd191 | ||
![]() |
2b8700beaa |
@ -3,6 +3,9 @@
|
|||||||
### Unreleased changes
|
### Unreleased changes
|
||||||
|
|
||||||
* Common Library:
|
* Common Library:
|
||||||
|
* Change `SimpleBasePlayer.State` access from protected to public to make
|
||||||
|
it easier to handle updates in other classes
|
||||||
|
([#2128](https://github.com/androidx/media/issues/2128)).
|
||||||
* ExoPlayer:
|
* ExoPlayer:
|
||||||
* Transformer:
|
* Transformer:
|
||||||
* Track Selection:
|
* Track Selection:
|
||||||
@ -19,6 +22,8 @@
|
|||||||
* Muxers:
|
* Muxers:
|
||||||
* IMA extension:
|
* IMA extension:
|
||||||
* Session:
|
* Session:
|
||||||
|
* Make `MediaSession.setSessionActivity(PendingIntent)` accept null
|
||||||
|
([#2109](https://github.com/androidx/media/issues/2109)).
|
||||||
* UI:
|
* UI:
|
||||||
* Downloads:
|
* Downloads:
|
||||||
* OkHttp Extension:
|
* OkHttp Extension:
|
||||||
|
@ -96,7 +96,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
public abstract class SimpleBasePlayer extends BasePlayer {
|
public abstract class SimpleBasePlayer extends BasePlayer {
|
||||||
|
|
||||||
/** An immutable state description of the player. */
|
/** An immutable state description of the player. */
|
||||||
protected static final class State {
|
public static final class State {
|
||||||
|
|
||||||
/** A builder for {@link State} objects. */
|
/** A builder for {@link State} objects. */
|
||||||
public static final class Builder {
|
public static final class Builder {
|
||||||
|
@ -84,6 +84,7 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities {
|
|||||||
private boolean streamIsFinal;
|
private boolean streamIsFinal;
|
||||||
private boolean throwRendererExceptionIsExecuting;
|
private boolean throwRendererExceptionIsExecuting;
|
||||||
private Timeline timeline;
|
private Timeline timeline;
|
||||||
|
@Nullable private MediaSource.MediaPeriodId mediaPeriodId;
|
||||||
|
|
||||||
@GuardedBy("lock")
|
@GuardedBy("lock")
|
||||||
@Nullable
|
@Nullable
|
||||||
@ -144,6 +145,7 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities {
|
|||||||
throws ExoPlaybackException {
|
throws ExoPlaybackException {
|
||||||
Assertions.checkState(state == STATE_DISABLED);
|
Assertions.checkState(state == STATE_DISABLED);
|
||||||
this.configuration = configuration;
|
this.configuration = configuration;
|
||||||
|
this.mediaPeriodId = mediaPeriodId;
|
||||||
state = STATE_ENABLED;
|
state = STATE_ENABLED;
|
||||||
onEnabled(joining, mayRenderStartOfStream);
|
onEnabled(joining, mayRenderStartOfStream);
|
||||||
replaceStream(formats, stream, startPositionUs, offsetUs, mediaPeriodId);
|
replaceStream(formats, stream, startPositionUs, offsetUs, mediaPeriodId);
|
||||||
@ -167,6 +169,7 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities {
|
|||||||
throws ExoPlaybackException {
|
throws ExoPlaybackException {
|
||||||
Assertions.checkState(!streamIsFinal);
|
Assertions.checkState(!streamIsFinal);
|
||||||
this.stream = stream;
|
this.stream = stream;
|
||||||
|
this.mediaPeriodId = mediaPeriodId;
|
||||||
if (readingPositionUs == C.TIME_END_OF_SOURCE) {
|
if (readingPositionUs == C.TIME_END_OF_SOURCE) {
|
||||||
readingPositionUs = startPositionUs;
|
readingPositionUs = startPositionUs;
|
||||||
}
|
}
|
||||||
@ -242,6 +245,7 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities {
|
|||||||
streamFormats = null;
|
streamFormats = null;
|
||||||
streamIsFinal = false;
|
streamIsFinal = false;
|
||||||
onDisabled();
|
onDisabled();
|
||||||
|
mediaPeriodId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -485,6 +489,15 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities {
|
|||||||
return timeline;
|
return timeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link MediaSource.MediaPeriodId} of the {@link MediaPeriod} producing the {@code stream},
|
||||||
|
* or {@code null} if the renderer is disabled.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
protected final MediaSource.MediaPeriodId getMediaPeriodId() {
|
||||||
|
return mediaPeriodId;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an {@link ExoPlaybackException} of type {@link ExoPlaybackException#TYPE_RENDERER} for
|
* Creates an {@link ExoPlaybackException} of type {@link ExoPlaybackException#TYPE_RENDERER} for
|
||||||
* this renderer.
|
* this renderer.
|
||||||
@ -530,7 +543,14 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ExoPlaybackException.createForRenderer(
|
return ExoPlaybackException.createForRenderer(
|
||||||
cause, getName(), getIndex(), format, formatSupport, isRecoverable, errorCode);
|
cause,
|
||||||
|
getName(),
|
||||||
|
getIndex(),
|
||||||
|
format,
|
||||||
|
formatSupport,
|
||||||
|
mediaPeriodId,
|
||||||
|
isRecoverable,
|
||||||
|
errorCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -131,6 +131,31 @@ public final class ExoPlaybackException extends PlaybackException {
|
|||||||
return new ExoPlaybackException(TYPE_SOURCE, cause, errorCode);
|
return new ExoPlaybackException(TYPE_SOURCE, cause, errorCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #createForRenderer(Throwable, String, int, Format, int, MediaPeriodId,
|
||||||
|
* boolean, int)} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@UnstableApi
|
||||||
|
public static ExoPlaybackException createForRenderer(
|
||||||
|
Throwable cause,
|
||||||
|
String rendererName,
|
||||||
|
int rendererIndex,
|
||||||
|
@Nullable Format rendererFormat,
|
||||||
|
@FormatSupport int rendererFormatSupport,
|
||||||
|
boolean isRecoverable,
|
||||||
|
@ErrorCode int errorCode) {
|
||||||
|
return createForRenderer(
|
||||||
|
cause,
|
||||||
|
rendererName,
|
||||||
|
rendererIndex,
|
||||||
|
rendererFormat,
|
||||||
|
rendererFormatSupport,
|
||||||
|
/* mediaPeriodId= */ null,
|
||||||
|
isRecoverable,
|
||||||
|
errorCode);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an instance of type {@link #TYPE_RENDERER}.
|
* Creates an instance of type {@link #TYPE_RENDERER}.
|
||||||
*
|
*
|
||||||
@ -142,6 +167,8 @@ public final class ExoPlaybackException extends PlaybackException {
|
|||||||
* or null if the renderer wasn't using a {@link Format}.
|
* or null if the renderer wasn't using a {@link Format}.
|
||||||
* @param rendererFormatSupport The {@link FormatSupport} of the renderer for {@code
|
* @param rendererFormatSupport The {@link FormatSupport} of the renderer for {@code
|
||||||
* rendererFormat}. Ignored if {@code rendererFormat} is null.
|
* rendererFormat}. Ignored if {@code rendererFormat} is null.
|
||||||
|
* @param mediaPeriodId The {@link MediaPeriodId mediaPeriodId} of the media associated with this
|
||||||
|
* error, or null if undetermined.
|
||||||
* @param isRecoverable If the failure can be recovered by disabling and re-enabling the renderer.
|
* @param isRecoverable If the failure can be recovered by disabling and re-enabling the renderer.
|
||||||
* @param errorCode See {@link #errorCode}.
|
* @param errorCode See {@link #errorCode}.
|
||||||
* @return The created instance.
|
* @return The created instance.
|
||||||
@ -153,9 +180,9 @@ public final class ExoPlaybackException extends PlaybackException {
|
|||||||
int rendererIndex,
|
int rendererIndex,
|
||||||
@Nullable Format rendererFormat,
|
@Nullable Format rendererFormat,
|
||||||
@FormatSupport int rendererFormatSupport,
|
@FormatSupport int rendererFormatSupport,
|
||||||
|
@Nullable MediaPeriodId mediaPeriodId,
|
||||||
boolean isRecoverable,
|
boolean isRecoverable,
|
||||||
@ErrorCode int errorCode) {
|
@ErrorCode int errorCode) {
|
||||||
|
|
||||||
return new ExoPlaybackException(
|
return new ExoPlaybackException(
|
||||||
TYPE_RENDERER,
|
TYPE_RENDERER,
|
||||||
cause,
|
cause,
|
||||||
@ -165,6 +192,7 @@ public final class ExoPlaybackException extends PlaybackException {
|
|||||||
rendererIndex,
|
rendererIndex,
|
||||||
rendererFormat,
|
rendererFormat,
|
||||||
rendererFormat == null ? C.FORMAT_HANDLED : rendererFormatSupport,
|
rendererFormat == null ? C.FORMAT_HANDLED : rendererFormatSupport,
|
||||||
|
mediaPeriodId,
|
||||||
isRecoverable);
|
isRecoverable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,6 +236,7 @@ public final class ExoPlaybackException extends PlaybackException {
|
|||||||
/* rendererIndex= */ C.INDEX_UNSET,
|
/* rendererIndex= */ C.INDEX_UNSET,
|
||||||
/* rendererFormat= */ null,
|
/* rendererFormat= */ null,
|
||||||
/* rendererFormatSupport= */ C.FORMAT_HANDLED,
|
/* rendererFormatSupport= */ C.FORMAT_HANDLED,
|
||||||
|
/* mediaPeriodId= */ null,
|
||||||
/* isRecoverable= */ false);
|
/* isRecoverable= */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,6 +250,7 @@ public final class ExoPlaybackException extends PlaybackException {
|
|||||||
/* rendererIndex= */ C.INDEX_UNSET,
|
/* rendererIndex= */ C.INDEX_UNSET,
|
||||||
/* rendererFormat= */ null,
|
/* rendererFormat= */ null,
|
||||||
/* rendererFormatSupport= */ C.FORMAT_HANDLED,
|
/* rendererFormatSupport= */ C.FORMAT_HANDLED,
|
||||||
|
/* mediaPeriodId= */ null,
|
||||||
/* isRecoverable= */ false);
|
/* isRecoverable= */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,6 +263,7 @@ public final class ExoPlaybackException extends PlaybackException {
|
|||||||
int rendererIndex,
|
int rendererIndex,
|
||||||
@Nullable Format rendererFormat,
|
@Nullable Format rendererFormat,
|
||||||
@FormatSupport int rendererFormatSupport,
|
@FormatSupport int rendererFormatSupport,
|
||||||
|
@Nullable MediaPeriodId mediaPeriodId,
|
||||||
boolean isRecoverable) {
|
boolean isRecoverable) {
|
||||||
this(
|
this(
|
||||||
deriveMessage(
|
deriveMessage(
|
||||||
@ -249,7 +280,7 @@ public final class ExoPlaybackException extends PlaybackException {
|
|||||||
rendererIndex,
|
rendererIndex,
|
||||||
rendererFormat,
|
rendererFormat,
|
||||||
rendererFormatSupport,
|
rendererFormatSupport,
|
||||||
/* mediaPeriodId= */ null,
|
mediaPeriodId,
|
||||||
/* timestampMs= */ SystemClock.elapsedRealtime(),
|
/* timestampMs= */ SystemClock.elapsedRealtime(),
|
||||||
isRecoverable);
|
isRecoverable);
|
||||||
}
|
}
|
||||||
|
@ -693,7 +693,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
} catch (ExoPlaybackException e) {
|
} catch (ExoPlaybackException e) {
|
||||||
if (e.type == ExoPlaybackException.TYPE_RENDERER) {
|
if (e.type == ExoPlaybackException.TYPE_RENDERER) {
|
||||||
@Nullable MediaPeriodHolder readingPeriod = queue.getReadingPeriod();
|
@Nullable MediaPeriodHolder readingPeriod = queue.getReadingPeriod();
|
||||||
if (readingPeriod != null) {
|
if (readingPeriod != null && e.mediaPeriodId == null) {
|
||||||
// We can assume that all renderer errors happen in the context of the reading period. See
|
// We can assume that all renderer errors happen in the context of the reading period. See
|
||||||
// [internal: b/150584930#comment4] for exceptions that aren't covered by this assumption.
|
// [internal: b/150584930#comment4] for exceptions that aren't covered by this assumption.
|
||||||
e =
|
e =
|
||||||
|
@ -312,6 +312,7 @@ public class MediaCodecAudioRendererTest {
|
|||||||
/* rendererIndex= */ 0,
|
/* rendererIndex= */ 0,
|
||||||
format,
|
format,
|
||||||
C.FORMAT_HANDLED,
|
C.FORMAT_HANDLED,
|
||||||
|
/* mediaPeriodId= */ null,
|
||||||
/* isRecoverable= */ false,
|
/* isRecoverable= */ false,
|
||||||
PlaybackException.ERROR_CODE_UNSPECIFIED));
|
PlaybackException.ERROR_CODE_UNSPECIFIED));
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ oneway interface IMediaController {
|
|||||||
int seq, in Bundle sessionCommandsBundle, in Bundle playerCommandsBundle) = 3009;
|
int seq, in Bundle sessionCommandsBundle, in Bundle playerCommandsBundle) = 3009;
|
||||||
void onRenderedFirstFrame(int seq) = 3010;
|
void onRenderedFirstFrame(int seq) = 3010;
|
||||||
void onExtrasChanged(int seq, in Bundle extras) = 3011;
|
void onExtrasChanged(int seq, in Bundle extras) = 3011;
|
||||||
void onSessionActivityChanged(int seq, in PendingIntent pendingIntent) = 3013;
|
void onSessionActivityChanged(int seq, in @nullable PendingIntent pendingIntent) = 3013;
|
||||||
void onError(int seq, in Bundle sessionError) = 3014;
|
void onError(int seq, in Bundle sessionError) = 3014;
|
||||||
void onSetMediaButtonPreferences(int seq, in List<Bundle> commandButtonList) = 3015;
|
void onSetMediaButtonPreferences(int seq, in List<Bundle> commandButtonList) = 3015;
|
||||||
// Next Id for MediaController: 3016
|
// Next Id for MediaController: 3016
|
||||||
|
@ -493,7 +493,7 @@ public class MediaController implements Player {
|
|||||||
*/
|
*/
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
default void onSessionActivityChanged(
|
default void onSessionActivityChanged(
|
||||||
MediaController controller, PendingIntent sessionActivity) {}
|
MediaController controller, @Nullable PendingIntent sessionActivity) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when an non-fatal error {@linkplain
|
* Called when an non-fatal error {@linkplain
|
||||||
|
@ -93,6 +93,7 @@ import com.google.common.util.concurrent.MoreExecutors;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.CancellationException;
|
import java.util.concurrent.CancellationException;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
@ -3079,8 +3080,8 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onSetSessionActivity(int seq, PendingIntent sessionActivity) {
|
public void onSetSessionActivity(int seq, @Nullable PendingIntent sessionActivity) {
|
||||||
if (!isConnected()) {
|
if (!isConnected() || Objects.equals(this.sessionActivity, sessionActivity)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.sessionActivity = sessionActivity;
|
this.sessionActivity = sessionActivity;
|
||||||
|
@ -214,10 +214,6 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||||||
@Override
|
@Override
|
||||||
public void onSessionActivityChanged(int seq, @Nullable PendingIntent sessionActivity)
|
public void onSessionActivityChanged(int seq, @Nullable PendingIntent sessionActivity)
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
if (sessionActivity == null) {
|
|
||||||
Log.w(TAG, "Ignoring null session activity intent");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dispatchControllerTaskOnHandler(
|
dispatchControllerTaskOnHandler(
|
||||||
controller -> controller.onSetSessionActivity(seq, sessionActivity));
|
controller -> controller.onSetSessionActivity(seq, sessionActivity));
|
||||||
}
|
}
|
||||||
|
@ -789,13 +789,16 @@ public class MediaSession {
|
|||||||
* Updates the session activity that was set when {@linkplain
|
* Updates the session activity that was set when {@linkplain
|
||||||
* Builder#setSessionActivity(PendingIntent) building the session}.
|
* Builder#setSessionActivity(PendingIntent) building the session}.
|
||||||
*
|
*
|
||||||
* @param activityPendingIntent The pending intent to start the session activity.
|
* <p>Note: When a controller is connected to the session that has a version smaller than 1.6.0,
|
||||||
|
* then setting the session activity to null has no effect on the controller side.
|
||||||
|
*
|
||||||
|
* @param activityPendingIntent The pending intent to start the session activity or null.
|
||||||
* @throws IllegalArgumentException if the {@link PendingIntent} passed into this method is
|
* @throws IllegalArgumentException if the {@link PendingIntent} passed into this method is
|
||||||
* {@linkplain PendingIntent#getActivity(Context, int, Intent, int) not an activity}.
|
* {@linkplain PendingIntent#getActivity(Context, int, Intent, int) not an activity}.
|
||||||
*/
|
*/
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
public final void setSessionActivity(PendingIntent activityPendingIntent) {
|
public final void setSessionActivity(@Nullable PendingIntent activityPendingIntent) {
|
||||||
if (Util.SDK_INT >= 31) {
|
if (Util.SDK_INT >= 31 && activityPendingIntent != null) {
|
||||||
checkArgument(Api31.isActivity(activityPendingIntent));
|
checkArgument(Api31.isActivity(activityPendingIntent));
|
||||||
}
|
}
|
||||||
impl.setSessionActivity(activityPendingIntent);
|
impl.setSessionActivity(activityPendingIntent);
|
||||||
@ -818,8 +821,8 @@ public class MediaSession {
|
|||||||
*/
|
*/
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
public final void setSessionActivity(
|
public final void setSessionActivity(
|
||||||
ControllerInfo controller, PendingIntent activityPendingIntent) {
|
ControllerInfo controller, @Nullable PendingIntent activityPendingIntent) {
|
||||||
if (Util.SDK_INT >= 31) {
|
if (Util.SDK_INT >= 31 && activityPendingIntent != null) {
|
||||||
checkArgument(Api31.isActivity(activityPendingIntent));
|
checkArgument(Api31.isActivity(activityPendingIntent));
|
||||||
}
|
}
|
||||||
impl.setSessionActivity(controller, activityPendingIntent);
|
impl.setSessionActivity(controller, activityPendingIntent);
|
||||||
@ -2088,7 +2091,7 @@ public class MediaSession {
|
|||||||
default void setMediaButtonPreferences(int seq, List<CommandButton> mediaButtonPreferences)
|
default void setMediaButtonPreferences(int seq, List<CommandButton> mediaButtonPreferences)
|
||||||
throws RemoteException {}
|
throws RemoteException {}
|
||||||
|
|
||||||
default void onSessionActivityChanged(int seq, PendingIntent sessionActivity)
|
default void onSessionActivityChanged(int seq, @Nullable PendingIntent sessionActivity)
|
||||||
throws RemoteException {}
|
throws RemoteException {}
|
||||||
|
|
||||||
default void onSessionExtrasChanged(int seq, Bundle sessionExtras) throws RemoteException {}
|
default void onSessionExtrasChanged(int seq, Bundle sessionExtras) throws RemoteException {}
|
||||||
|
@ -95,7 +95,6 @@ import java.util.List;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import org.checkerframework.checker.initialization.qual.Initialized;
|
import org.checkerframework.checker.initialization.qual.Initialized;
|
||||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|
||||||
|
|
||||||
/* package */ class MediaSessionImpl {
|
/* package */ class MediaSessionImpl {
|
||||||
|
|
||||||
@ -136,7 +135,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
|
|
||||||
private PlayerInfo playerInfo;
|
private PlayerInfo playerInfo;
|
||||||
private PlayerWrapper playerWrapper;
|
private PlayerWrapper playerWrapper;
|
||||||
private @MonotonicNonNull PendingIntent sessionActivity;
|
@Nullable private PendingIntent sessionActivity;
|
||||||
@Nullable private PlayerListener playerListener;
|
@Nullable private PlayerListener playerListener;
|
||||||
@Nullable private MediaSession.Listener mediaSessionListener;
|
@Nullable private MediaSession.Listener mediaSessionListener;
|
||||||
@Nullable private ControllerInfo controllerForCurrentRequest;
|
@Nullable private ControllerInfo controllerForCurrentRequest;
|
||||||
@ -850,7 +849,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
protected void setSessionActivity(PendingIntent sessionActivity) {
|
protected void setSessionActivity(@Nullable PendingIntent sessionActivity) {
|
||||||
this.sessionActivity = sessionActivity;
|
this.sessionActivity = sessionActivity;
|
||||||
ImmutableList<ControllerInfo> connectedControllers =
|
ImmutableList<ControllerInfo> connectedControllers =
|
||||||
sessionStub.getConnectedControllersManager().getConnectedControllers();
|
sessionStub.getConnectedControllersManager().getConnectedControllers();
|
||||||
@ -860,7 +859,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
protected void setSessionActivity(ControllerInfo controller, PendingIntent sessionActivity) {
|
protected void setSessionActivity(
|
||||||
|
ControllerInfo controller, @Nullable PendingIntent sessionActivity) {
|
||||||
if (controller.getControllerVersion() >= 3
|
if (controller.getControllerVersion() >= 3
|
||||||
&& sessionStub.getConnectedControllersManager().isConnected(controller)) {
|
&& sessionStub.getConnectedControllersManager().isConnected(controller)) {
|
||||||
dispatchRemoteControllerTaskWithoutReturn(
|
dispatchRemoteControllerTaskWithoutReturn(
|
||||||
|
@ -1137,7 +1137,7 @@ import org.checkerframework.checker.initialization.qual.Initialized;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSessionActivityChanged(int seq, PendingIntent sessionActivity) {
|
public void onSessionActivityChanged(int seq, @Nullable PendingIntent sessionActivity) {
|
||||||
sessionCompat.setSessionActivity(sessionActivity);
|
sessionCompat.setSessionActivity(sessionActivity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2098,9 +2098,10 @@ import java.util.concurrent.ExecutionException;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("nullness:argument") // sessionActivity can be null.
|
||||||
@Override
|
@Override
|
||||||
public void onSessionActivityChanged(int sequenceNumber, PendingIntent sessionActivity)
|
public void onSessionActivityChanged(
|
||||||
throws RemoteException {
|
int sequenceNumber, @Nullable PendingIntent sessionActivity) throws RemoteException {
|
||||||
iController.onSessionActivityChanged(sequenceNumber, sessionActivity);
|
iController.onSessionActivityChanged(sequenceNumber, sessionActivity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -550,7 +550,7 @@ public class MediaSessionCompat {
|
|||||||
*
|
*
|
||||||
* @param pi The intent to launch to show UI for this Session.
|
* @param pi The intent to launch to show UI for this Session.
|
||||||
*/
|
*/
|
||||||
public void setSessionActivity(PendingIntent pi) {
|
public void setSessionActivity(@Nullable PendingIntent pi) {
|
||||||
mImpl.setSessionActivity(pi);
|
mImpl.setSessionActivity(pi);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2219,7 +2219,7 @@ public class MediaSessionCompat {
|
|||||||
|
|
||||||
void setMetadata(@Nullable MediaMetadataCompat metadata);
|
void setMetadata(@Nullable MediaMetadataCompat metadata);
|
||||||
|
|
||||||
void setSessionActivity(PendingIntent pi);
|
void setSessionActivity(@Nullable PendingIntent pi);
|
||||||
|
|
||||||
void setMediaButtonReceiver(@Nullable PendingIntent mbr);
|
void setMediaButtonReceiver(@Nullable PendingIntent mbr);
|
||||||
|
|
||||||
@ -2700,7 +2700,7 @@ public class MediaSessionCompat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSessionActivity(PendingIntent pi) {
|
public void setSessionActivity(@Nullable PendingIntent pi) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
mSessionActivity = pi;
|
mSessionActivity = pi;
|
||||||
}
|
}
|
||||||
@ -4053,7 +4053,7 @@ public class MediaSessionCompat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSessionActivity(PendingIntent pi) {
|
public void setSessionActivity(@Nullable PendingIntent pi) {
|
||||||
mSessionFwk.setSessionActivity(pi);
|
mSessionFwk.setSessionActivity(pi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1217,6 +1217,7 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
|
|||||||
assertThat(playbackStateExtrasFromController.get()).string("key-0").isEqualTo("value-0");
|
assertThat(playbackStateExtrasFromController.get()).string("key-0").isEqualTo("value-0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation") // Testing access through deprecated androidx.media library
|
||||||
@Test
|
@Test
|
||||||
public void setSessionActivity_forAllControllers_changedWhenReceivedWithSetter()
|
public void setSessionActivity_forAllControllers_changedWhenReceivedWithSetter()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
@ -1224,12 +1225,17 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
|
|||||||
PendingIntent sessionActivity =
|
PendingIntent sessionActivity =
|
||||||
PendingIntent.getActivity(
|
PendingIntent.getActivity(
|
||||||
context, 0, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
|
context, 0, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
CountDownLatch latch = new CountDownLatch(1);
|
CountDownLatch playingLatch = new CountDownLatch(1);
|
||||||
|
CountDownLatch bufferingLatch = new CountDownLatch(1);
|
||||||
MediaControllerCompat.Callback callback =
|
MediaControllerCompat.Callback callback =
|
||||||
new MediaControllerCompat.Callback() {
|
new MediaControllerCompat.Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void onPlaybackStateChanged(PlaybackStateCompat state) {
|
public void onPlaybackStateChanged(PlaybackStateCompat state) {
|
||||||
latch.countDown();
|
if (state.getState() == PlaybackStateCompat.STATE_BUFFERING) {
|
||||||
|
bufferingLatch.countDown();
|
||||||
|
} else if (state.getState() == PlaybackStateCompat.STATE_PLAYING) {
|
||||||
|
playingLatch.countDown();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
controllerCompat.registerCallback(callback, handler);
|
controllerCompat.registerCallback(callback, handler);
|
||||||
@ -1238,12 +1244,25 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
|
|||||||
session.setSessionActivity(/* controllerKey= */ null, sessionActivity);
|
session.setSessionActivity(/* controllerKey= */ null, sessionActivity);
|
||||||
// The legacy API has no change listener for the session activity. Changing the state to
|
// The legacy API has no change listener for the session activity. Changing the state to
|
||||||
// trigger a callback.
|
// trigger a callback.
|
||||||
|
session
|
||||||
|
.getMockPlayer()
|
||||||
|
.notifyPlayWhenReadyChanged(
|
||||||
|
true,
|
||||||
|
Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST,
|
||||||
|
Player.PLAYBACK_SUPPRESSION_REASON_NONE);
|
||||||
session.getMockPlayer().notifyPlaybackStateChanged(STATE_READY);
|
session.getMockPlayer().notifyPlaybackStateChanged(STATE_READY);
|
||||||
|
|
||||||
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
assertThat(playingLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
||||||
assertThat(controllerCompat.getSessionActivity()).isEqualTo(sessionActivity);
|
assertThat(controllerCompat.getSessionActivity()).isEqualTo(sessionActivity);
|
||||||
|
|
||||||
|
session.setSessionActivity(/* controllerKey= */ null, null);
|
||||||
|
session.getMockPlayer().notifyPlaybackStateChanged(Player.STATE_BUFFERING);
|
||||||
|
|
||||||
|
assertThat(bufferingLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
||||||
|
assertThat(controllerCompat.getSessionActivity()).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation") // Testing access through deprecated androidx.media library
|
||||||
@Test
|
@Test
|
||||||
public void setSessionActivity_setToNotificationController_changedWhenReceivedWithSetter()
|
public void setSessionActivity_setToNotificationController_changedWhenReceivedWithSetter()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
@ -1251,24 +1270,41 @@ public class MediaControllerCompatCallbackWithMediaSessionTest {
|
|||||||
PendingIntent sessionActivity =
|
PendingIntent sessionActivity =
|
||||||
PendingIntent.getActivity(
|
PendingIntent.getActivity(
|
||||||
context, 0, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
|
context, 0, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
CountDownLatch latch = new CountDownLatch(1);
|
CountDownLatch playingLatch = new CountDownLatch(1);
|
||||||
|
CountDownLatch bufferingLatch = new CountDownLatch(1);
|
||||||
MediaControllerCompat.Callback callback =
|
MediaControllerCompat.Callback callback =
|
||||||
new MediaControllerCompat.Callback() {
|
new MediaControllerCompat.Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void onPlaybackStateChanged(PlaybackStateCompat state) {
|
public void onPlaybackStateChanged(PlaybackStateCompat state) {
|
||||||
latch.countDown();
|
if (state.getState() == PlaybackStateCompat.STATE_BUFFERING) {
|
||||||
|
bufferingLatch.countDown();
|
||||||
|
} else if (state.getState() == PlaybackStateCompat.STATE_PLAYING) {
|
||||||
|
playingLatch.countDown();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
controllerCompat.registerCallback(callback, handler);
|
controllerCompat.registerCallback(callback, handler);
|
||||||
assertThat(controllerCompat.getSessionActivity()).isNull();
|
assertThat(controllerCompat.getSessionActivity()).isNull();
|
||||||
|
|
||||||
session.setSessionActivity(NOTIFICATION_CONTROLLER_KEY, sessionActivity);
|
session.setSessionActivity(NOTIFICATION_CONTROLLER_KEY, sessionActivity);
|
||||||
|
session
|
||||||
|
.getMockPlayer()
|
||||||
|
.notifyPlayWhenReadyChanged(
|
||||||
|
true,
|
||||||
|
Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST,
|
||||||
|
Player.PLAYBACK_SUPPRESSION_REASON_NONE);
|
||||||
// The legacy API has no change listener for the session activity. Changing the state to
|
// The legacy API has no change listener for the session activity. Changing the state to
|
||||||
// trigger a callback.
|
// trigger a callback.
|
||||||
session.getMockPlayer().notifyPlaybackStateChanged(STATE_READY);
|
session.getMockPlayer().notifyPlaybackStateChanged(STATE_READY);
|
||||||
|
|
||||||
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
assertThat(playingLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
||||||
assertThat(controllerCompat.getSessionActivity()).isEqualTo(sessionActivity);
|
assertThat(controllerCompat.getSessionActivity()).isEqualTo(sessionActivity);
|
||||||
|
|
||||||
|
session.setSessionActivity(NOTIFICATION_CONTROLLER_KEY, null);
|
||||||
|
session.getMockPlayer().notifyPlaybackStateChanged(Player.STATE_BUFFERING);
|
||||||
|
|
||||||
|
assertThat(bufferingLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
||||||
|
assertThat(controllerCompat.getSessionActivity()).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -2566,14 +2566,19 @@ public class MediaControllerListenerTest {
|
|||||||
PendingIntent.getActivity(
|
PendingIntent.getActivity(
|
||||||
context, 0, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
|
context, 0, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
CountDownLatch latch = new CountDownLatch(1);
|
CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
CountDownLatch nullLatch = new CountDownLatch(1);
|
||||||
List<PendingIntent> receivedSessionActivities = new ArrayList<>();
|
List<PendingIntent> receivedSessionActivities = new ArrayList<>();
|
||||||
MediaController.Listener listener =
|
MediaController.Listener listener =
|
||||||
new MediaController.Listener() {
|
new MediaController.Listener() {
|
||||||
@Override
|
@Override
|
||||||
public void onSessionActivityChanged(
|
public void onSessionActivityChanged(
|
||||||
MediaController controller, PendingIntent sessionActivity) {
|
MediaController controller, @Nullable PendingIntent sessionActivity) {
|
||||||
receivedSessionActivities.add(sessionActivity);
|
if (sessionActivity == null) {
|
||||||
latch.countDown();
|
nullLatch.countDown();
|
||||||
|
} else {
|
||||||
|
receivedSessionActivities.add(sessionActivity);
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
MediaController controller =
|
MediaController controller =
|
||||||
@ -2586,6 +2591,13 @@ public class MediaControllerListenerTest {
|
|||||||
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
assertThat(latch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
||||||
assertThat(controller.getSessionActivity()).isEqualTo(sessionActivity);
|
assertThat(controller.getSessionActivity()).isEqualTo(sessionActivity);
|
||||||
assertThat(receivedSessionActivities).containsExactly(sessionActivity);
|
assertThat(receivedSessionActivities).containsExactly(sessionActivity);
|
||||||
|
|
||||||
|
remoteSession.setSessionActivity(/* controllerKey= */ null, sessionActivity);
|
||||||
|
remoteSession.setSessionActivity(/* controllerKey= */ null, null);
|
||||||
|
|
||||||
|
assertThat(nullLatch.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
||||||
|
assertThat(controller.getSessionActivity()).isNull();
|
||||||
|
assertThat(receivedSessionActivities).containsExactly(sessionActivity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -2601,7 +2613,7 @@ public class MediaControllerListenerTest {
|
|||||||
new MediaController.Listener() {
|
new MediaController.Listener() {
|
||||||
@Override
|
@Override
|
||||||
public void onSessionActivityChanged(
|
public void onSessionActivityChanged(
|
||||||
MediaController controller, PendingIntent sessionActivity) {
|
MediaController controller, @Nullable PendingIntent sessionActivity) {
|
||||||
receivedSessionActivities1.add(sessionActivity);
|
receivedSessionActivities1.add(sessionActivity);
|
||||||
latch1.countDown();
|
latch1.countDown();
|
||||||
}
|
}
|
||||||
@ -2610,15 +2622,17 @@ public class MediaControllerListenerTest {
|
|||||||
connectionHints1.putString(KEY_CONTROLLER, "ctrl-1");
|
connectionHints1.putString(KEY_CONTROLLER, "ctrl-1");
|
||||||
MediaController controller1 =
|
MediaController controller1 =
|
||||||
controllerTestRule.createController(remoteSession.getToken(), connectionHints1, listener1);
|
controllerTestRule.createController(remoteSession.getToken(), connectionHints1, listener1);
|
||||||
List<PendingIntent> receivedSessionActivities2 = new ArrayList<>();
|
AtomicInteger controller2CallbackCount = new AtomicInteger();
|
||||||
CountDownLatch latch2 = new CountDownLatch(1);
|
CountDownLatch latch2 = new CountDownLatch(1);
|
||||||
MediaController.Listener listener2 =
|
MediaController.Listener listener2 =
|
||||||
new MediaController.Listener() {
|
new MediaController.Listener() {
|
||||||
@Override
|
@Override
|
||||||
public void onSessionActivityChanged(
|
public void onSessionActivityChanged(
|
||||||
MediaController controller, PendingIntent sessionActivity) {
|
MediaController controller, @Nullable PendingIntent sessionActivity) {
|
||||||
receivedSessionActivities2.add(sessionActivity);
|
controller2CallbackCount.incrementAndGet();
|
||||||
latch2.countDown();
|
if (sessionActivity == null) {
|
||||||
|
latch2.countDown();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Bundle connectionHints2 = new Bundle();
|
Bundle connectionHints2 = new Bundle();
|
||||||
@ -2634,14 +2648,16 @@ public class MediaControllerListenerTest {
|
|||||||
assertThat(controller1.getSessionActivity()).isEqualTo(sessionActivity);
|
assertThat(controller1.getSessionActivity()).isEqualTo(sessionActivity);
|
||||||
assertThat(controller2.getSessionActivity()).isNull();
|
assertThat(controller2.getSessionActivity()).isNull();
|
||||||
assertThat(receivedSessionActivities1).containsExactly(sessionActivity);
|
assertThat(receivedSessionActivities1).containsExactly(sessionActivity);
|
||||||
assertThat(receivedSessionActivities2).isEmpty();
|
assertThat(controller2CallbackCount.get()).isEqualTo(0);
|
||||||
|
|
||||||
remoteSession.setSessionActivity(/* controllerKey= */ "ctrl-2", sessionActivity);
|
remoteSession.setSessionActivity(/* controllerKey= */ "ctrl-2", sessionActivity);
|
||||||
|
remoteSession.setSessionActivity(/* controllerKey= */ "ctrl-2", null);
|
||||||
|
|
||||||
assertThat(latch2.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
assertThat(latch2.await(TIMEOUT_MS, MILLISECONDS)).isTrue();
|
||||||
assertThat(controller2.getSessionActivity()).isEqualTo(sessionActivity);
|
assertThat(controller1.getSessionActivity()).isEqualTo(sessionActivity);
|
||||||
|
assertThat(controller2.getSessionActivity()).isNull();
|
||||||
assertThat(receivedSessionActivities1).containsExactly(sessionActivity);
|
assertThat(receivedSessionActivities1).containsExactly(sessionActivity);
|
||||||
assertThat(receivedSessionActivities2).containsExactly(sessionActivity);
|
assertThat(controller2CallbackCount.get()).isEqualTo(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -703,7 +703,7 @@ public class MediaSessionProviderService extends Service {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSessionActivity(
|
public void setSessionActivity(
|
||||||
String sessionId, @Nullable String controllerKey, PendingIntent sessionActivity)
|
String sessionId, @Nullable String controllerKey, @Nullable PendingIntent sessionActivity)
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
MediaSession mediaSession = sessionMap.get(sessionId);
|
MediaSession mediaSession = sessionMap.get(sessionId);
|
||||||
if (mediaSession == null) {
|
if (mediaSession == null) {
|
||||||
|
@ -218,7 +218,7 @@ public class RemoteMediaSession {
|
|||||||
binder.setSessionExtrasForController(sessionId, controllerKey, extras);
|
binder.setSessionExtrasForController(sessionId, controllerKey, extras);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSessionActivity(String controllerKey, PendingIntent sessionActivity)
|
public void setSessionActivity(String controllerKey, @Nullable PendingIntent sessionActivity)
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
binder.setSessionActivity(sessionId, controllerKey, sessionActivity);
|
binder.setSessionActivity(sessionId, controllerKey, sessionActivity);
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@ public class RemoteMediaSessionCompat {
|
|||||||
binder.setShuffleMode(sessionTag, shuffleMode);
|
binder.setShuffleMode(sessionTag, shuffleMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSessionActivity(PendingIntent intent) throws RemoteException {
|
public void setSessionActivity(@Nullable PendingIntent intent) throws RemoteException {
|
||||||
binder.setSessionActivity(sessionTag, intent);
|
binder.setSessionActivity(sessionTag, intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +79,8 @@ public final class TestMediaBrowserListener implements MediaBrowser.Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSessionActivityChanged(MediaController controller, PendingIntent sessionActivity) {
|
public void onSessionActivityChanged(
|
||||||
|
MediaController controller, @Nullable PendingIntent sessionActivity) {
|
||||||
delegate.onSessionActivityChanged(controller, sessionActivity);
|
delegate.onSessionActivityChanged(controller, sessionActivity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,6 +120,7 @@ public class FakeRenderer extends BaseRenderer {
|
|||||||
getIndex(),
|
getIndex(),
|
||||||
format,
|
format,
|
||||||
C.FORMAT_UNSUPPORTED_TYPE,
|
C.FORMAT_UNSUPPORTED_TYPE,
|
||||||
|
getMediaPeriodId(),
|
||||||
/* isRecoverable= */ false,
|
/* isRecoverable= */ false,
|
||||||
PlaybackException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
|
PlaybackException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import static androidx.media3.common.util.Util.usToMs;
|
|||||||
import static androidx.media3.transformer.AndroidTestUtil.JPG_ASSET;
|
import static androidx.media3.transformer.AndroidTestUtil.JPG_ASSET;
|
||||||
import static androidx.media3.transformer.AndroidTestUtil.MP4_ASSET;
|
import static androidx.media3.transformer.AndroidTestUtil.MP4_ASSET;
|
||||||
import static androidx.media3.transformer.AndroidTestUtil.assumeFormatsSupported;
|
import static androidx.media3.transformer.AndroidTestUtil.assumeFormatsSupported;
|
||||||
|
import static androidx.media3.transformer.AndroidTestUtil.recordTestSkipped;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||||
import static org.junit.Assert.assertThrows;
|
import static org.junit.Assert.assertThrows;
|
||||||
@ -44,6 +45,7 @@ import java.nio.ByteBuffer;
|
|||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
import org.junit.AssumptionViolatedException;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@ -69,6 +71,30 @@ public class EditingMetricsCollectorTest {
|
|||||||
testId = testName.getMethodName();
|
testId = testName.getMethodName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void export_usePlatformDiagnosticsDisabled_doesNotCollectMetrics() throws Exception {
|
||||||
|
if (Util.SDK_INT < 35) {
|
||||||
|
String reason = "Metrics collection is unsupported below API 35.";
|
||||||
|
recordTestSkipped(context, testId, reason);
|
||||||
|
throw new AssumptionViolatedException(reason);
|
||||||
|
}
|
||||||
|
AtomicReference<EditingEndedEvent> editingEndedEventAtomicReference = new AtomicReference<>();
|
||||||
|
Transformer transformer =
|
||||||
|
new Transformer.Builder(context)
|
||||||
|
.setUsePlatformDiagnostics(false)
|
||||||
|
.setMetricsReporterFactory(
|
||||||
|
new TestMetricsReporterFactory(context, editingEndedEventAtomicReference::set))
|
||||||
|
.build();
|
||||||
|
EditedMediaItem audioVideoItem =
|
||||||
|
new EditedMediaItem.Builder(MediaItem.fromUri(MP4_ASSET.uri)).build();
|
||||||
|
|
||||||
|
new TransformerAndroidTestRunner.Builder(context, transformer)
|
||||||
|
.build()
|
||||||
|
.run(testId, audioVideoItem);
|
||||||
|
|
||||||
|
assertThat(editingEndedEventAtomicReference.get()).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void exportSuccess_populatesEditingEndedEvent() throws Exception {
|
public void exportSuccess_populatesEditingEndedEvent() throws Exception {
|
||||||
assumeTrue("Reporting metrics requires API 35", Util.SDK_INT >= 35);
|
assumeTrue("Reporting metrics requires API 35", Util.SDK_INT >= 35);
|
||||||
|
@ -48,7 +48,7 @@ class RepeatButtonStateTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun buttonClicked_withLimitedNumberOfModes_playerShuffleModeChangedToNextInSequence() {
|
fun buttonClicked_withLimitedNumberOfModes_playerRepeatModeChangedToNextInSequence() {
|
||||||
val player = TestPlayer()
|
val player = TestPlayer()
|
||||||
val state = RepeatButtonState(player, listOf(Player.REPEAT_MODE_OFF, Player.REPEAT_MODE_ONE))
|
val state = RepeatButtonState(player, listOf(Player.REPEAT_MODE_OFF, Player.REPEAT_MODE_ONE))
|
||||||
assertThat(state.repeatModeState).isEqualTo(Player.REPEAT_MODE_OFF)
|
assertThat(state.repeatModeState).isEqualTo(Player.REPEAT_MODE_OFF)
|
||||||
|
@ -60,9 +60,9 @@ class ShuffleButtonStateTest {
|
|||||||
@Test
|
@Test
|
||||||
fun playerSetShuffleModeAndOnClick_inTheSameHandlerMessage_uiStateSynchronises() {
|
fun playerSetShuffleModeAndOnClick_inTheSameHandlerMessage_uiStateSynchronises() {
|
||||||
// The UDF model of Compose relies on holding the Player as the single source of truth with
|
// The UDF model of Compose relies on holding the Player as the single source of truth with
|
||||||
// RepeatButtonState changing its state in sync with the relevant Player events. This means that
|
// ShuffleButtonState changing its state in sync with the relevant Player events. This means
|
||||||
// we should never find ourselves in a situation where a button's icon (here: determined by
|
// that we should never find ourselves in a situation where a button's icon (here: determined by
|
||||||
// RepeatButtonState.repeatModeState) is out of sync with the Player's repeat mode. It can cause
|
// ShuffleButtonState.shuffleOn) is out of sync with the Player's shuffle mode. It can cause
|
||||||
// confusion for a human user whose intent to toggle the mode will not be fulfilled. The
|
// confusion for a human user whose intent to toggle the mode will not be fulfilled. The
|
||||||
// following test tries to simulate this scenario by squeezing the 2 actions together (setter +
|
// following test tries to simulate this scenario by squeezing the 2 actions together (setter +
|
||||||
// onClick) into a single Looper iteration. This is a practically unlikely scenario for a human
|
// onClick) into a single Looper iteration. This is a practically unlikely scenario for a human
|
||||||
|
@ -62,4 +62,3 @@ afterEvaluate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tasks.withType(PublishToMavenRepository) { it.dependsOn lint, test }
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user