Merge "Reuse a given MediaSessionCompat instead of creating another one" into nyc-support-25.1-dev
diff --git a/v7/mediarouter/src/android/support/v7/media/MediaRouter.java b/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
index 8e451b3..d398e15 100644
--- a/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
+++ b/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
@@ -2688,21 +2688,13 @@
         }
 
         public void setMediaSession(Object session) {
-            if (mMediaSession != null) {
-                mMediaSession.clearVolumeHandling();
-            }
-            if (session == null) {
-                mMediaSession = null;
-            } else {
-                mMediaSession = new MediaSessionRecord(session);
-                updatePlaybackInfoFromSelectedRoute();
-            }
+            setMediaSessionRecord(session != null ? new MediaSessionRecord(session) : null);
         }
 
         public void setMediaSessionCompat(final MediaSessionCompat session) {
             mCompatSession = session;
             if (android.os.Build.VERSION.SDK_INT >= 21) {
-                setMediaSession(session != null ? session.getMediaSession() : null);
+                setMediaSessionRecord(session != null ? new MediaSessionRecord(session) : null);
             } else if (android.os.Build.VERSION.SDK_INT >= 14) {
                 if (mRccMediaSession != null) {
                     removeRemoteControlClient(mRccMediaSession.getRemoteControlClient());
@@ -2718,6 +2710,16 @@
             }
         }
 
+        private void setMediaSessionRecord(MediaSessionRecord mediaSessionRecord) {
+            if (mMediaSession != null) {
+                mMediaSession.clearVolumeHandling();
+            }
+            mMediaSession = mediaSessionRecord;
+            if (mediaSessionRecord != null) {
+                updatePlaybackInfoFromSelectedRoute();
+            }
+        }
+
         public MediaSessionCompat.Token getMediaSessionToken() {
             if (mMediaSession != null) {
                 return mMediaSession.getToken();
@@ -2795,6 +2797,10 @@
                 mMsCompat = MediaSessionCompat.fromMediaSession(mApplicationContext, mediaSession);
             }
 
+            public MediaSessionRecord(MediaSessionCompat mediaSessionCompat) {
+                mMsCompat = mediaSessionCompat;
+            }
+
             public void configureVolume(@VolumeProviderCompat.ControlType int controlType,
                     int max, int current) {
                 if (mVpCompat != null && controlType == mControlType && max == mMaxVolume) {
diff --git a/v7/mediarouter/tests/src/android/support/v7/media/MediaRouterTest.java b/v7/mediarouter/tests/src/android/support/v7/media/MediaRouterTest.java
new file mode 100644
index 0000000..8c43f76
--- /dev/null
+++ b/v7/mediarouter/tests/src/android/support/v7/media/MediaRouterTest.java
@@ -0,0 +1,121 @@
+/*
+* Copyright (C) 2017 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package android.support.v7.media;
+
+import static android.support.test.InstrumentationRegistry.getContext;
+import static android.support.test.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.v4.media.session.MediaControllerCompat;
+import android.support.v4.media.session.MediaSessionCompat;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test {@link MediaRouter}.
+ */
+@RunWith(AndroidJUnit4.class)
+public class MediaRouterTest {
+   // The maximum time to wait for an operation.
+   private static final long TIME_OUT_MS = 3000L;
+   private static final String SESSION_TAG = "test-session";
+   private final Object mWaitLock = new Object();
+
+   private Context mContext;
+   private MediaRouter mRouter;
+   private MediaSessionCompat mSession;
+   private MediaSessionCallback mSessionCallback = new MediaSessionCallback();
+
+   @Before
+   public void setUp() throws Exception {
+       getInstrumentation().runOnMainSync(new Runnable() {
+           @Override
+           public void run() {
+               mContext = getContext();
+               mRouter = MediaRouter.getInstance(mContext);
+               mSession = new MediaSessionCompat(mContext, SESSION_TAG);
+           }
+       });
+   }
+
+   @After
+   public void tearDown() throws Exception {
+       mSession.release();
+   }
+
+   /**
+    * This test checks whether the session callback work properly after setMediaSessionCompat() is
+    * called.
+    */
+   @Test
+   @SmallTest
+   public void testSessionCallbackAfterSetMediaSessionCompat() throws Exception {
+       getInstrumentation().runOnMainSync(new Runnable() {
+           @Override
+           public void run() {
+               mSession.setCallback(mSessionCallback);
+               mRouter.setMediaSessionCompat(mSession);
+           }
+       });
+
+       MediaControllerCompat controller = mSession.getController();
+       MediaControllerCompat.TransportControls controls = controller.getTransportControls();
+       synchronized (mWaitLock) {
+           mSessionCallback.reset();
+           controls.play();
+           mWaitLock.wait(TIME_OUT_MS);
+           assertTrue(mSessionCallback.mOnPlayCalled);
+
+           mSessionCallback.reset();
+           controls.pause();
+           mWaitLock.wait(TIME_OUT_MS);
+           assertTrue(mSessionCallback.mOnPauseCalled);
+       }
+   }
+
+   private class MediaSessionCallback extends MediaSessionCompat.Callback {
+       private boolean mOnPlayCalled;
+       private boolean mOnPauseCalled;
+
+       public void reset() {
+           mOnPlayCalled = false;
+           mOnPauseCalled = false;
+       }
+
+       @Override
+       public void onPlay() {
+           synchronized (mWaitLock) {
+               mOnPlayCalled = true;
+               mWaitLock.notify();
+           }
+       }
+
+       @Override
+       public void onPause() {
+           synchronized (mWaitLock) {
+               mOnPauseCalled = true;
+               mWaitLock.notify();
+           }
+       }
+   }
+}
\ No newline at end of file