Skip to content

Commit

Permalink
Exclude tracks from PlayerInfo if not changed
Browse files Browse the repository at this point in the history
This change includes a change in the `IMediaController.aidl` file and needs
to provide backwards compatibility for when a client connects that is of an older or
newer version of the current service implementation.

This CL proposes to create a new AIDL method `onPlayerInfoChangedWithExtensions`
that is easier to extend in the future because it does use an `Bundle` rather than
primitives. A `Bundle` can be changed in a backward/forwards compatible way
in case we need further changes.

The compatibility handling is provided in `MediaSessionStub` and `MediaControllerStub`. The approach is not based on specific AIDL/Binder features but implemented fully in application code.

Issue: androidx/media#102
#minor-release
PiperOrigin-RevId: 490483068
  • Loading branch information
marcbaechinger authored and icbaker committed Nov 24, 2022
1 parent 10fac68 commit 3d8c52f
Show file tree
Hide file tree
Showing 11 changed files with 396 additions and 131 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,8 @@ default void onTimelineChanged(Timeline timeline, @TimelineChangeReason int reas
* to the current {@link #getRepeatMode() repeat mode}.
*
* <p>Note that this callback is also called when the playlist becomes non-empty or empty as a
* consequence of a playlist change.
* consequence of a playlist change or {@linkplain #onAvailableCommandsChanged(Commands) a
* change in available commands}.
*
* <p>{@link #onEvents(Player, Events)} will also be called to report this event along with
* other events that happen in the same {@link Looper} message queue iteration.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,19 @@ oneway interface IMediaController {
void onSetCustomLayout(int seq, in List<Bundle> commandButtonList) = 3003;
void onCustomCommand(int seq, in Bundle command, in Bundle args) = 3004;
void onDisconnected(int seq) = 3005;
void onPlayerInfoChanged(int seq, in Bundle playerInfoBundle, boolean isTimelineExcluded) = 3006;
/** Deprecated: Use onPlayerInfoChangedWithExclusions from MediaControllerStub#VERSION_INT=2. */
void onPlayerInfoChanged(
int seq, in Bundle playerInfoBundle, boolean isTimelineExcluded) = 3006;
/** Introduced to deprecate onPlayerInfoChanged (from MediaControllerStub#VERSION_INT=2). */
void onPlayerInfoChangedWithExclusions(
int seq, in Bundle playerInfoBundle, in Bundle playerInfoExclusions) = 3012;
void onPeriodicSessionPositionInfoChanged(int seq, in Bundle sessionPositionInfo) = 3007;
void onAvailableCommandsChangedFromPlayer(int seq, in Bundle commandsBundle) = 3008;
void onAvailableCommandsChangedFromSession(
int seq, in Bundle sessionCommandsBundle, in Bundle playerCommandsBundle) = 3009;
void onRenderedFirstFrame(int seq) = 3010;
void onExtrasChanged(int seq, in Bundle extras) = 3011;
// Next Id for MediaController: 3012
// Next Id for MediaController: 3013

void onChildrenChanged(
int seq, String parentId, int itemCount, in @nullable Bundle libraryParams) = 4000;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import static androidx.media3.common.util.Util.usToMs;
import static androidx.media3.session.MediaUtils.calculateBufferedPercentage;
import static androidx.media3.session.MediaUtils.intersect;
import static androidx.media3.session.MediaUtils.mergePlayerInfo;
import static java.lang.Math.max;
import static java.lang.Math.min;

Expand All @@ -42,6 +43,7 @@
import android.os.RemoteException;
import android.os.SystemClock;
import android.support.v4.media.MediaBrowserCompat;
import android.util.Pair;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
Expand Down Expand Up @@ -79,6 +81,7 @@
import androidx.media3.common.util.Size;
import androidx.media3.common.util.Util;
import androidx.media3.session.MediaController.MediaControllerImpl;
import androidx.media3.session.PlayerInfo.BundlingExclusions;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
Expand Down Expand Up @@ -129,7 +132,8 @@
@Nullable private IMediaSession iSession;
private long lastReturnedCurrentPositionMs;
private long lastSetPlayWhenReadyCalledTimeMs;
@Nullable private Timeline pendingPlayerInfoUpdateTimeline;
@Nullable private PlayerInfo pendingPlayerInfo;
@Nullable private BundlingExclusions pendingBundlingExclusions;

public MediaControllerImplBase(
Context context,
Expand Down Expand Up @@ -2329,30 +2333,41 @@ void onCustomCommand(int seq, SessionCommand command, Bundle args) {
}

@SuppressWarnings("deprecation") // Implementing and calling deprecated listener method.
void onPlayerInfoChanged(PlayerInfo newPlayerInfo, boolean isTimelineExcluded) {
void onPlayerInfoChanged(PlayerInfo newPlayerInfo, BundlingExclusions bundlingExclusions) {
if (!isConnected()) {
return;
}
if (pendingPlayerInfo != null && pendingBundlingExclusions != null) {
Pair<PlayerInfo, BundlingExclusions> mergedPlayerInfoUpdate =
mergePlayerInfo(
pendingPlayerInfo,
pendingBundlingExclusions,
newPlayerInfo,
bundlingExclusions,
intersectedPlayerCommands);
newPlayerInfo = mergedPlayerInfoUpdate.first;
bundlingExclusions = mergedPlayerInfoUpdate.second;
}
pendingPlayerInfo = null;
pendingBundlingExclusions = null;
if (!pendingMaskingSequencedFutureNumbers.isEmpty()) {
// We are still waiting for all pending masking operations to be handled.
if (!isTimelineExcluded) {
pendingPlayerInfoUpdateTimeline = newPlayerInfo.timeline;
}
pendingPlayerInfo = newPlayerInfo;
pendingBundlingExclusions = bundlingExclusions;
return;
}
PlayerInfo oldPlayerInfo = playerInfo;
if (isTimelineExcluded) {
newPlayerInfo =
newPlayerInfo.copyWithTimeline(
pendingPlayerInfoUpdateTimeline != null
? pendingPlayerInfoUpdateTimeline
: oldPlayerInfo.timeline);
}
// Assigning class variable now so that all getters called from listeners see the updated value.
// But we need to use a local final variable to ensure listeners get consistent parameters.
playerInfo = newPlayerInfo;
PlayerInfo finalPlayerInfo = newPlayerInfo;
pendingPlayerInfoUpdateTimeline = null;
playerInfo =
mergePlayerInfo(
oldPlayerInfo,
/* oldBundlingExclusions= */ BundlingExclusions.NONE,
newPlayerInfo,
/* newBundlingExclusions= */ bundlingExclusions,
intersectedPlayerCommands)
.first;
PlayerInfo finalPlayerInfo = playerInfo;
PlaybackException oldPlayerError = oldPlayerInfo.playerError;
PlaybackException playerError = finalPlayerInfo.playerError;
boolean errorsMatch =
Expand Down Expand Up @@ -2397,7 +2412,7 @@ void onPlayerInfoChanged(PlayerInfo newPlayerInfo, boolean isTimelineExcluded) {
/* eventFlag= */ Player.EVENT_SHUFFLE_MODE_ENABLED_CHANGED,
listener -> listener.onShuffleModeEnabledChanged(finalPlayerInfo.shuffleModeEnabled));
}
if (!isTimelineExcluded && !Util.areEqual(oldPlayerInfo.timeline, finalPlayerInfo.timeline)) {
if (!Util.areEqual(oldPlayerInfo.timeline, finalPlayerInfo.timeline)) {
listeners.queueEvent(
/* eventFlag= */ Player.EVENT_TIMELINE_CHANGED,
listener ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import androidx.media3.common.util.BundleableUtil;
import androidx.media3.common.util.Log;
import androidx.media3.session.MediaLibraryService.LibraryParams;
import androidx.media3.session.PlayerInfo.BundlingExclusions;
import java.lang.ref.WeakReference;
import java.util.List;
import org.checkerframework.checker.nullness.qual.NonNull;
Expand All @@ -35,7 +36,7 @@
private static final String TAG = "MediaControllerStub";

/** The version of the IMediaController interface. */
public static final int VERSION_INT = 1;
public static final int VERSION_INT = 2;

private final WeakReference<MediaControllerImplBase> controller;

Expand Down Expand Up @@ -169,17 +170,39 @@ public void onPeriodicSessionPositionInfoChanged(int seq, Bundle sessionPosition
controller -> controller.notifyPeriodicSessionPositionInfoChanged(sessionPositionInfo));
}

/**
* @deprecated Use {@link #onPlayerInfoChangedWithExclusions} from {@link #VERSION_INT} 2.
*/
@Override
@Deprecated
public void onPlayerInfoChanged(int seq, Bundle playerInfoBundle, boolean isTimelineExcluded) {
onPlayerInfoChangedWithExclusions(
seq,
playerInfoBundle,
new BundlingExclusions(isTimelineExcluded, /* areCurrentTracksExcluded= */ true)
.toBundle());
}

/** Added in {@link #VERSION_INT} 2. */
@Override
public void onPlayerInfoChangedWithExclusions(
int seq, Bundle playerInfoBundle, Bundle playerInfoExclusions) {
PlayerInfo playerInfo;
try {
playerInfo = PlayerInfo.CREATOR.fromBundle(playerInfoBundle);
} catch (RuntimeException e) {
Log.w(TAG, "Ignoring malformed Bundle for PlayerInfo", e);
return;
}
BundlingExclusions bundlingExclusions;
try {
bundlingExclusions = BundlingExclusions.CREATOR.fromBundle(playerInfoExclusions);
} catch (RuntimeException e) {
Log.w(TAG, "Ignoring malformed Bundle for BundlingExclusions", e);
return;
}
dispatchControllerTaskOnHandler(
controller -> controller.onPlayerInfoChanged(playerInfo, isTimelineExcluded));
controller -> controller.onPlayerInfoChanged(playerInfo, bundlingExclusions));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1136,7 +1136,8 @@ default void onPlayerInfoChanged(
boolean excludeMediaItemsMetadata,
boolean excludeCues,
boolean excludeTimeline,
boolean excludeTracks)
boolean excludeTracks,
int controllerInterfaceVersion)
throws RemoteException {}

default void onPeriodicSessionPositionInfoChanged(
Expand Down
Loading

0 comments on commit 3d8c52f

Please sign in to comment.