Skip to content

Commit e2ece2f

Browse files
toniheichristosts
authored andcommitted
Add missing command checks in UI module
The commands are partly checked already before enabling features or calling player methods, but the checks were still missing in many places. #minor-release PiperOrigin-RevId: 504589888
1 parent e8ffc7b commit e2ece2f

File tree

6 files changed

+208
-68
lines changed

6 files changed

+208
-68
lines changed

libraries/ui/src/main/java/androidx/media3/ui/DefaultMediaDescriptionAdapter.java

+11
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package androidx.media3.ui;
1717

18+
import static androidx.media3.common.Player.COMMAND_GET_MEDIA_ITEMS_METADATA;
19+
1820
import android.app.PendingIntent;
1921
import android.graphics.Bitmap;
2022
import android.graphics.BitmapFactory;
@@ -48,6 +50,9 @@ public DefaultMediaDescriptionAdapter(@Nullable PendingIntent pendingIntent) {
4850

4951
@Override
5052
public CharSequence getCurrentContentTitle(Player player) {
53+
if (!player.isCommandAvailable(COMMAND_GET_MEDIA_ITEMS_METADATA)) {
54+
return "";
55+
}
5156
@Nullable CharSequence displayTitle = player.getMediaMetadata().displayTitle;
5257
if (!TextUtils.isEmpty(displayTitle)) {
5358
return displayTitle;
@@ -66,6 +71,9 @@ public PendingIntent createCurrentContentIntent(Player player) {
6671
@Nullable
6772
@Override
6873
public CharSequence getCurrentContentText(Player player) {
74+
if (!player.isCommandAvailable(COMMAND_GET_MEDIA_ITEMS_METADATA)) {
75+
return null;
76+
}
6977
@Nullable CharSequence artist = player.getMediaMetadata().artist;
7078
if (!TextUtils.isEmpty(artist)) {
7179
return artist;
@@ -77,6 +85,9 @@ public CharSequence getCurrentContentText(Player player) {
7785
@Nullable
7886
@Override
7987
public Bitmap getCurrentLargeIcon(Player player, BitmapCallback callback) {
88+
if (!player.isCommandAvailable(COMMAND_GET_MEDIA_ITEMS_METADATA)) {
89+
return null;
90+
}
8091
@Nullable byte[] data = player.getMediaMetadata().artworkData;
8192
if (data == null) {
8293
return null;

libraries/ui/src/main/java/androidx/media3/ui/PlayerControlView.java

+94-43
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,22 @@
1515
*/
1616
package androidx.media3.ui;
1717

18+
import static androidx.media3.common.Player.COMMAND_GET_CURRENT_MEDIA_ITEM;
19+
import static androidx.media3.common.Player.COMMAND_GET_TIMELINE;
20+
import static androidx.media3.common.Player.COMMAND_GET_TRACKS;
21+
import static androidx.media3.common.Player.COMMAND_PLAY_PAUSE;
22+
import static androidx.media3.common.Player.COMMAND_PREPARE;
1823
import static androidx.media3.common.Player.COMMAND_SEEK_BACK;
1924
import static androidx.media3.common.Player.COMMAND_SEEK_FORWARD;
2025
import static androidx.media3.common.Player.COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM;
26+
import static androidx.media3.common.Player.COMMAND_SEEK_TO_DEFAULT_POSITION;
27+
import static androidx.media3.common.Player.COMMAND_SEEK_TO_MEDIA_ITEM;
2128
import static androidx.media3.common.Player.COMMAND_SEEK_TO_NEXT;
2229
import static androidx.media3.common.Player.COMMAND_SEEK_TO_PREVIOUS;
30+
import static androidx.media3.common.Player.COMMAND_SET_REPEAT_MODE;
31+
import static androidx.media3.common.Player.COMMAND_SET_SHUFFLE_MODE;
32+
import static androidx.media3.common.Player.COMMAND_SET_SPEED_AND_PITCH;
33+
import static androidx.media3.common.Player.COMMAND_SET_TRACK_SELECTION_PARAMETERS;
2334
import static androidx.media3.common.Player.EVENT_AVAILABLE_COMMANDS_CHANGED;
2435
import static androidx.media3.common.Player.EVENT_IS_PLAYING_CHANGED;
2536
import static androidx.media3.common.Player.EVENT_PLAYBACK_PARAMETERS_CHANGED;
@@ -35,6 +46,7 @@
3546
import static androidx.media3.common.util.Assertions.checkNotNull;
3647
import static androidx.media3.common.util.Util.castNonNull;
3748
import static androidx.media3.common.util.Util.getDrawable;
49+
import static androidx.media3.common.util.Util.msToUs;
3850

3951
import android.annotation.SuppressLint;
4052
import android.content.Context;
@@ -798,7 +810,7 @@ public void setShowTimeoutMs(int showTimeoutMs) {
798810
*/
799811
public void setRepeatToggleModes(@RepeatModeUtil.RepeatToggleModes int repeatToggleModes) {
800812
this.repeatToggleModes = repeatToggleModes;
801-
if (player != null) {
813+
if (player != null && player.isCommandAvailable(COMMAND_SET_REPEAT_MODE)) {
802814
@Player.RepeatMode int currentMode = player.getRepeatMode();
803815
if (repeatToggleModes == RepeatModeUtil.REPEAT_TOGGLE_MODE_NONE
804816
&& currentMode != Player.REPEAT_MODE_OFF) {
@@ -1062,7 +1074,7 @@ private void updateRepeatModeButton() {
10621074
}
10631075

10641076
@Nullable Player player = this.player;
1065-
if (player == null) {
1077+
if (player == null || !player.isCommandAvailable(COMMAND_SET_REPEAT_MODE)) {
10661078
updateButton(/* enabled= */ false, repeatToggleButton);
10671079
repeatToggleButton.setImageDrawable(repeatOffButtonDrawable);
10681080
repeatToggleButton.setContentDescription(repeatOffButtonContentDescription);
@@ -1096,7 +1108,7 @@ private void updateShuffleButton() {
10961108
@Nullable Player player = this.player;
10971109
if (!controlViewLayoutManager.getShowButton(shuffleButton)) {
10981110
updateButton(/* enabled= */ false, shuffleButton);
1099-
} else if (player == null) {
1111+
} else if (player == null || !player.isCommandAvailable(COMMAND_SET_SHUFFLE_MODE)) {
11001112
updateButton(/* enabled= */ false, shuffleButton);
11011113
shuffleButton.setImageDrawable(shuffleOffButtonDrawable);
11021114
shuffleButton.setContentDescription(shuffleOffContentDescription);
@@ -1120,8 +1132,8 @@ private void initTrackSelectionAdapter() {
11201132
textTrackSelectionAdapter.clear();
11211133
audioTrackSelectionAdapter.clear();
11221134
if (player == null
1123-
|| !player.isCommandAvailable(Player.COMMAND_GET_TRACKS)
1124-
|| !player.isCommandAvailable(Player.COMMAND_SET_TRACK_SELECTION_PARAMETERS)) {
1135+
|| !player.isCommandAvailable(COMMAND_GET_TRACKS)
1136+
|| !player.isCommandAvailable(COMMAND_SET_TRACK_SELECTION_PARAMETERS)) {
11251137
return;
11261138
}
11271139
Tracks tracks = player.getCurrentTracks();
@@ -1162,12 +1174,14 @@ private void updateTimeline() {
11621174
if (player == null) {
11631175
return;
11641176
}
1165-
multiWindowTimeBar =
1166-
showMultiWindowTimeBar && canShowMultiWindowTimeBar(player.getCurrentTimeline(), window);
1177+
multiWindowTimeBar = showMultiWindowTimeBar && canShowMultiWindowTimeBar(player, window);
11671178
currentWindowOffset = 0;
11681179
long durationUs = 0;
11691180
int adGroupCount = 0;
1170-
Timeline timeline = player.getCurrentTimeline();
1181+
Timeline timeline =
1182+
player.isCommandAvailable(COMMAND_GET_TIMELINE)
1183+
? player.getCurrentTimeline()
1184+
: Timeline.EMPTY;
11711185
if (!timeline.isEmpty()) {
11721186
int currentWindowIndex = player.getCurrentMediaItemIndex();
11731187
int firstWindowIndex = multiWindowTimeBar ? 0 : currentWindowIndex;
@@ -1209,6 +1223,11 @@ private void updateTimeline() {
12091223
}
12101224
durationUs += window.durationUs;
12111225
}
1226+
} else if (player.isCommandAvailable(COMMAND_GET_CURRENT_MEDIA_ITEM)) {
1227+
long playerDurationMs = player.getContentDuration();
1228+
if (playerDurationMs != C.TIME_UNSET) {
1229+
durationUs = msToUs(playerDurationMs);
1230+
}
12121231
}
12131232
long durationMs = Util.usToMs(durationUs);
12141233
if (durationView != null) {
@@ -1236,7 +1255,7 @@ private void updateProgress() {
12361255
@Nullable Player player = this.player;
12371256
long position = 0;
12381257
long bufferedPosition = 0;
1239-
if (player != null) {
1258+
if (player != null && player.isCommandAvailable(COMMAND_GET_CURRENT_MEDIA_ITEM)) {
12401259
position = currentWindowOffset + player.getContentPosition();
12411260
bufferedPosition = currentWindowOffset + player.getContentBufferedPosition();
12421261
}
@@ -1314,7 +1333,7 @@ private void displaySettingsWindow(RecyclerView.Adapter<?> adapter, View anchorV
13141333
}
13151334

13161335
private void setPlaybackSpeed(float speed) {
1317-
if (player == null) {
1336+
if (player == null || !player.isCommandAvailable(COMMAND_SET_SPEED_AND_PITCH)) {
13181337
return;
13191338
}
13201339
player.setPlaybackParameters(player.getPlaybackParameters().withSpeed(speed));
@@ -1335,11 +1354,12 @@ private void updateButton(boolean enabled, @Nullable View view) {
13351354
}
13361355

13371356
private void seekToTimeBarPosition(Player player, long positionMs) {
1338-
int windowIndex;
1339-
Timeline timeline = player.getCurrentTimeline();
1340-
if (multiWindowTimeBar && !timeline.isEmpty()) {
1357+
if (multiWindowTimeBar
1358+
&& player.isCommandAvailable(COMMAND_GET_TIMELINE)
1359+
&& player.isCommandAvailable(COMMAND_SEEK_TO_MEDIA_ITEM)) {
1360+
Timeline timeline = player.getCurrentTimeline();
13411361
int windowCount = timeline.getWindowCount();
1342-
windowIndex = 0;
1362+
int windowIndex = 0;
13431363
while (true) {
13441364
long windowDurationMs = timeline.getWindow(windowIndex, window).getDurationMs();
13451365
if (positionMs < windowDurationMs) {
@@ -1352,17 +1372,13 @@ private void seekToTimeBarPosition(Player player, long positionMs) {
13521372
positionMs -= windowDurationMs;
13531373
windowIndex++;
13541374
}
1355-
} else {
1356-
windowIndex = player.getCurrentMediaItemIndex();
1375+
player.seekTo(windowIndex, positionMs);
1376+
} else if (player.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM)) {
1377+
player.seekTo(positionMs);
13571378
}
1358-
seekTo(player, windowIndex, positionMs);
13591379
updateProgress();
13601380
}
13611381

1362-
private void seekTo(Player player, int windowIndex, long positionMs) {
1363-
player.seekTo(windowIndex, positionMs);
1364-
}
1365-
13661382
private void onFullScreenButtonClicked(View v) {
13671383
if (onFullScreenModeChangedListener == null) {
13681384
return;
@@ -1440,10 +1456,12 @@ public boolean dispatchMediaKeyEvent(KeyEvent event) {
14401456
}
14411457
if (event.getAction() == KeyEvent.ACTION_DOWN) {
14421458
if (keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) {
1443-
if (player.getPlaybackState() != Player.STATE_ENDED) {
1459+
if (player.getPlaybackState() != Player.STATE_ENDED
1460+
&& player.isCommandAvailable(COMMAND_SEEK_FORWARD)) {
14441461
player.seekForward();
14451462
}
1446-
} else if (keyCode == KeyEvent.KEYCODE_MEDIA_REWIND) {
1463+
} else if (keyCode == KeyEvent.KEYCODE_MEDIA_REWIND
1464+
&& player.isCommandAvailable(COMMAND_SEEK_BACK)) {
14471465
player.seekBack();
14481466
} else if (event.getRepeatCount() == 0) {
14491467
switch (keyCode) {
@@ -1458,10 +1476,14 @@ public boolean dispatchMediaKeyEvent(KeyEvent event) {
14581476
dispatchPause(player);
14591477
break;
14601478
case KeyEvent.KEYCODE_MEDIA_NEXT:
1461-
player.seekToNext();
1479+
if (player.isCommandAvailable(COMMAND_SEEK_TO_NEXT)) {
1480+
player.seekToNext();
1481+
}
14621482
break;
14631483
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
1464-
player.seekToPrevious();
1484+
if (player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS)) {
1485+
player.seekToPrevious();
1486+
}
14651487
break;
14661488
default:
14671489
break;
@@ -1501,7 +1523,10 @@ private void onLayoutChange(
15011523
}
15021524

15031525
private boolean shouldEnablePlayPauseButton() {
1504-
return player != null && !player.getCurrentTimeline().isEmpty();
1526+
return player != null
1527+
&& player.isCommandAvailable(COMMAND_PLAY_PAUSE)
1528+
&& (!player.isCommandAvailable(COMMAND_GET_TIMELINE)
1529+
|| !player.getCurrentTimeline().isEmpty());
15051530
}
15061531

15071532
private boolean shouldShowPauseButton() {
@@ -1522,16 +1547,21 @@ private void dispatchPlayPause(Player player) {
15221547

15231548
private void dispatchPlay(Player player) {
15241549
@State int state = player.getPlaybackState();
1525-
if (state == Player.STATE_IDLE) {
1550+
if (state == Player.STATE_IDLE && player.isCommandAvailable(COMMAND_PREPARE)) {
15261551
player.prepare();
1527-
} else if (state == Player.STATE_ENDED) {
1528-
seekTo(player, player.getCurrentMediaItemIndex(), C.TIME_UNSET);
1552+
} else if (state == Player.STATE_ENDED
1553+
&& player.isCommandAvailable(COMMAND_SEEK_TO_DEFAULT_POSITION)) {
1554+
player.seekToDefaultPosition();
1555+
}
1556+
if (player.isCommandAvailable(COMMAND_PLAY_PAUSE)) {
1557+
player.play();
15291558
}
1530-
player.play();
15311559
}
15321560

15331561
private void dispatchPause(Player player) {
1534-
player.pause();
1562+
if (player.isCommandAvailable(COMMAND_PLAY_PAUSE)) {
1563+
player.pause();
1564+
}
15351565
}
15361566

15371567
@SuppressLint("InlinedApi")
@@ -1547,13 +1577,18 @@ private static boolean isHandledMediaKey(int keyCode) {
15471577
}
15481578

15491579
/**
1550-
* Returns whether the specified {@code timeline} can be shown on a multi-window time bar.
1580+
* Returns whether the specified {@code player} can be shown on a multi-window time bar.
15511581
*
1552-
* @param timeline The {@link Timeline} to check.
1582+
* @param player The {@link Player} to check.
15531583
* @param window A scratch {@link Timeline.Window} instance.
15541584
* @return Whether the specified timeline can be shown on a multi-window time bar.
15551585
*/
1556-
private static boolean canShowMultiWindowTimeBar(Timeline timeline, Timeline.Window window) {
1586+
private static boolean canShowMultiWindowTimeBar(Player player, Timeline.Window window) {
1587+
if (!player.isCommandAvailable(COMMAND_GET_TIMELINE)
1588+
|| !player.isCommandAvailable(COMMAND_SEEK_TO_MEDIA_ITEM)) {
1589+
return false;
1590+
}
1591+
Timeline timeline = player.getCurrentTimeline();
15571592
if (timeline.getWindowCount() > MAX_WINDOWS_FOR_MULTI_WINDOW_TIME_BAR) {
15581593
return false;
15591594
}
@@ -1674,22 +1709,33 @@ public void onClick(View view) {
16741709
}
16751710
controlViewLayoutManager.resetHideCallbacks();
16761711
if (nextButton == view) {
1677-
player.seekToNext();
1712+
if (player.isCommandAvailable(COMMAND_SEEK_TO_NEXT)) {
1713+
player.seekToNext();
1714+
}
16781715
} else if (previousButton == view) {
1679-
player.seekToPrevious();
1716+
if (player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS)) {
1717+
player.seekToPrevious();
1718+
}
16801719
} else if (fastForwardButton == view) {
1681-
if (player.getPlaybackState() != Player.STATE_ENDED) {
1720+
if (player.getPlaybackState() != Player.STATE_ENDED
1721+
&& player.isCommandAvailable(COMMAND_SEEK_FORWARD)) {
16821722
player.seekForward();
16831723
}
16841724
} else if (rewindButton == view) {
1685-
player.seekBack();
1725+
if (player.isCommandAvailable(COMMAND_SEEK_BACK)) {
1726+
player.seekBack();
1727+
}
16861728
} else if (playPauseButton == view) {
16871729
dispatchPlayPause(player);
16881730
} else if (repeatToggleButton == view) {
1689-
player.setRepeatMode(
1690-
RepeatModeUtil.getNextRepeatMode(player.getRepeatMode(), repeatToggleModes));
1731+
if (player.isCommandAvailable(COMMAND_SET_REPEAT_MODE)) {
1732+
player.setRepeatMode(
1733+
RepeatModeUtil.getNextRepeatMode(player.getRepeatMode(), repeatToggleModes));
1734+
}
16911735
} else if (shuffleButton == view) {
1692-
player.setShuffleModeEnabled(!player.getShuffleModeEnabled());
1736+
if (player.isCommandAvailable(COMMAND_SET_SHUFFLE_MODE)) {
1737+
player.setShuffleModeEnabled(!player.getShuffleModeEnabled());
1738+
}
16931739
} else if (settingsButton == view) {
16941740
controlViewLayoutManager.removeHideCallbacks();
16951741
displaySettingsWindow(settingsAdapter, settingsButton);
@@ -1892,7 +1938,8 @@ public void onBindViewHolderAtZeroPosition(SubSettingViewHolder holder) {
18921938
holder.checkView.setVisibility(isTrackSelectionOff ? VISIBLE : INVISIBLE);
18931939
holder.itemView.setOnClickListener(
18941940
v -> {
1895-
if (player != null) {
1941+
if (player != null
1942+
&& player.isCommandAvailable(COMMAND_SET_TRACK_SELECTION_PARAMETERS)) {
18961943
TrackSelectionParameters trackSelectionParameters =
18971944
player.getTrackSelectionParameters();
18981945
player.setTrackSelectionParameters(
@@ -1933,7 +1980,8 @@ public void onBindViewHolderAtZeroPosition(SubSettingViewHolder holder) {
19331980
holder.checkView.setVisibility(hasSelectionOverride ? INVISIBLE : VISIBLE);
19341981
holder.itemView.setOnClickListener(
19351982
v -> {
1936-
if (player == null) {
1983+
if (player == null
1984+
|| !player.isCommandAvailable(COMMAND_SET_TRACK_SELECTION_PARAMETERS)) {
19371985
return;
19381986
}
19391987
TrackSelectionParameters trackSelectionParameters =
@@ -2036,6 +2084,9 @@ public void onBindViewHolder(SubSettingViewHolder holder, int position) {
20362084
holder.checkView.setVisibility(explicitlySelected ? VISIBLE : INVISIBLE);
20372085
holder.itemView.setOnClickListener(
20382086
v -> {
2087+
if (!player.isCommandAvailable(COMMAND_SET_TRACK_SELECTION_PARAMETERS)) {
2088+
return;
2089+
}
20392090
TrackSelectionParameters trackSelectionParameters =
20402091
player.getTrackSelectionParameters();
20412092
player.setTrackSelectionParameters(

0 commit comments

Comments
 (0)