Merge "Disable translation of dynamic grouping strings" into pi-androidx-dev
diff --git a/media-widget/src/androidTest/java/androidx/media/widget/VideoView2Test.java b/media-widget/src/androidTest/java/androidx/media/widget/VideoView2Test.java
index 29809a9..0e5c8a8 100644
--- a/media-widget/src/androidTest/java/androidx/media/widget/VideoView2Test.java
+++ b/media-widget/src/androidTest/java/androidx/media/widget/VideoView2Test.java
@@ -52,6 +52,7 @@
import androidx.test.runner.AndroidJUnit4;
import org.junit.After;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -213,6 +214,46 @@
any(MediaController2.class), eq(BaseMediaPlayer.PLAYER_STATE_PAUSED));
}
+ @Test
+ public void testSetSpeed() throws Throwable {
+ // Don't run the test if the codec isn't supported.
+ if (!hasCodec()) {
+ Log.i(TAG, "SKIPPING testSetSpeed(): codec is not supported");
+ return;
+ }
+
+ final float targetSpeed1 = 1.5f;
+ mActivityRule.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ mVideoView.setSpeed(targetSpeed1);
+ } catch (IllegalStateException e) {
+ Assert.fail("This should not happen. :" + e);
+ }
+ mVideoView.setMediaItem2(mMediaItem);
+ }
+ });
+ verify(mControllerCallback, timeout(TIME_OUT).atLeastOnce()).onConnected(
+ any(MediaController2.class), any(SessionCommandGroup2.class));
+ verify(mControllerCallback, timeout(TIME_OUT).atLeastOnce()).onPlayerStateChanged(
+ any(MediaController2.class), eq(BaseMediaPlayer.PLAYER_STATE_PAUSED));
+ assertEquals(targetSpeed1, mController.getPlaybackSpeed(), 0.05f);
+
+ final float targetSpeed2 = 0.5f;
+ mActivityRule.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mVideoView.setSpeed(targetSpeed2);
+ }
+ });
+ mController.play();
+ verify(mControllerCallback, timeout(TIME_OUT).atLeastOnce()).onPlaybackSpeedChanged(
+ any(MediaController2.class), eq(targetSpeed2));
+ assertEquals(targetSpeed2, mVideoView.getSpeed(), 0.05f);
+ assertEquals(targetSpeed2, mController.getPlaybackSpeed(), 0.05f);
+ }
+
private void setKeepScreenOn() throws Throwable {
mActivityRule.runOnUiThread(new Runnable() {
@Override
diff --git a/media-widget/src/main/java/androidx/media/widget/VideoView2ImplBase.java b/media-widget/src/main/java/androidx/media/widget/VideoView2ImplBase.java
index cd6faea..c2716da 100644
--- a/media-widget/src/main/java/androidx/media/widget/VideoView2ImplBase.java
+++ b/media-widget/src/main/java/androidx/media/widget/VideoView2ImplBase.java
@@ -120,6 +120,7 @@
int mTargetState = STATE_IDLE;
int mCurrentState = STATE_IDLE;
long mSeekWhenPrepared; // recording the seek position while preparing
+ float mSpeed;
int mVideoWidth;
int mVideoHeight;
@@ -169,6 +170,9 @@
.setSessionCallback(mCallbackExecutor, new MediaSessionCallback())
.build();
}
+ if (mSpeed != mMediaSession.getPlaybackSpeed()) {
+ mMediaSession.setPlaybackSpeed(mSpeed);
+ }
if (localPlaybackState == STATE_PLAYING) {
mMediaSession.play();
}
@@ -207,6 +211,7 @@
mVideoWidth = 0;
mVideoHeight = 0;
mSelectedSubtitleTrackIndex = INVALID_TRACK_INDEX;
+ mSpeed = 1.0f;
mAudioAttributes = new AudioAttributesCompat.Builder()
.setUsage(AudioAttributesCompat.USAGE_MEDIA)
@@ -335,13 +340,15 @@
/**
* Returns {@link SessionToken2} so that developers create their own
* {@link androidx.media2.MediaController2} instance. This method should be called when
- * VideoView2 is attached to window, or it throws IllegalStateException.
+ * VideoView2 is attached to window or after {@link #setMediaItem2} is called.
*
* @throws IllegalStateException if internal MediaSession is not created yet.
*/
@Override
public SessionToken2 getMediaSessionToken2() {
- checkMediaSession();
+ if (mMediaSession == null) {
+ throw new IllegalStateException("MediaSession2 instance is not available.");
+ }
return mMediaSession.getToken();
}
@@ -384,8 +391,10 @@
Log.e(TAG, "Unsupported speed (" + speed + ") is ignored.");
return;
}
- checkMediaSession();
- mMediaSession.setPlaybackSpeed(speed);
+ mSpeed = speed;
+ if (isMediaPrepared()) {
+ mMediaSession.setPlaybackSpeed(speed);
+ }
}
/**
@@ -396,8 +405,7 @@
*/
@Override
public float getSpeed() {
- checkMediaSession();
- return mMediaSession.getPlaybackSpeed();
+ return mSpeed;
}
/**
@@ -679,12 +687,6 @@
///////////////////////////////////////////////////
// Protected or private methods
///////////////////////////////////////////////////
- private void checkMediaSession() {
- if (mMediaSession == null) {
- throw new IllegalStateException("MediaSession instance is not available.");
- }
- }
-
private void attachMediaControlView() {
// Get MediaController from MediaSession and set it inside MediaControlView
mMediaControlView.setMediaSessionToken2(mMediaSession.getToken());
@@ -694,7 +696,7 @@
mInstance.addView(mMediaControlView, params);
}
- private boolean isInPlaybackState() {
+ private boolean isMediaPrepared() {
return mMediaSession != null
&& mMediaSession.getPlayerState() != BaseMediaPlayer.PLAYER_STATE_ERROR
&& mMediaSession.getPlayerState() != BaseMediaPlayer.PLAYER_STATE_IDLE;
@@ -750,6 +752,7 @@
mMediaSession.updatePlayer(mMediaPlayer.getBaseMediaPlayer(),
mMediaSession.getPlaylistAgent());
}
+ mMediaSession.setPlaylist(mPlayList, null);
final Context context = mInstance.getContext();
mSubtitleController = new SubtitleController(context);
@@ -757,7 +760,6 @@
mSubtitleController.registerRenderer(new Cea708CaptionRenderer(context));
mSubtitleController.setAnchor((SubtitleController.Anchor) mSubtitleAnchorView);
- mMediaSession.setPlaylist(mPlayList, null);
// we don't set the target state here either, but preserve the
// target state that was there before.
@@ -794,7 +796,7 @@
}
private void selectOrDeselectSubtitle(boolean select) {
- if (!isInPlaybackState()) {
+ if (!isMediaPrepared()) {
return;
}
if (select) {
@@ -1082,6 +1084,9 @@
extractTracks();
extractMetadata();
sendMetadata();
+ if (mSpeed != mMediaSession.getPlaybackSpeed()) {
+ mMediaSession.setPlaybackSpeed(mSpeed);
+ }
}
if (mMediaControlView != null) {
@@ -1235,7 +1240,18 @@
@Override
public void onMediaPrepared(@NonNull MediaSession2 session,
@NonNull BaseMediaPlayer player, @NonNull MediaItem2 item) {
- Log.d(TAG, "onMediaPrepared() is called.");
+ if (DEBUG) {
+ Log.d(TAG, "onMediaPrepared() is called.");
+ }
+ }
+
+ @Override
+ public void onPlaybackSpeedChanged(@NonNull MediaSession2 session,
+ @NonNull BaseMediaPlayer player, float speed) {
+ if (DEBUG) {
+ Log.d(TAG, "onPlaybackSpeedChanged is called. Speed: " + speed);
+ }
+ mSpeed = speed;
}
}
}
diff --git a/media/src/main/java/android/support/v4/media/session/MediaSessionCompat.java b/media/src/main/java/android/support/v4/media/session/MediaSessionCompat.java
index d457aa2..a81d3d4 100644
--- a/media/src/main/java/android/support/v4/media/session/MediaSessionCompat.java
+++ b/media/src/main/java/android/support/v4/media/session/MediaSessionCompat.java
@@ -1033,13 +1033,14 @@
if (keyEvent == null || keyEvent.getAction() != KeyEvent.ACTION_DOWN) {
return false;
}
+ RemoteUserInfo remoteUserInfo = impl.getCurrentControllerInfo();
int keyCode = keyEvent.getKeyCode();
switch (keyCode) {
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
case KeyEvent.KEYCODE_HEADSETHOOK:
if (keyEvent.getRepeatCount() > 0) {
// Consider long-press as a single tap.
- handleMediaPlayPauseKeySingleTapIfPending();
+ handleMediaPlayPauseKeySingleTapIfPending(remoteUserInfo);
} else if (mMediaPlayPauseKeyPending) {
mCallbackHandler.removeMessages(
CallbackHandler.MSG_MEDIA_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT);
@@ -1052,21 +1053,22 @@
}
} else {
mMediaPlayPauseKeyPending = true;
- mCallbackHandler.sendEmptyMessageDelayed(
+ mCallbackHandler.sendMessageDelayed(mCallbackHandler.obtainMessage(
CallbackHandler.MSG_MEDIA_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT,
+ remoteUserInfo),
ViewConfiguration.getDoubleTapTimeout());
}
return true;
default:
// If another key is pressed within double tap timeout, consider the pending
// pending play/pause as a single tap to handle media keys in order.
- handleMediaPlayPauseKeySingleTapIfPending();
+ handleMediaPlayPauseKeySingleTapIfPending(remoteUserInfo);
break;
}
return false;
}
- void handleMediaPlayPauseKeySingleTapIfPending() {
+ void handleMediaPlayPauseKeySingleTapIfPending(RemoteUserInfo remoteUserInfo) {
if (!mMediaPlayPauseKeyPending) {
return;
}
@@ -1085,11 +1087,13 @@
| PlaybackStateCompat.ACTION_PLAY)) != 0;
boolean canPause = (validActions & (PlaybackStateCompat.ACTION_PLAY_PAUSE
| PlaybackStateCompat.ACTION_PAUSE)) != 0;
+ impl.setCurrentControllerInfo(remoteUserInfo);
if (isPlaying && canPause) {
onPause();
} else if (!isPlaying && canPlay) {
onPlay();
}
+ impl.setCurrentControllerInfo(null);
}
/**
@@ -1330,7 +1334,7 @@
@Override
public void handleMessage(Message msg) {
if (msg.what == MSG_MEDIA_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT) {
- handleMediaPlayPauseKeySingleTapIfPending();
+ handleMediaPlayPauseKeySingleTapIfPending((RemoteUserInfo) msg.obj);
}
}
}
@@ -1969,6 +1973,9 @@
String getCallingPackage();
RemoteUserInfo getCurrentControllerInfo();
+
+ // Internal only method
+ void setCurrentControllerInfo(RemoteUserInfo remoteUserInfo);
}
static class MediaSessionImplBase implements MediaSessionImpl {
@@ -1995,6 +2002,7 @@
private boolean mIsMbrRegistered = false;
private boolean mIsRccRegistered = false;
volatile Callback mCallback;
+ private RemoteUserInfo mRemoteUserInfo;
@SessionFlags int mFlags;
@@ -2422,11 +2430,15 @@
@Override
public RemoteUserInfo getCurrentControllerInfo() {
synchronized (mLock) {
- if (mHandler != null) {
- return mHandler.getRemoteUserInfo();
- }
+ return mRemoteUserInfo;
}
- return null;
+ }
+
+ @Override
+ public void setCurrentControllerInfo(RemoteUserInfo remoteUserInfo) {
+ synchronized (mLock) {
+ mRemoteUserInfo = remoteUserInfo;
+ }
}
// Registers/unregisters components as needed.
@@ -2976,7 +2988,6 @@
}
class MessageHandler extends Handler {
-
private static final int MSG_COMMAND = 1;
private static final int MSG_ADJUST_VOLUME = 2;
private static final int MSG_PREPARE = 3;
@@ -3012,8 +3023,6 @@
private static final int KEYCODE_MEDIA_PAUSE = 127;
private static final int KEYCODE_MEDIA_PLAY = 126;
- private RemoteUserInfo mRemoteUserInfo;
-
public MessageHandler(Looper looper) {
super(looper);
}
@@ -3027,8 +3036,8 @@
Bundle data = msg.getData();
ensureClassLoader(data);
- mRemoteUserInfo = new RemoteUserInfo(data.getString(DATA_CALLING_PACKAGE),
- data.getInt(DATA_CALLING_PID), data.getInt(DATA_CALLING_UID));
+ setCurrentControllerInfo(new RemoteUserInfo(data.getString(DATA_CALLING_PACKAGE),
+ data.getInt(DATA_CALLING_PID), data.getInt(DATA_CALLING_UID)));
Bundle extras = data.getBundle(DATA_EXTRAS);
ensureClassLoader(extras);
@@ -3141,7 +3150,7 @@
break;
}
} finally {
- mRemoteUserInfo = null;
+ setCurrentControllerInfo(null);
}
}
@@ -3195,10 +3204,6 @@
break;
}
}
-
- RemoteUserInfo getRemoteUserInfo() {
- return mRemoteUserInfo;
- }
}
}
@@ -3570,10 +3575,17 @@
@Override
public Object getRemoteControlClient() {
+ // Note: When this returns somthing, {@link MediaSessionCompatCallbackTest} and
+ // {@link #setCurrentUserInfoOverride} should be also updated.
return null;
}
@Override
+ public void setCurrentControllerInfo(RemoteUserInfo remoteUserInfo) {
+ // No-op, until we return something from {@link #getRemoteControlClient}.
+ }
+
+ @Override
public String getCallingPackage() {
if (android.os.Build.VERSION.SDK_INT < 24) {
return null;
@@ -3584,6 +3596,7 @@
@Override
public RemoteUserInfo getCurrentControllerInfo() {
+ // Note: Update MediaSessionCompatCallbackTest when we return something.
return null;
}
@@ -3898,6 +3911,11 @@
}
@Override
+ public void setCurrentControllerInfo(RemoteUserInfo remoteUserInfo) {
+ // No-op. {@link MediaSession#getCurrentControllerInfo} would work.
+ }
+
+ @Override
public final @NonNull RemoteUserInfo getCurrentControllerInfo() {
android.media.session.MediaSessionManager.RemoteUserInfo info =
((MediaSession) mSessionObj).getCurrentControllerInfo();
diff --git a/media/version-compat-tests/current/client/src/androidTest/java/android/support/mediacompat/client/ClientBroadcastReceiver.java b/media/version-compat-tests/current/client/src/androidTest/java/android/support/mediacompat/client/ClientBroadcastReceiver.java
index 3227482..35b762d 100644
--- a/media/version-compat-tests/current/client/src/androidTest/java/android/support/mediacompat/client/ClientBroadcastReceiver.java
+++ b/media/version-compat-tests/current/client/src/androidTest/java/android/support/mediacompat/client/ClientBroadcastReceiver.java
@@ -20,6 +20,7 @@
import static android.support.mediacompat.testlib.MediaControllerConstants
.ADD_QUEUE_ITEM_WITH_INDEX;
import static android.support.mediacompat.testlib.MediaControllerConstants.ADJUST_VOLUME;
+import static android.support.mediacompat.testlib.MediaControllerConstants.DISPATCH_MEDIA_BUTTON;
import static android.support.mediacompat.testlib.MediaControllerConstants.FAST_FORWARD;
import static android.support.mediacompat.testlib.MediaControllerConstants.PAUSE;
import static android.support.mediacompat.testlib.MediaControllerConstants.PLAY;
@@ -67,6 +68,7 @@
import android.support.v4.media.session.MediaControllerCompat.TransportControls;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
+import android.view.KeyEvent;
public class ClientBroadcastReceiver extends BroadcastReceiver {
@@ -113,6 +115,10 @@
case ADJUST_VOLUME:
controller.adjustVolume(extras.getInt(KEY_ARGUMENT), 0);
break;
+ case DISPATCH_MEDIA_BUTTON:
+ controller.dispatchMediaButtonEvent(
+ (KeyEvent) extras.getParcelable(KEY_ARGUMENT));
+ break;
}
} else if (ACTION_CALL_TRANSPORT_CONTROLS_METHOD.equals(intent.getAction())
&& extras != null) {
diff --git a/media/version-compat-tests/current/service/src/androidTest/java/android/support/mediacompat/service/MediaSessionCompatCallbackTest.java b/media/version-compat-tests/current/service/src/androidTest/java/android/support/mediacompat/service/MediaSessionCompatCallbackTest.java
index fb9c183..204461f 100644
--- a/media/version-compat-tests/current/service/src/androidTest/java/android/support/mediacompat/service/MediaSessionCompatCallbackTest.java
+++ b/media/version-compat-tests/current/service/src/androidTest/java/android/support/mediacompat/service/MediaSessionCompatCallbackTest.java
@@ -19,6 +19,7 @@
import static android.support.mediacompat.testlib.MediaControllerConstants
.ADD_QUEUE_ITEM_WITH_INDEX;
import static android.support.mediacompat.testlib.MediaControllerConstants.ADJUST_VOLUME;
+import static android.support.mediacompat.testlib.MediaControllerConstants.DISPATCH_MEDIA_BUTTON;
import static android.support.mediacompat.testlib.MediaControllerConstants.FAST_FORWARD;
import static android.support.mediacompat.testlib.MediaControllerConstants.PAUSE;
import static android.support.mediacompat.testlib.MediaControllerConstants.PLAY;
@@ -88,6 +89,7 @@
import android.os.Process;
import android.os.ResultReceiver;
import android.os.SystemClock;
+import android.support.mediacompat.testlib.util.IntentUtil;
import android.support.mediacompat.testlib.util.PollingCheck;
import android.support.v4.media.MediaBrowserCompat;
import android.support.v4.media.MediaDescriptionCompat;
@@ -213,6 +215,7 @@
return;
}
mCallback.reset(1);
+ mCallback.setExpectedCallerPackageName(IntentUtil.SERVICE_PACKAGE_NAME);
mSession.setCallback(mCallback, new Handler(Looper.getMainLooper()));
MediaSessionCompat session = MediaSessionCompat.fromMediaSession(
getContext(), mSession.getMediaSession());
@@ -227,7 +230,7 @@
@SmallTest
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.P)
public void testCallers() throws Exception {
- mCallback.reset(1);
+ mCallback.reset(1, getContext().getPackageName());
mSession.setCallback(mCallback, new Handler(Looper.getMainLooper()));
MediaSessionCompat session = MediaSessionCompat.fromMediaSession(
getContext(), mSession.getMediaSession());
@@ -245,7 +248,7 @@
assertEquals(Process.myUid(), remoteUserInfo1.getUid());
assertEquals(Process.myPid(), remoteUserInfo1.getPid());
- mCallback.reset(1);
+ mCallback.reset(1, getContext().getPackageName());
controller2.getTransportControls().stop();
mCallback.await(TIME_OUT_MS);
assertTrue(mCallback.mOnStopCalled);
@@ -654,7 +657,7 @@
mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS);
mSession.setActive(true);
- final long waitTimeForNoResponse = 30L;
+ final long waitTimeForNoResponse = 100L;
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON)
.setComponent(new ComponentName(getContext(), getContext().getClass()));
@@ -665,37 +668,37 @@
setPlaybackState(PlaybackStateCompat.STATE_PLAYING);
mCallback.reset(1);
- sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY);
+ sendMediaKeyEventFromController(KeyEvent.KEYCODE_MEDIA_PLAY);
assertTrue(mCallback.await(TIME_OUT_MS));
assertEquals(1, mCallback.mOnPlayCalledCount);
mCallback.reset(1);
- sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PAUSE);
+ sendMediaKeyEventFromController(KeyEvent.KEYCODE_MEDIA_PAUSE);
assertTrue(mCallback.await(TIME_OUT_MS));
assertTrue(mCallback.mOnPauseCalled);
mCallback.reset(1);
- sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_NEXT);
+ sendMediaKeyEventFromController(KeyEvent.KEYCODE_MEDIA_NEXT);
assertTrue(mCallback.await(TIME_OUT_MS));
assertTrue(mCallback.mOnSkipToNextCalled);
mCallback.reset(1);
- sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PREVIOUS);
+ sendMediaKeyEventFromController(KeyEvent.KEYCODE_MEDIA_PREVIOUS);
assertTrue(mCallback.await(TIME_OUT_MS));
assertTrue(mCallback.mOnSkipToPreviousCalled);
mCallback.reset(1);
- sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_STOP);
+ sendMediaKeyEventFromController(KeyEvent.KEYCODE_MEDIA_STOP);
assertTrue(mCallback.await(TIME_OUT_MS));
assertTrue(mCallback.mOnStopCalled);
mCallback.reset(1);
- sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD);
+ sendMediaKeyEventFromController(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD);
assertTrue(mCallback.await(TIME_OUT_MS));
assertTrue(mCallback.mOnFastForwardCalled);
mCallback.reset(1);
- sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_REWIND);
+ sendMediaKeyEventFromController(KeyEvent.KEYCODE_MEDIA_REWIND);
assertTrue(mCallback.await(TIME_OUT_MS));
assertTrue(mCallback.mOnRewindCalled);
@@ -703,22 +706,22 @@
// First, send PLAY_PAUSE button event while in STATE_PAUSED.
mCallback.reset(1);
setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
- sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+ sendMediaKeyEventFromController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
assertTrue(mCallback.await(TIME_OUT_MS));
assertEquals(1, mCallback.mOnPlayCalledCount);
// Next, send PLAY_PAUSE button event while in STATE_PLAYING.
mCallback.reset(1);
setPlaybackState(PlaybackStateCompat.STATE_PLAYING);
- sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+ sendMediaKeyEventFromController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
assertTrue(mCallback.await(TIME_OUT_MS));
assertTrue(mCallback.mOnPauseCalled);
// Double tap of PLAY_PAUSE is the next track.
mCallback.reset(2);
setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
- sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
- sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+ sendMediaKeyEventFromController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+ sendMediaKeyEventFromController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
assertFalse(mCallback.await(waitTimeForNoResponse));
assertTrue(mCallback.mOnSkipToNextCalled);
assertEquals(0, mCallback.mOnPlayCalledCount);
@@ -728,7 +731,7 @@
// It should be the same as the single short-press.
mCallback.reset(1);
setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
- sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, true);
+ sendMediaKeyEventFromController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, true);
assertTrue(mCallback.await(TIME_OUT_MS));
assertEquals(1, mCallback.mOnPlayCalledCount);
@@ -736,8 +739,8 @@
// Initial down event from the second press within double tap time-out will make
// onSkipToNext() to be called, so further down events shouldn't be handled again.
mCallback.reset(2);
- sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
- sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, true);
+ sendMediaKeyEventFromController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+ sendMediaKeyEventFromController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, true);
assertFalse(mCallback.await(waitTimeForNoResponse));
assertTrue(mCallback.mOnSkipToNextCalled);
assertEquals(0, mCallback.mOnPlayCalledCount);
@@ -748,8 +751,8 @@
// so it shouldn't be used as the first tap of the double tap.
mCallback.reset(2);
setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
- sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, true);
- sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+ sendMediaKeyEventFromController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, true);
+ sendMediaKeyEventFromController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
assertTrue(mCallback.await(TIME_OUT_MS));
// onMediaButtonEvent() calls either onPlay() or onPause() depending on the playback state,
// so onPlay() should be called once and onPause() also should be called once.
@@ -761,9 +764,9 @@
// PLAY_PAUSE should be handled as normal.
mCallback.reset(3);
setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
- sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
- sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_STOP);
- sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+ sendMediaKeyEventFromController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+ sendMediaKeyEventFromController(KeyEvent.KEYCODE_MEDIA_STOP);
+ sendMediaKeyEventFromController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
assertTrue(mCallback.await(TIME_OUT_MS));
assertFalse(mCallback.mOnSkipToNextCalled);
assertTrue(mCallback.mOnStopCalled);
@@ -772,8 +775,8 @@
// Test if media keys are handled in order.
mCallback.reset(2);
setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
- sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
- sendMediaKeyInputToController(KeyEvent.KEYCODE_MEDIA_STOP);
+ sendMediaKeyEventFromController(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+ sendMediaKeyEventFromController(KeyEvent.KEYCODE_MEDIA_STOP);
assertTrue(mCallback.await(TIME_OUT_MS));
assertEquals(1, mCallback.mOnPlayCalledCount);
assertTrue(mCallback.mOnStopCalled);
@@ -976,29 +979,32 @@
}
}
- private void sendMediaKeyInputToController(int keyCode) {
- sendMediaKeyInputToController(keyCode, false);
+ private void sendMediaKeyEventFromController(int keyCode) {
+ sendMediaKeyEventFromController(keyCode, false);
}
- private void sendMediaKeyInputToController(int keyCode, boolean isLongPress) {
- MediaControllerCompat controller = mSession.getController();
+ private void sendMediaKeyEventFromController(int keyCode, boolean isLongPress) {
long currentTimeMs = System.currentTimeMillis();
KeyEvent down = new KeyEvent(
currentTimeMs, currentTimeMs, KeyEvent.ACTION_DOWN, keyCode, 0);
- controller.dispatchMediaButtonEvent(down);
+ callMediaControllerMethod(
+ DISPATCH_MEDIA_BUTTON, down, getContext(), mSession.getSessionToken());
if (isLongPress) {
KeyEvent longPress = new KeyEvent(
currentTimeMs, System.currentTimeMillis(), KeyEvent.ACTION_DOWN, keyCode, 1);
- controller.dispatchMediaButtonEvent(longPress);
+ callMediaControllerMethod(
+ DISPATCH_MEDIA_BUTTON, longPress, getContext(), mSession.getSessionToken());
}
KeyEvent up = new KeyEvent(
currentTimeMs, System.currentTimeMillis(), KeyEvent.ACTION_UP, keyCode, 0);
- controller.dispatchMediaButtonEvent(up);
+ callMediaControllerMethod(
+ DISPATCH_MEDIA_BUTTON, up, getContext(), mSession.getSessionToken());
}
private class MediaSessionCallback extends MediaSessionCompat.Callback {
private CountDownLatch mLatch;
private RemoteUserInfo mRemoteUserInfoForStop;
+ private String mExpectedCallerPackageName;
private long mSeekPosition;
private long mQueueItemId;
private RatingCompat mRating;
@@ -1044,6 +1050,7 @@
public void reset(int count) {
mLatch = new CountDownLatch(count);
+ mExpectedCallerPackageName = IntentUtil.CLIENT_PACKAGE_NAME;
mSeekPosition = -1;
mQueueItemId = -1;
mRating = null;
@@ -1088,6 +1095,15 @@
mOnRemoveQueueItemCalled = false;
}
+ public void reset(int count, String expectedCallerPackageName) {
+ reset(count);
+ setExpectedCallerPackageName(expectedCallerPackageName);
+ }
+
+ public void setExpectedCallerPackageName(String packageName) {
+ mExpectedCallerPackageName = packageName;
+ }
+
public boolean await(long timeoutMs) {
try {
return mLatch.await(timeoutMs, TimeUnit.MILLISECONDS);
@@ -1098,6 +1114,10 @@
@Override
public void onPlay() {
+ if (!isCallerTestClient()) {
+ // Ignore
+ return;
+ }
mOnPlayCalledCount++;
setPlaybackState(PlaybackStateCompat.STATE_PLAYING);
mLatch.countDown();
@@ -1105,6 +1125,10 @@
@Override
public void onPause() {
+ if (!isCallerTestClient()) {
+ // Ignore
+ return;
+ }
mOnPauseCalled = true;
setPlaybackState(PlaybackStateCompat.STATE_PAUSED);
mLatch.countDown();
@@ -1112,6 +1136,10 @@
@Override
public void onStop() {
+ if (!isCallerTestClient()) {
+ // Ignore
+ return;
+ }
mOnStopCalled = true;
setPlaybackState(PlaybackStateCompat.STATE_STOPPED);
mRemoteUserInfoForStop = mSession.getCurrentControllerInfo();
@@ -1120,30 +1148,50 @@
@Override
public void onFastForward() {
+ if (!isCallerTestClient()) {
+ // Ignore
+ return;
+ }
mOnFastForwardCalled = true;
mLatch.countDown();
}
@Override
public void onRewind() {
+ if (!isCallerTestClient()) {
+ // Ignore
+ return;
+ }
mOnRewindCalled = true;
mLatch.countDown();
}
@Override
public void onSkipToPrevious() {
+ if (!isCallerTestClient()) {
+ // Ignore
+ return;
+ }
mOnSkipToPreviousCalled = true;
mLatch.countDown();
}
@Override
public void onSkipToNext() {
+ if (!isCallerTestClient()) {
+ // Ignore
+ return;
+ }
mOnSkipToNextCalled = true;
mLatch.countDown();
}
@Override
public void onSeekTo(long pos) {
+ if (!isCallerTestClient()) {
+ // Ignore
+ return;
+ }
mOnSeekToCalled = true;
mSeekPosition = pos;
mLatch.countDown();
@@ -1151,6 +1199,10 @@
@Override
public void onSetRating(RatingCompat rating) {
+ if (!isCallerTestClient()) {
+ // Ignore
+ return;
+ }
mOnSetRatingCalled = true;
mRating = rating;
mLatch.countDown();
@@ -1158,6 +1210,10 @@
@Override
public void onPlayFromMediaId(String mediaId, Bundle extras) {
+ if (!isCallerTestClient()) {
+ // Ignore
+ return;
+ }
mOnPlayFromMediaIdCalled = true;
mMediaId = mediaId;
mExtras = extras;
@@ -1166,6 +1222,10 @@
@Override
public void onPlayFromSearch(String query, Bundle extras) {
+ if (!isCallerTestClient()) {
+ // Ignore
+ return;
+ }
mOnPlayFromSearchCalled = true;
mQuery = query;
mExtras = extras;
@@ -1174,6 +1234,10 @@
@Override
public void onPlayFromUri(Uri uri, Bundle extras) {
+ if (!isCallerTestClient()) {
+ // Ignore
+ return;
+ }
mOnPlayFromUriCalled = true;
mUri = uri;
mExtras = extras;
@@ -1182,6 +1246,10 @@
@Override
public void onCustomAction(String action, Bundle extras) {
+ if (!isCallerTestClient()) {
+ // Ignore
+ return;
+ }
mOnCustomActionCalled = true;
mAction = action;
mExtras = extras;
@@ -1190,6 +1258,10 @@
@Override
public void onSkipToQueueItem(long id) {
+ if (!isCallerTestClient()) {
+ // Ignore
+ return;
+ }
mOnSkipToQueueItemCalled = true;
mQueueItemId = id;
mLatch.countDown();
@@ -1197,6 +1269,10 @@
@Override
public void onCommand(String command, Bundle extras, ResultReceiver cb) {
+ if (!isCallerTestClient()) {
+ // Ignore
+ return;
+ }
mOnCommandCalled = true;
mCommand = command;
mExtras = extras;
@@ -1206,12 +1282,20 @@
@Override
public void onPrepare() {
+ if (!isCallerTestClient()) {
+ // Ignore
+ return;
+ }
mOnPrepareCalled = true;
mLatch.countDown();
}
@Override
public void onPrepareFromMediaId(String mediaId, Bundle extras) {
+ if (!isCallerTestClient()) {
+ // Ignore
+ return;
+ }
mOnPrepareFromMediaIdCalled = true;
mMediaId = mediaId;
mExtras = extras;
@@ -1220,6 +1304,10 @@
@Override
public void onPrepareFromSearch(String query, Bundle extras) {
+ if (!isCallerTestClient()) {
+ // Ignore
+ return;
+ }
mOnPrepareFromSearchCalled = true;
mQuery = query;
mExtras = extras;
@@ -1228,6 +1316,10 @@
@Override
public void onPrepareFromUri(Uri uri, Bundle extras) {
+ if (!isCallerTestClient()) {
+ // Ignore
+ return;
+ }
mOnPrepareFromUriCalled = true;
mUri = uri;
mExtras = extras;
@@ -1236,6 +1328,10 @@
@Override
public void onSetRepeatMode(int repeatMode) {
+ if (!isCallerTestClient()) {
+ // Ignore
+ return;
+ }
mOnSetRepeatModeCalled = true;
mRepeatMode = repeatMode;
mLatch.countDown();
@@ -1243,6 +1339,10 @@
@Override
public void onAddQueueItem(MediaDescriptionCompat description) {
+ if (!isCallerTestClient()) {
+ // Ignore
+ return;
+ }
mOnAddQueueItemCalled = true;
mQueueDescription = description;
mQueue.add(new MediaSessionCompat.QueueItem(description, mQueue.size()));
@@ -1252,6 +1352,10 @@
@Override
public void onAddQueueItem(MediaDescriptionCompat description, int index) {
+ if (!isCallerTestClient()) {
+ // Ignore
+ return;
+ }
mOnAddQueueItemAtCalled = true;
mQueueIndex = index;
mQueueDescription = description;
@@ -1262,6 +1366,10 @@
@Override
public void onRemoveQueueItem(MediaDescriptionCompat description) {
+ if (!isCallerTestClient()) {
+ // Ignore
+ return;
+ }
mOnRemoveQueueItemCalled = true;
String mediaId = description.getMediaId();
for (int i = mQueue.size() - 1; i >= 0; --i) {
@@ -1276,6 +1384,10 @@
@Override
public void onSetCaptioningEnabled(boolean enabled) {
+ if (!isCallerTestClient()) {
+ // Ignore
+ return;
+ }
mOnSetCaptioningEnabledCalled = true;
mCaptioningEnabled = enabled;
mLatch.countDown();
@@ -1283,9 +1395,26 @@
@Override
public void onSetShuffleMode(int shuffleMode) {
+ if (!isCallerTestClient()) {
+ // Ignore
+ return;
+ }
mOnSetShuffleModeCalled = true;
mShuffleMode = shuffleMode;
mLatch.countDown();
}
+
+ private boolean isCallerTestClient() {
+ if (Build.VERSION.SDK_INT >= 21 && Build.VERSION.SDK_INT < 28) {
+ // RemoteUserInfo isn't available.
+ return true;
+ }
+ RemoteUserInfo info = mSession.getCurrentControllerInfo();
+ assertNotNull(info);
+
+ // Don't stop test for an unexpected package name here, because any controller may
+ // connect to test session and send command while testing.
+ return mExpectedCallerPackageName.equals(info.getPackageName());
+ }
}
}
diff --git a/media/version-compat-tests/lib/src/main/java/android/support/mediacompat/testlib/MediaControllerConstants.java b/media/version-compat-tests/lib/src/main/java/android/support/mediacompat/testlib/MediaControllerConstants.java
index e81f7d9..3480664 100644
--- a/media/version-compat-tests/lib/src/main/java/android/support/mediacompat/testlib/MediaControllerConstants.java
+++ b/media/version-compat-tests/lib/src/main/java/android/support/mediacompat/testlib/MediaControllerConstants.java
@@ -28,6 +28,7 @@
public static final int REMOVE_QUEUE_ITEM = 204;
public static final int SET_VOLUME_TO = 205;
public static final int ADJUST_VOLUME = 206;
+ public static final int DISPATCH_MEDIA_BUTTON = 207;
// TransportControls methods.
public static final int PLAY = 301;
diff --git a/media/version-compat-tests/previous/client/src/androidTest/java/android/support/mediacompat/client/ClientBroadcastReceiver.java b/media/version-compat-tests/previous/client/src/androidTest/java/android/support/mediacompat/client/ClientBroadcastReceiver.java
index 3227482..35b762d 100644
--- a/media/version-compat-tests/previous/client/src/androidTest/java/android/support/mediacompat/client/ClientBroadcastReceiver.java
+++ b/media/version-compat-tests/previous/client/src/androidTest/java/android/support/mediacompat/client/ClientBroadcastReceiver.java
@@ -20,6 +20,7 @@
import static android.support.mediacompat.testlib.MediaControllerConstants
.ADD_QUEUE_ITEM_WITH_INDEX;
import static android.support.mediacompat.testlib.MediaControllerConstants.ADJUST_VOLUME;
+import static android.support.mediacompat.testlib.MediaControllerConstants.DISPATCH_MEDIA_BUTTON;
import static android.support.mediacompat.testlib.MediaControllerConstants.FAST_FORWARD;
import static android.support.mediacompat.testlib.MediaControllerConstants.PAUSE;
import static android.support.mediacompat.testlib.MediaControllerConstants.PLAY;
@@ -67,6 +68,7 @@
import android.support.v4.media.session.MediaControllerCompat.TransportControls;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
+import android.view.KeyEvent;
public class ClientBroadcastReceiver extends BroadcastReceiver {
@@ -113,6 +115,10 @@
case ADJUST_VOLUME:
controller.adjustVolume(extras.getInt(KEY_ARGUMENT), 0);
break;
+ case DISPATCH_MEDIA_BUTTON:
+ controller.dispatchMediaButtonEvent(
+ (KeyEvent) extras.getParcelable(KEY_ARGUMENT));
+ break;
}
} else if (ACTION_CALL_TRANSPORT_CONTROLS_METHOD.equals(intent.getAction())
&& extras != null) {