Skip to content

Commit

Permalink
Add MediaSession.Builder().setPeriodicPositionUpdateEnabled()
Browse files Browse the repository at this point in the history
This allows to disable periodic position updates when building
the session.

#minor-release

PiperOrigin-RevId: 572531837
  • Loading branch information
marcbaechinger authored and copybara-github committed Oct 11, 2023
1 parent 164e658 commit 4dc3db4
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,20 @@ public Builder setShowPlayButtonIfPlaybackIsSuppressed(
return super.setShowPlayButtonIfPlaybackIsSuppressed(showPlayButtonIfPlaybackIsSuppressed);
}

/**
* Sets whether periodic position updates should be sent to controllers while playing. If
* false, no periodic position updates are sent to controllers.
*
* <p>The default is {@code true}.
*
* @param isEnabled Whether periodic position update is enabled.
*/
@UnstableApi
@Override
public Builder setPeriodicPositionUpdateEnabled(boolean isEnabled) {
return super.setPeriodicPositionUpdateEnabled(isEnabled);
}

/**
* Builds a {@link MediaLibrarySession}.
*
Expand All @@ -539,7 +553,8 @@ public MediaLibrarySession build() {
callback,
extras,
checkNotNull(bitmapLoader),
playIfSuppressed);
playIfSuppressed,
isPeriodicPositionUpdateEnabled);
}
}

Expand All @@ -552,7 +567,8 @@ public MediaLibrarySession build() {
MediaSession.Callback callback,
Bundle tokenExtras,
BitmapLoader bitmapLoader,
boolean playIfSuppressed) {
boolean playIfSuppressed,
boolean isPeriodicPositionUpdateEnabled) {
super(
context,
id,
Expand All @@ -562,7 +578,8 @@ public MediaLibrarySession build() {
callback,
tokenExtras,
bitmapLoader,
playIfSuppressed);
playIfSuppressed,
isPeriodicPositionUpdateEnabled);
}

@Override
Expand All @@ -575,7 +592,8 @@ public MediaLibrarySession build() {
MediaSession.Callback callback,
Bundle tokenExtras,
BitmapLoader bitmapLoader,
boolean playIfSuppressed) {
boolean playIfSuppressed,
boolean isPeriodicPositionUpdateEnabled) {
return new MediaLibrarySessionImpl(
this,
context,
Expand All @@ -586,7 +604,8 @@ public MediaLibrarySession build() {
(Callback) callback,
tokenExtras,
bitmapLoader,
playIfSuppressed);
playIfSuppressed,
isPeriodicPositionUpdateEnabled);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ public MediaLibrarySessionImpl(
MediaLibrarySession.Callback callback,
Bundle tokenExtras,
BitmapLoader bitmapLoader,
boolean playIfSuppressed) {
boolean playIfSuppressed,
boolean isPeriodicPositionUpdateEnabled) {
super(
instance,
context,
Expand All @@ -86,7 +87,8 @@ public MediaLibrarySessionImpl(
callback,
tokenExtras,
bitmapLoader,
playIfSuppressed);
playIfSuppressed,
isPeriodicPositionUpdateEnabled);
this.instance = instance;
this.callback = callback;
parentIdToSubscribedControllers = HashMultimap.create();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,20 @@ public Builder setCustomLayout(List<CommandButton> customLayout) {
return super.setCustomLayout(customLayout);
}

/**
* Sets whether periodic position updates should be sent to controllers while playing. If false,
* no periodic position updates are sent to controllers.
*
* <p>The default is {@code true}.
*
* @param isEnabled Whether periodic position update is enabled.
*/
@UnstableApi
@Override
public Builder setPeriodicPositionUpdateEnabled(boolean isEnabled) {
return super.setPeriodicPositionUpdateEnabled(isEnabled);
}

/**
* Sets whether a play button is shown if playback is {@linkplain
* Player#getPlaybackSuppressionReason() suppressed}.
Expand Down Expand Up @@ -413,7 +427,8 @@ public MediaSession build() {
callback,
extras,
checkNotNull(bitmapLoader),
playIfSuppressed);
playIfSuppressed,
isPeriodicPositionUpdateEnabled);
}
}

Expand Down Expand Up @@ -606,7 +621,8 @@ public static ControllerInfo createTestOnlyControllerInfo(
Callback callback,
Bundle tokenExtras,
BitmapLoader bitmapLoader,
boolean playIfSuppressed) {
boolean playIfSuppressed,
boolean isPeriodicPositionUpdateEnabled) {
synchronized (STATIC_LOCK) {
if (SESSION_ID_TO_SESSION_MAP.containsKey(id)) {
throw new IllegalStateException("Session ID must be unique. ID=" + id);
Expand All @@ -623,7 +639,8 @@ public static ControllerInfo createTestOnlyControllerInfo(
callback,
tokenExtras,
bitmapLoader,
playIfSuppressed);
playIfSuppressed,
isPeriodicPositionUpdateEnabled);
}

/* package */ MediaSessionImpl createImpl(
Expand All @@ -635,7 +652,8 @@ public static ControllerInfo createTestOnlyControllerInfo(
Callback callback,
Bundle tokenExtras,
BitmapLoader bitmapLoader,
boolean playIfSuppressed) {
boolean playIfSuppressed,
boolean isPeriodicPositionUpdateEnabled) {
return new MediaSessionImpl(
this,
context,
Expand All @@ -646,7 +664,8 @@ public static ControllerInfo createTestOnlyControllerInfo(
callback,
tokenExtras,
bitmapLoader,
playIfSuppressed);
playIfSuppressed,
isPeriodicPositionUpdateEnabled);
}

/* package */ MediaSessionImpl getImpl() {
Expand Down Expand Up @@ -1798,8 +1817,8 @@ default void onRenderedFirstFrame(int seq) throws RemoteException {}
/* package */ Bundle extras;
/* package */ @MonotonicNonNull BitmapLoader bitmapLoader;
/* package */ boolean playIfSuppressed;

/* package */ ImmutableList<CommandButton> customLayout;
/* package */ boolean isPeriodicPositionUpdateEnabled;

public BuilderBase(Context context, Player player, CallbackT callback) {
this.context = checkNotNull(context);
Expand All @@ -1810,6 +1829,7 @@ public BuilderBase(Context context, Player player, CallbackT callback) {
extras = Bundle.EMPTY;
customLayout = ImmutableList.of();
playIfSuppressed = true;
isPeriodicPositionUpdateEnabled = true;
}

@SuppressWarnings("unchecked")
Expand Down Expand Up @@ -1855,6 +1875,12 @@ public BuilderT setShowPlayButtonIfPlaybackIsSuppressed(
return (BuilderT) this;
}

@SuppressWarnings("unchecked")
public BuilderT setPeriodicPositionUpdateEnabled(boolean isPeriodicPositionUpdateEnabled) {
this.isPeriodicPositionUpdateEnabled = isPeriodicPositionUpdateEnabled;
return (BuilderT) this;
}

public abstract SessionT build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@
private final Runnable periodicSessionPositionInfoUpdateRunnable;
private final Handler mainHandler;
private final boolean playIfSuppressed;
private final boolean isPeriodicPositionUpdateEnabled;

private PlayerInfo playerInfo;
private PlayerWrapper playerWrapper;
Expand Down Expand Up @@ -148,7 +149,8 @@ public MediaSessionImpl(
MediaSession.Callback callback,
Bundle tokenExtras,
BitmapLoader bitmapLoader,
boolean playIfSuppressed) {
boolean playIfSuppressed,
boolean isPeriodicPositionUpdateEnabled) {
this.context = context;
this.instance = instance;

Expand All @@ -166,6 +168,7 @@ public MediaSessionImpl(
this.callback = callback;
this.bitmapLoader = bitmapLoader;
this.playIfSuppressed = playIfSuppressed;
this.isPeriodicPositionUpdateEnabled = isPeriodicPositionUpdateEnabled;

playerInfo = PlayerInfo.DEFAULT;
onPlayerInfoChangedHandler = new PlayerInfoChangedHandler(player.getApplicationLooper());
Expand Down Expand Up @@ -1053,7 +1056,8 @@ private void notifyPeriodicSessionPositionInfoChangesOnHandler() {

private void schedulePeriodicSessionPositionInfoChanges() {
applicationHandler.removeCallbacks(periodicSessionPositionInfoUpdateRunnable);
if (sessionPositionUpdateDelayMs > 0
if (isPeriodicPositionUpdateEnabled
&& sessionPositionUpdateDelayMs > 0
&& (playerWrapper.isPlaying() || playerWrapper.isLoading())) {
applicationHandler.postDelayed(
periodicSessionPositionInfoUpdateRunnable, sessionPositionUpdateDelayMs);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import android.text.TextUtils;
import androidx.media.MediaSessionManager;
import androidx.media3.common.MediaLibraryInfo;
import androidx.media3.common.Player;
import androidx.media3.common.util.Log;
import androidx.media3.common.util.Util;
import androidx.media3.test.session.common.HandlerThreadTestRule;
Expand All @@ -41,6 +42,8 @@
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
Expand Down Expand Up @@ -433,4 +436,62 @@ public MediaSession.ConnectionResult onConnect(
// version of remote controller.
assertThat(controllerVersionRef.get()).isEqualTo(MediaLibraryInfo.VERSION_INT);
}

@Test
public void setPeriodicPositionUpdateEnabled_periodicUpdatesEnabled_bufferedPositionMsUpdated()
throws Exception {
player.playWhenReady = true;
player.playbackState = Player.STATE_READY;
MediaSession session =
sessionTestRule.ensureReleaseAfterTest(
new MediaSession.Builder(context, player)
.setPeriodicPositionUpdateEnabled(true)
.setId(
"setPeriodicPositionUpdateEnabled_periodicUpdatesEnabled_bufferedPositionMsUpdated")
.build());
threadTestRule.getHandler().postAndSync(() -> session.setSessionPositionUpdateDelayMs(10L));
MediaController controller =
new MediaController.Builder(ApplicationProvider.getApplicationContext(), session.getToken())
.buildAsync()
.get();
List<Long> bufferedPositionsMs = new ArrayList<>();
TestHandler testHandler = new TestHandler(controller.getApplicationLooper());

for (long bufferedPositionMs = 0; bufferedPositionMs < 5000; bufferedPositionMs += 1000) {
player.bufferedPosition = bufferedPositionMs;
Thread.sleep(50L);
bufferedPositionsMs.add(testHandler.postAndSync(controller::getBufferedPosition));
}

assertThat(bufferedPositionsMs).containsExactly(0L, 1000L, 2000L, 3000L, 4000L).inOrder();
}

@Test
public void setPeriodicPositionUpdateEnabled_periodicUpdatesDisabled_bufferedPositionMsUnchanged()
throws Exception {
player.playWhenReady = true;
player.playbackState = Player.STATE_READY;
MediaSession session =
sessionTestRule.ensureReleaseAfterTest(
new MediaSession.Builder(context, player)
.setPeriodicPositionUpdateEnabled(false)
.setId(
"setPeriodicPositionUpdateEnabled_periodicUpdatesDisabled_bufferedPositionMsUnchanged")
.build());
threadTestRule.getHandler().postAndSync(() -> session.setSessionPositionUpdateDelayMs(10L));
MediaController controller =
new MediaController.Builder(ApplicationProvider.getApplicationContext(), session.getToken())
.buildAsync()
.get();
List<Long> bufferedPositionsMs = new ArrayList<>();
TestHandler testHandler = new TestHandler(controller.getApplicationLooper());

for (long bufferedPositionMs = 0; bufferedPositionMs < 5000; bufferedPositionMs += 1000) {
player.bufferedPosition = bufferedPositionMs;
Thread.sleep(50L);
bufferedPositionsMs.add(testHandler.postAndSync(controller::getBufferedPosition));
}

assertThat(bufferedPositionsMs).containsExactly(0L, 0L, 0L, 0L, 0L).inOrder();
}
}

0 comments on commit 4dc3db4

Please sign in to comment.