1fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang/*
2fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang * Copyright 2018 The Android Open Source Project
3fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang *
4fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang * Licensed under the Apache License, Version 2.0 (the "License");
5fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang * you may not use this file except in compliance with the License.
6fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang * You may obtain a copy of the License at
7fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang *
8fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang *      http://www.apache.org/licenses/LICENSE-2.0
9fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang *
10fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang * Unless required by applicable law or agreed to in writing, software
11fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang * distributed under the License is distributed on an "AS IS" BASIS,
12fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang * See the License for the specific language governing permissions and
14fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang * limitations under the License.
15fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang */
16fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
17fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangpackage androidx.media;
18fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
19e18fafc56c49f683278d91e16a7246c7b1e01badHyundo Moonimport static org.junit.Assert.assertEquals;
20fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport static org.junit.Assert.assertFalse;
21fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport static org.junit.Assert.assertNotEquals;
22fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport static org.junit.Assert.assertNotNull;
23fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport static org.junit.Assert.assertNull;
24fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport static org.junit.Assert.assertTrue;
25fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport static org.junit.Assert.fail;
26fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
27fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.app.PendingIntent;
281df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moonimport android.content.Context;
29fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.content.Intent;
30fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.media.AudioManager;
31fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.net.Uri;
32fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.os.Build;
33fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.os.Bundle;
34fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.os.Handler;
35fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.os.HandlerThread;
36fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.os.Process;
37fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.os.ResultReceiver;
38fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.support.test.filters.FlakyTest;
39fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.support.test.filters.SdkSuppress;
40fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.support.test.filters.SmallTest;
41fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport android.support.test.runner.AndroidJUnit4;
42fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
43fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport androidx.annotation.NonNull;
44fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport androidx.media.MediaController2.ControllerCallback;
45c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kimimport androidx.media.MediaController2.PlaybackInfo;
46e57a84cc8a3c62a777d4dcf48d1c7f6e58657bf6Jaewan Kimimport androidx.media.MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback;
47fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport androidx.media.MediaSession2.ControllerInfo;
48fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport androidx.media.MediaSession2.SessionCallback;
49fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport androidx.media.TestServiceRegistry.SessionServiceCallback;
50fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport androidx.media.TestUtils.SyncHandler;
511df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moonimport androidx.testutils.PollingCheck;
52fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
53fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport org.junit.After;
54fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport org.junit.Before;
55fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport org.junit.Test;
56fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport org.junit.runner.RunWith;
57fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
58fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport java.lang.reflect.Method;
59fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport java.util.List;
60fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport java.util.concurrent.CountDownLatch;
61fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport java.util.concurrent.TimeUnit;
62fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangimport java.util.concurrent.atomic.AtomicReference;
63fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
64fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang/**
65fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang * Tests {@link MediaController2}.
66fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang */
67fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang// TODO(jaewan): Implement host-side test so controller and session can run in different processes.
68fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang// TODO(jaewan): Fix flaky failure -- see MediaController2Impl.getController()
69fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang// TODO(jaeawn): Revisit create/close session in the sHandler. It's no longer necessary.
700607eb1068e49e97490c8923b68b883f45dba399Hyundo Moon@SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN)
71fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang@RunWith(AndroidJUnit4.class)
72fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang@SmallTest
73fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang@FlakyTest
74fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kangpublic class MediaController2Test extends MediaSession2TestBase {
75fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    private static final String TAG = "MediaController2Test";
76fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
77fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    PendingIntent mIntent;
78fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    MediaSession2 mSession;
79fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    MediaController2 mController;
80fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    MockPlayer mPlayer;
81fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    MockPlaylistAgent mMockAgent;
821df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon    AudioManager mAudioManager;
83fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
84fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Before
85fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Override
86fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void setUp() throws Exception {
87fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        super.setUp();
88fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final Intent sessionActivity = new Intent(mContext, MockActivity.class);
89fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // Create this test specific MediaSession2 to use our own Handler.
90fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mIntent = PendingIntent.getActivity(mContext, 0, sessionActivity, 0);
91fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
92fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mPlayer = new MockPlayer(1);
93fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mMockAgent = new MockPlaylistAgent();
94fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mSession = new MediaSession2.Builder(mContext)
95fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
96fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlaylistAgent(mMockAgent)
97fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, new SessionCallback() {
98fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    @Override
99fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    public SessionCommandGroup2 onConnect(MediaSession2 session,
100fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                            ControllerInfo controller) {
101fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        if (Process.myUid() == controller.getUid()) {
102fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                            return super.onConnect(session, controller);
103fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        }
104fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        return null;
105fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    }
106fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
107fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    @Override
108fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    public void onPlaylistMetadataChanged(MediaSession2 session,
109fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                            MediaPlaylistAgent playlistAgent,
110fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                            MediaMetadata2 metadata) {
111fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        super.onPlaylistMetadataChanged(session, playlistAgent, metadata);
112fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    }
113fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                })
114fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionActivity(mIntent)
115fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId(TAG).build();
116fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController = createController(mSession.getToken());
1171df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
118fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        TestServiceRegistry.getInstance().setHandler(sHandler);
119fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
120fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
121fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @After
122fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Override
123fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void cleanUp() throws Exception {
124fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        super.cleanUp();
125fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        if (mSession != null) {
126fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            mSession.close();
127fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
128fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        TestServiceRegistry.getInstance().cleanUp();
129fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
130fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
131fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    /**
132fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     * Test if the {@link MediaSession2TestBase.TestControllerCallback} wraps the callback proxy
133fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     * without missing any method.
134fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     */
135fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
136fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testTestControllerCallback() {
137fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
138fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        Method[] methods = TestControllerCallback.class.getMethods();
139fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertNotNull(methods);
140fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        for (int i = 0; i < methods.length; i++) {
141fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            // For any methods in the controller callback, TestControllerCallback should have
142fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            // overriden the method and call matching API in the callback proxy.
143fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertNotEquals("TestControllerCallback should override " + methods[i]
144fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                            + " and call callback proxy",
145fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    ControllerCallback.class, methods[i].getDeclaringClass());
146fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
147fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
148fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
149fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
150fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testPlay() {
151fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
152fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.play();
153fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try {
154fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
155fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        } catch (InterruptedException e) {
156fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            fail(e.getMessage());
157fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
158fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mPlayer.mPlayCalled);
159fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
160fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
161fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
162fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testPause() {
163fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
164fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.pause();
165fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try {
166fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
167fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        } catch (InterruptedException e) {
168fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            fail(e.getMessage());
169fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
170fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mPlayer.mPauseCalled);
171fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
172fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
173fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
174fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testReset() {
175fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
176fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.reset();
177fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try {
178fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
179fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        } catch (InterruptedException e) {
180fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            fail(e.getMessage());
181fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
182fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mPlayer.mResetCalled);
183fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
184fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
185fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
186fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testPrepare() {
187fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
188fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.prepare();
189fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try {
190fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
191fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        } catch (InterruptedException e) {
192fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            fail(e.getMessage());
193fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
194fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mPlayer.mPrepareCalled);
195fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
196fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
197fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
198fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testSeekTo() {
199fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
200fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final long seekPosition = 12125L;
201fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.seekTo(seekPosition);
202fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try {
203fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(mPlayer.mCountDownLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
204fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        } catch (InterruptedException e) {
205fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            fail(e.getMessage());
206fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
207fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mPlayer.mSeekToCalled);
208fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(seekPosition, mPlayer.mSeekPosition);
209fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
210fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
211fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
212fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testGettersAfterConnected() throws InterruptedException {
213fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
2144c2e24f0a0e63fa260e959395d27b6e0ec95555aDongwon Kang        final int state = MediaPlayerInterface.PLAYER_STATE_PLAYING;
2154c2e24f0a0e63fa260e959395d27b6e0ec95555aDongwon Kang        final int bufferingState = MediaPlayerInterface.BUFFERING_STATE_BUFFERING_COMPLETE;
216fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final long position = 150000;
217fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final long bufferedPosition = 900000;
218fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final float speed = 0.5f;
2191a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        final long timeDiff = 102;
2203a151f1283d08b40c12e4a17903ba421f23c4342Hyundo Moon        final MediaItem2 currentMediaItem = TestUtils.createMediaItemWithMetadata();
221fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
222fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mPlayer.mLastPlayerState = state;
223ebc904f04b5f4c011ec791b1b0e94660ac02fdbaHyundo Moon        mPlayer.mLastBufferingState = bufferingState;
224fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mPlayer.mCurrentPosition = position;
225fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mPlayer.mBufferedPosition = bufferedPosition;
226fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mPlayer.mPlaybackSpeed = speed;
2273a151f1283d08b40c12e4a17903ba421f23c4342Hyundo Moon        mMockAgent.mCurrentMediaItem = currentMediaItem;
228fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
229fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        MediaController2 controller = createController(mSession.getToken());
2301a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        controller.setTimeDiff(timeDiff);
231fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(state, controller.getPlayerState());
232fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(bufferedPosition, controller.getBufferedPosition());
233e18fafc56c49f683278d91e16a7246c7b1e01badHyundo Moon        assertEquals(speed, controller.getPlaybackSpeed(), 0.0f);
2341a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        assertEquals(position + (long) (speed * timeDiff), controller.getCurrentPosition());
2353a151f1283d08b40c12e4a17903ba421f23c4342Hyundo Moon        assertEquals(currentMediaItem, controller.getCurrentMediaItem());
236fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
237fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
238fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
239c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim    public void testUpdatePlayer() throws InterruptedException {
240c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim        prepareLooper();
2414c2e24f0a0e63fa260e959395d27b6e0ec95555aDongwon Kang        final int testState = MediaPlayerInterface.PLAYER_STATE_PLAYING;
242c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim        final List<MediaItem2> testPlaylist = TestUtils.createPlaylist(3);
243c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim        final AudioAttributesCompat testAudioAttributes = new AudioAttributesCompat.Builder()
244c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim                .setLegacyStreamType(AudioManager.STREAM_RING).build();
245c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim        final CountDownLatch latch = new CountDownLatch(3);
246c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim        mController = createController(mSession.getToken(), true, new ControllerCallback() {
247c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim            @Override
248c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim            public void onPlayerStateChanged(MediaController2 controller, int state) {
249c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim                assertEquals(mController, controller);
250c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim                assertEquals(testState, state);
251c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim                latch.countDown();
252c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim            }
253c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim
254c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim            @Override
255c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim            public void onPlaylistChanged(MediaController2 controller, List<MediaItem2> list,
256c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim                    MediaMetadata2 metadata) {
257c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim                assertEquals(mController, controller);
258c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim                assertEquals(testPlaylist, list);
259c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim                assertNull(metadata);
260c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim                latch.countDown();
261c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim            }
262c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim
263c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim            @Override
264c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim            public void onPlaybackInfoChanged(MediaController2 controller, PlaybackInfo info) {
265c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim                assertEquals(mController, controller);
266c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim                assertEquals(testAudioAttributes, info.getAudioAttributes());
267c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim                latch.countDown();
268c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim            }
269c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim        });
270c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim
271c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim        MockPlayer player = new MockPlayer(0);
272c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim        player.mLastPlayerState = testState;
273c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim        player.setAudioAttributes(testAudioAttributes);
274c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim
275c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim        MockPlaylistAgent agent = new MockPlaylistAgent();
276c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim        agent.mPlaylist = testPlaylist;
277c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim
278c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim        mSession.updatePlayer(player, agent, null);
279c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
280c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim    }
281c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim
282c227e5c8c58de8656a0a31a1f48bf66e49c4a19dJaewan Kim    @Test
283fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testGetSessionActivity() {
284fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
285fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        PendingIntent sessionActivity = mController.getSessionActivity();
286fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(mContext.getPackageName(), sessionActivity.getCreatorPackage());
287fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(Process.myUid(), sessionActivity.getCreatorUid());
288fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
289fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
290fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
291fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testSetPlaylist() throws InterruptedException {
292fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
293fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final List<MediaItem2> list = TestUtils.createPlaylist(2);
294fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.setPlaylist(list, null /* Metadata */);
295fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
296fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
297fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mSetPlaylistCalled);
298fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertNull(mMockAgent.mMetadata);
299fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
300fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertNotNull(mMockAgent.mPlaylist);
301fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(list.size(), mMockAgent.mPlaylist.size());
302fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        for (int i = 0; i < list.size(); i++) {
303fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            // MediaController2.setPlaylist does not ensure the equality of the items.
304fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertEquals(list.get(i).getMediaId(), mMockAgent.mPlaylist.get(i).getMediaId());
305fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
306fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
307fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
308fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    /**
309fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     * This also tests {@link ControllerCallback#onPlaylistChanged(
310fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     * MediaController2, List, MediaMetadata2)}.
311fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     */
312fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
313fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testGetPlaylist() throws InterruptedException {
314fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
315fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final List<MediaItem2> testList = TestUtils.createPlaylist(2);
316fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final AtomicReference<List<MediaItem2>> listFromCallback = new AtomicReference<>();
317fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
318fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final ControllerCallback callback = new ControllerCallback() {
319fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
320fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onPlaylistChanged(MediaController2 controller,
321fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    List<MediaItem2> playlist, MediaMetadata2 metadata) {
322fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertNotNull(playlist);
323fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(testList.size(), playlist.size());
324fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                for (int i = 0; i < playlist.size(); i++) {
325fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    assertEquals(testList.get(i).getMediaId(), playlist.get(i).getMediaId());
326fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                }
327fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                listFromCallback.set(playlist);
328fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
329fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
330fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
331fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaPlaylistAgent agent = new MockPlaylistAgent() {
332fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
333fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public List<MediaItem2> getPlaylist() {
334fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                return testList;
335fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
336fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
337fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try (MediaSession2 session = new MediaSession2.Builder(mContext)
338fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
339fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId("testControllerCallback_onPlaylistChanged")
340fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, new SessionCallback() {})
341fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlaylistAgent(agent)
342fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .build()) {
343fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            MediaController2 controller = createController(
344fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    session.getToken(), true, callback);
345fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            agent.notifyPlaylistChanged();
346fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
347fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertEquals(listFromCallback.get(), controller.getPlaylist());
348fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
349fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
350fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
351fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
352fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testUpdatePlaylistMetadata() throws InterruptedException {
353fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
354fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaMetadata2 testMetadata = TestUtils.createMetadata();
355fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.updatePlaylistMetadata(testMetadata);
356fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
357fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
358fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mUpdatePlaylistMetadataCalled);
359fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertNotNull(mMockAgent.mMetadata);
360fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(testMetadata.getMediaId(), mMockAgent.mMetadata.getMediaId());
361fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
362fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
363fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
364fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testGetPlaylistMetadata() throws InterruptedException {
365fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
366fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaMetadata2 testMetadata = TestUtils.createMetadata();
367fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final AtomicReference<MediaMetadata2> metadataFromCallback = new AtomicReference<>();
368fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
369fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final ControllerCallback callback = new ControllerCallback() {
370fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
371fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onPlaylistMetadataChanged(MediaController2 controller,
372fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    MediaMetadata2 metadata) {
373fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertNotNull(testMetadata);
374fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(testMetadata.getMediaId(), metadata.getMediaId());
375fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                metadataFromCallback.set(metadata);
376fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
377fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
378fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
379fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaPlaylistAgent agent = new MockPlaylistAgent() {
380fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
381fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public MediaMetadata2 getPlaylistMetadata() {
382fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                return testMetadata;
383fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
384fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
385fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try (MediaSession2 session = new MediaSession2.Builder(mContext)
386fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
387fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId("testGetPlaylistMetadata")
388fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, new SessionCallback() {})
389fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlaylistAgent(agent)
390fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .build()) {
391fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            MediaController2 controller = createController(session.getToken(), true, callback);
392fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            agent.notifyPlaylistMetadataChanged();
393fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
394fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertEquals(metadataFromCallback.get().getMediaId(),
395fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    controller.getPlaylistMetadata().getMediaId());
396fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
397fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
398fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
399e18fafc56c49f683278d91e16a7246c7b1e01badHyundo Moon    @Test
400e18fafc56c49f683278d91e16a7246c7b1e01badHyundo Moon    public void testSetPlaybackSpeed() throws Exception {
401e18fafc56c49f683278d91e16a7246c7b1e01badHyundo Moon        prepareLooper();
402e18fafc56c49f683278d91e16a7246c7b1e01badHyundo Moon        final float speed = 1.5f;
403e18fafc56c49f683278d91e16a7246c7b1e01badHyundo Moon        mController.setPlaybackSpeed(speed);
404e18fafc56c49f683278d91e16a7246c7b1e01badHyundo Moon        assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
405e18fafc56c49f683278d91e16a7246c7b1e01badHyundo Moon        assertEquals(speed, mPlayer.mPlaybackSpeed, 0.0f);
406e18fafc56c49f683278d91e16a7246c7b1e01badHyundo Moon    }
407e18fafc56c49f683278d91e16a7246c7b1e01badHyundo Moon
408fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    /**
409fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     * Test whether {@link MediaSession2#setPlaylist(List, MediaMetadata2)} is notified
410fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     * through the
411fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     * {@link ControllerCallback#onPlaylistMetadataChanged(MediaController2, MediaMetadata2)}
412fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     * if the controller doesn't have {@link SessionCommand2#COMMAND_CODE_PLAYLIST_GET_LIST} but
413fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     * {@link SessionCommand2#COMMAND_CODE_PLAYLIST_GET_LIST_METADATA}.
414fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     */
415fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
416fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testControllerCallback_onPlaylistMetadataChanged() throws InterruptedException {
417fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
418fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaItem2 item = TestUtils.createMediaItemWithMetadata();
419fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final List<MediaItem2> list = TestUtils.createPlaylist(2);
420fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
421fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final ControllerCallback callback = new ControllerCallback() {
422fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
423fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onPlaylistMetadataChanged(MediaController2 controller,
424fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    MediaMetadata2 metadata) {
425fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertNotNull(metadata);
426fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(item.getMediaId(), metadata.getMediaId());
427fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
428fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
429fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
430fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SessionCallback sessionCallback = new SessionCallback() {
431fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
432fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public SessionCommandGroup2 onConnect(MediaSession2 session,
433fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    ControllerInfo controller) {
434fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                if (Process.myUid() == controller.getUid()) {
435fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    SessionCommandGroup2 commands = new SessionCommandGroup2();
436fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    commands.addCommand(new SessionCommand2(
437fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                              SessionCommand2.COMMAND_CODE_PLAYLIST_GET_LIST_METADATA));
438fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    return commands;
439fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                }
440fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                return super.onConnect(session, controller);
441fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
442fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
443fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaPlaylistAgent agent = new MockPlaylistAgent() {
444fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
445fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public MediaMetadata2 getPlaylistMetadata() {
446fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                return item.getMetadata();
447fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
448fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
449fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
450fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public List<MediaItem2> getPlaylist() {
451fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                return list;
452fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
453fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
454fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try (MediaSession2 session = new MediaSession2.Builder(mContext)
455fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
456fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId("testControllerCallback_onPlaylistMetadataChanged")
457fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, sessionCallback)
458fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlaylistAgent(agent)
459fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .build()) {
460fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            MediaController2 controller = createController(session.getToken(), true, callback);
461fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            agent.notifyPlaylistMetadataChanged();
462fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
463fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
464fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
465fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
4661a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim
4671a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim    @Test
4681a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim    public void testControllerCallback_onSeekCompleted() throws InterruptedException {
4691a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        prepareLooper();
4701a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        final long testSeekPosition = 400;
4711a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        final long testPosition = 500;
4721a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        final CountDownLatch latch = new CountDownLatch(1);
4731a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        final ControllerCallback callback = new ControllerCallback() {
4741a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim            @Override
4751a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim            public void onSeekCompleted(MediaController2 controller, long position) {
4761a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim                controller.setTimeDiff(Long.valueOf(0));
4771a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim                assertEquals(testSeekPosition, position);
4781a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim                assertEquals(testPosition, controller.getCurrentPosition());
4791a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim                latch.countDown();
4801a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim            }
4811a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        };
4821a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        final MediaController2 controller = createController(mSession.getToken(), true, callback);
4831a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        mPlayer.mCurrentPosition = testPosition;
4841a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        mPlayer.notifySeekCompleted(testSeekPosition);
4851a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
4861a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim    }
4871a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim
4881a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim    @Test
4891a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim    public void testControllerCallback_onBufferingStateChanged() throws InterruptedException {
4901a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        prepareLooper();
4911a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        final List<MediaItem2> testPlaylist = TestUtils.createPlaylist(3);
4921a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        final MediaItem2 testItem = testPlaylist.get(0);
4934c2e24f0a0e63fa260e959395d27b6e0ec95555aDongwon Kang        final int testBufferingState = MediaPlayerInterface.BUFFERING_STATE_BUFFERING_AND_PLAYABLE;
4941a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        final long testBufferingPosition = 500;
4951a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        final CountDownLatch latch = new CountDownLatch(1);
4961a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        final ControllerCallback callback = new ControllerCallback() {
4971a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim            @Override
4981a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim            public void onBufferingStateChanged(MediaController2 controller, MediaItem2 item,
4991a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim                    int state) {
5001a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim                controller.setTimeDiff(Long.valueOf(0));
5011a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim                assertEquals(testItem, item);
5021a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim                assertEquals(testBufferingState, state);
5031a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim                assertEquals(testBufferingState, controller.getBufferingState());
5041a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim                assertEquals(testBufferingPosition, controller.getBufferedPosition());
5051a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim                latch.countDown();
5061a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim            }
5071a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        };
5081a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        final MediaController2 controller = createController(mSession.getToken(), true, callback);
5091a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        mSession.setPlaylist(testPlaylist, null);
5101a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        mPlayer.mBufferedPosition = testBufferingPosition;
5111a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        mPlayer.notifyBufferingStateChanged(testItem.getDataSourceDesc(), testBufferingState);
5121a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
5131a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim    }
5141a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim
5151a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim    @Test
5161a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim    public void testControllerCallback_onPlayerStateChanged() throws InterruptedException {
5171a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        prepareLooper();
5184c2e24f0a0e63fa260e959395d27b6e0ec95555aDongwon Kang        final int testPlayerState = MediaPlayerInterface.PLAYER_STATE_PLAYING;
5191a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        final long testPosition = 500;
5201a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        final CountDownLatch latch = new CountDownLatch(1);
5211a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        final ControllerCallback callback = new ControllerCallback() {
5221a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim            @Override
5231a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim            public void onPlayerStateChanged(MediaController2 controller, int state) {
5241a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim                controller.setTimeDiff(Long.valueOf(0));
5251a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim                assertEquals(testPlayerState, state);
5261a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim                assertEquals(testPlayerState, controller.getPlayerState());
5271a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim                assertEquals(testPosition, controller.getCurrentPosition());
5281a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim                latch.countDown();
5291a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim            }
5301a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        };
5311a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        final MediaController2 controller = createController(mSession.getToken(), true, callback);
5321a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        mPlayer.mCurrentPosition = testPosition;
5331a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        mPlayer.notifyPlaybackState(testPlayerState);
5341a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
5351a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim    }
5361a125123e09a1f0e2991b1fce907970d8993667eJaewan Kim
537fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
538fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testAddPlaylistItem() throws InterruptedException {
539fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
540fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int testIndex = 12;
541fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaItem2 testMediaItem = TestUtils.createMediaItemWithMetadata();
542fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.addPlaylistItem(testIndex, testMediaItem);
543fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
544fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
545fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mAddPlaylistItemCalled);
546fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(testIndex, mMockAgent.mIndex);
547fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // MediaController2.addPlaylistItem does not ensure the equality of the items.
548fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(testMediaItem.getMediaId(), mMockAgent.mItem.getMediaId());
549fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
550fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
551fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
552fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testRemovePlaylistItem() throws InterruptedException {
553fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
554fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mMockAgent.mPlaylist = TestUtils.createPlaylist(2);
555fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
556fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // Recreate controller for sending removePlaylistItem.
557fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // It's easier to ensure that MediaController2.getPlaylist() returns the playlist from the
558fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // agent.
559fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        MediaController2 controller = createController(mSession.getToken());
560fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        MediaItem2 targetItem = controller.getPlaylist().get(0);
561fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        controller.removePlaylistItem(targetItem);
562fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
563fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
564fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mRemovePlaylistItemCalled);
565fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(targetItem, mMockAgent.mItem);
566fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
567fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
568fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
569fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testReplacePlaylistItem() throws InterruptedException {
570fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
571fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int testIndex = 12;
572fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaItem2 testMediaItem = TestUtils.createMediaItemWithMetadata();
573fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.replacePlaylistItem(testIndex, testMediaItem);
574fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
575fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
576fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mReplacePlaylistItemCalled);
577fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // MediaController2.replacePlaylistItem does not ensure the equality of the items.
578fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(testMediaItem.getMediaId(), mMockAgent.mItem.getMediaId());
579fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
580fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
581fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
582fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testSkipToPreviousItem() throws InterruptedException {
583fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
584fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.skipToPreviousItem();
585fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
586fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mSkipToPreviousItemCalled);
587fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
588fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
589fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
590fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testSkipToNextItem() throws InterruptedException {
591fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
592fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.skipToNextItem();
593fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
594fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mSkipToNextItemCalled);
595fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
596fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
597fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
598fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testSkipToPlaylistItem() throws InterruptedException {
599fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
600fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        MediaController2 controller = createController(mSession.getToken());
601fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        MediaItem2 targetItem = TestUtils.createMediaItemWithMetadata();
602fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        controller.skipToPlaylistItem(targetItem);
603fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
604fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
605fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mSkipToPlaylistItemCalled);
606fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(targetItem, mMockAgent.mItem);
607fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
608fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
609fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    /**
610fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     * This also tests {@link ControllerCallback#onShuffleModeChanged(MediaController2, int)}.
611fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     */
612fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
613fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testGetShuffleMode() throws InterruptedException {
614fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
615fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int testShuffleMode = MediaPlaylistAgent.SHUFFLE_MODE_GROUP;
616fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaPlaylistAgent agent = new MockPlaylistAgent() {
617fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
618fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public int getShuffleMode() {
619fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                return testShuffleMode;
620fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
621fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
622fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
623fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final ControllerCallback callback = new ControllerCallback() {
624fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
625fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onShuffleModeChanged(MediaController2 controller, int shuffleMode) {
626fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(testShuffleMode, shuffleMode);
627fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
628fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
629fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
630fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mSession.updatePlayer(mPlayer, agent, null);
631fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        MediaController2 controller = createController(mSession.getToken(), true, callback);
632fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        agent.notifyShuffleModeChanged();
633fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
634fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(testShuffleMode, controller.getShuffleMode());
635fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
636fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
637fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
638fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testSetShuffleMode() throws InterruptedException {
639fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
640fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int testShuffleMode = MediaPlaylistAgent.SHUFFLE_MODE_GROUP;
641fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.setShuffleMode(testShuffleMode);
642fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
643fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
644fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mSetShuffleModeCalled);
645fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(testShuffleMode, mMockAgent.mShuffleMode);
646fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
647fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
648fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    /**
649fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     * This also tests {@link ControllerCallback#onRepeatModeChanged(MediaController2, int)}.
650fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     */
651fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
652fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testGetRepeatMode() throws InterruptedException {
653fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
654fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int testRepeatMode = MediaPlaylistAgent.REPEAT_MODE_GROUP;
655fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaPlaylistAgent agent = new MockPlaylistAgent() {
656fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
657fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public int getRepeatMode() {
658fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                return testRepeatMode;
659fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
660fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
661fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
662fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final ControllerCallback callback = new ControllerCallback() {
663fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
664fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onRepeatModeChanged(MediaController2 controller, int repeatMode) {
665fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(testRepeatMode, repeatMode);
666fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
667fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
668fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
669fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mSession.updatePlayer(mPlayer, agent, null);
670fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        MediaController2 controller = createController(mSession.getToken(), true, callback);
671fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        agent.notifyRepeatModeChanged();
672fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
673fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(testRepeatMode, controller.getRepeatMode());
674fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
675fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
676fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
677fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testSetRepeatMode() throws InterruptedException {
678fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
679fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int testRepeatMode = MediaPlaylistAgent.REPEAT_MODE_GROUP;
680fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.setRepeatMode(testRepeatMode);
681fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
682fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
683fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mMockAgent.mSetRepeatModeCalled);
684fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(testRepeatMode, mMockAgent.mRepeatMode);
685fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
686fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
687fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
688fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testSetVolumeTo() throws Exception {
689fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
690fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int maxVolume = 100;
691fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int currentVolume = 23;
692fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int volumeControlType = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE;
693fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        TestVolumeProvider volumeProvider =
694fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                new TestVolumeProvider(volumeControlType, maxVolume, currentVolume);
695fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
696fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mSession.updatePlayer(new MockPlayer(0), null, volumeProvider);
697fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaController2 controller = createController(mSession.getToken(), true, null);
698fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
699fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int targetVolume = 50;
700fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        controller.setVolumeTo(targetVolume, 0 /* flags */);
701fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(volumeProvider.mLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
702fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(volumeProvider.mSetVolumeToCalled);
703fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(targetVolume, volumeProvider.mVolume);
704fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
705fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
706fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
707fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testAdjustVolume() throws Exception {
708fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
709fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int maxVolume = 100;
710fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int currentVolume = 23;
711fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int volumeControlType = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE;
712fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        TestVolumeProvider volumeProvider =
713fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                new TestVolumeProvider(volumeControlType, maxVolume, currentVolume);
714fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
715fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mSession.updatePlayer(new MockPlayer(0), null, volumeProvider);
716fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaController2 controller = createController(mSession.getToken(), true, null);
717fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
718fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int direction = AudioManager.ADJUST_RAISE;
719fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        controller.adjustVolume(direction, 0 /* flags */);
720fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(volumeProvider.mLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
721fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(volumeProvider.mAdjustVolumeCalled);
722fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(direction, volumeProvider.mDirection);
723fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
724fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
725fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
7261df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon    public void testSetVolumeWithLocalVolume() throws Exception {
7271df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        prepareLooper();
7281df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        if (Build.VERSION.SDK_INT >= 21 && mAudioManager.isVolumeFixed()) {
7291df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon            // This test is not eligible for this device.
7301df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon            return;
7311df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        }
7321df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon
7331df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        // Here, we intentionally choose STREAM_ALARM in order not to consider
7341df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        // 'Do Not Disturb' or 'Volume limit'.
7351df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        final int stream = AudioManager.STREAM_ALARM;
7361df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        final int maxVolume = mAudioManager.getStreamMaxVolume(stream);
7371df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        final int minVolume = 0;
7381df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        if (maxVolume <= minVolume) {
7391df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon            return;
7401df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        }
7411df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon
7421df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        // Set stream of the session.
7431df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        AudioAttributesCompat attrs = new AudioAttributesCompat.Builder()
7441df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon                .setLegacyStreamType(stream)
7451df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon                .build();
7461df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        mPlayer.setAudioAttributes(attrs);
7471df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        mSession.updatePlayer(mPlayer, null, null);
7481df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon
7491df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        final int originalVolume = mAudioManager.getStreamVolume(stream);
7501df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        final int targetVolume = originalVolume == minVolume
7511df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon                ? originalVolume + 1 : originalVolume - 1;
7521df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon
7531df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        mController.setVolumeTo(targetVolume, AudioManager.FLAG_SHOW_UI);
7541df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        new PollingCheck(WAIT_TIME_MS) {
7551df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon            @Override
7561df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon            protected boolean check() {
7571df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon                return targetVolume == mAudioManager.getStreamVolume(stream);
7581df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon            }
7591df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        }.run();
7601df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon
7611df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        // Set back to original volume.
7621df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        mAudioManager.setStreamVolume(stream, originalVolume, 0 /* flags */);
7631df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon    }
7641df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon
7651df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon    @Test
7661df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon    public void testAdjustVolumeWithLocalVolume() throws Exception {
7671df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        prepareLooper();
7681df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        if (Build.VERSION.SDK_INT >= 21 && mAudioManager.isVolumeFixed()) {
7691df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon            // This test is not eligible for this device.
7701df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon            return;
7711df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        }
7721df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon
7731df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        // Here, we intentionally choose STREAM_ALARM in order not to consider
7741df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        // 'Do Not Disturb' or 'Volume limit'.
7751df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        final int stream = AudioManager.STREAM_ALARM;
7761df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        final int maxVolume = mAudioManager.getStreamMaxVolume(stream);
7771df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        final int minVolume = 0;
7781df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        if (maxVolume <= minVolume) {
7791df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon            return;
7801df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        }
7811df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon
7821df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        // Set stream of the session.
7831df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        AudioAttributesCompat attrs = new AudioAttributesCompat.Builder()
7841df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon                .setLegacyStreamType(stream)
7851df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon                .build();
7861df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        mPlayer.setAudioAttributes(attrs);
7871df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        mSession.updatePlayer(mPlayer, null, null);
7881df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon
7891df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        final int originalVolume = mAudioManager.getStreamVolume(stream);
7901df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        final int direction = originalVolume == minVolume
7911df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon                ? AudioManager.ADJUST_RAISE : AudioManager.ADJUST_LOWER;
7921df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        final int targetVolume = originalVolume + direction;
7931df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon
7941df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        mController.adjustVolume(direction, AudioManager.FLAG_SHOW_UI);
7951df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        new PollingCheck(WAIT_TIME_MS) {
7961df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon            @Override
7971df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon            protected boolean check() {
7981df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon                return targetVolume == mAudioManager.getStreamVolume(stream);
7991df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon            }
8001df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        }.run();
8011df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon
8021df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        // Set back to original volume.
8031df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon        mAudioManager.setStreamVolume(stream, originalVolume, 0 /* flags */);
8041df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon    }
8051df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon
8061df65e9a40c933daca477b2c9d1d28389fa66aecHyundo Moon    @Test
807fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testGetPackageName() {
808fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
809fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(mContext.getPackageName(), mController.getSessionToken().getPackageName());
810fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
811fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
812fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
813fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testSendCustomCommand() throws InterruptedException {
814fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
815fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // TODO(jaewan): Need to revisit with the permission.
816fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SessionCommand2 testCommand =
817fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                new SessionCommand2(SessionCommand2.COMMAND_CODE_PLAYBACK_PREPARE);
818fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final Bundle testArgs = new Bundle();
819fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testArgs.putString("args", "testSendCustomCommand");
820fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
821fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
822fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SessionCallback callback = new SessionCallback() {
823fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
824fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onCustomCommand(MediaSession2 session, ControllerInfo controller,
825fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    SessionCommand2 customCommand, Bundle args, ResultReceiver cb) {
826fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(mContext.getPackageName(), controller.getPackageName());
827fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(testCommand, customCommand);
828fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertTrue(TestUtils.equals(testArgs, args));
829fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertNull(cb);
830fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
831fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
832fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
833fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mSession.close();
834fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer)
835fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, callback).setId(TAG).build();
836fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaController2 controller = createController(mSession.getToken());
837fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        controller.sendCustomCommand(testCommand, testArgs, null);
838fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
839fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
840fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
841fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
842fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testControllerCallback_onConnected() throws InterruptedException {
843fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
844fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // createController() uses controller callback to wait until the controller becomes
845fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // available.
846fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        MediaController2 controller = createController(mSession.getToken());
847fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertNotNull(controller);
848fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
849fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
850fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
851fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testControllerCallback_sessionRejects() throws InterruptedException {
852fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
853fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final MediaSession2.SessionCallback sessionCallback = new SessionCallback() {
854fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
855fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public SessionCommandGroup2 onConnect(MediaSession2 session,
856fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    ControllerInfo controller) {
857fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                return null;
858fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
859fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
860fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        sHandler.postAndSync(new Runnable() {
861fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
862fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void run() {
863fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                mSession.close();
864fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer)
865fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        .setSessionCallback(sHandlerExecutor, sessionCallback).build();
866fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
867fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        });
868fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        MediaController2 controller =
869fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                createController(mSession.getToken(), false, null);
870fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertNotNull(controller);
871fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        waitForConnect(controller, false);
872fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        waitForDisconnect(controller, true);
873fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
874fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
875fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
876fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testControllerCallback_releaseSession() throws InterruptedException {
877fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
878fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mSession.close();
879fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        waitForDisconnect(mController, true);
880fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
881fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
882fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
883fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testControllerCallback_close() throws InterruptedException {
884fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
885fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.close();
886fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        waitForDisconnect(mController, true);
887fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
888fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
889fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
890fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testFastForward() throws InterruptedException {
891fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
892fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
893fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SessionCallback callback = new SessionCallback() {
894fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
895fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onFastForward(MediaSession2 session, ControllerInfo controller) {
896fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(mContext.getPackageName(), controller.getPackageName());
897fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
898fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
899fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
900fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try (MediaSession2 session = new MediaSession2.Builder(mContext)
901fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
902fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, callback)
903fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId("testFastForward").build()) {
904fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            MediaController2 controller = createController(session.getToken());
905fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            controller.fastForward();
906fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
907fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
908fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
909fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
910fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
911fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testRewind() throws InterruptedException {
912fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
913fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
914fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SessionCallback callback = new SessionCallback() {
915fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
916fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onRewind(MediaSession2 session, ControllerInfo controller) {
917fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(mContext.getPackageName(), controller.getPackageName());
918fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
919fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
920fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
921fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try (MediaSession2 session = new MediaSession2.Builder(mContext)
922fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
923fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, callback)
924fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId("testRewind").build()) {
925fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            MediaController2 controller = createController(session.getToken());
926fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            controller.rewind();
927fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
928fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
929fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
930fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
931fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
932fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testPlayFromSearch() throws InterruptedException {
933fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
934fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final String request = "random query";
935fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final Bundle bundle = new Bundle();
936fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        bundle.putString("key", "value");
937fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
938fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SessionCallback callback = new SessionCallback() {
939fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
940fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onPlayFromSearch(MediaSession2 session, ControllerInfo controller,
941fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    String query, Bundle extras) {
942fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                super.onPlayFromSearch(session, controller, query, extras);
943fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(mContext.getPackageName(), controller.getPackageName());
944fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(request, query);
945fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertTrue(TestUtils.equals(bundle, extras));
946fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
947fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
948fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
949fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try (MediaSession2 session = new MediaSession2.Builder(mContext)
950fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
951fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, callback)
952fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId("testPlayFromSearch").build()) {
953fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            MediaController2 controller = createController(session.getToken());
954fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            controller.playFromSearch(request, bundle);
955fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
956fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
957fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
958fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
959fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
960fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testPlayFromUri() throws InterruptedException {
961fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
962fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final Uri request = Uri.parse("foo://boo");
963fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final Bundle bundle = new Bundle();
964fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        bundle.putString("key", "value");
965fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
966fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SessionCallback callback = new SessionCallback() {
967fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
968fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onPlayFromUri(MediaSession2 session, ControllerInfo controller, Uri uri,
969fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    Bundle extras) {
970fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(mContext.getPackageName(), controller.getPackageName());
971fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(request, uri);
972fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertTrue(TestUtils.equals(bundle, extras));
973fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
974fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
975fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
976fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try (MediaSession2 session = new MediaSession2.Builder(mContext)
977fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
978fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, callback)
979fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId("testPlayFromUri").build()) {
980fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            MediaController2 controller = createController(session.getToken());
981fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            controller.playFromUri(request, bundle);
982fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
983fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
984fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
985fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
986fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
987fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testPlayFromMediaId() throws InterruptedException {
988fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
989fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final String request = "media_id";
990fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final Bundle bundle = new Bundle();
991fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        bundle.putString("key", "value");
992fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
993fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SessionCallback callback = new SessionCallback() {
994fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
995fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onPlayFromMediaId(MediaSession2 session, ControllerInfo controller,
996fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    String mediaId, Bundle extras) {
997fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(mContext.getPackageName(), controller.getPackageName());
998fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(request, mediaId);
999fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertTrue(TestUtils.equals(bundle, extras));
1000fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
1001fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
1002fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
1003fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try (MediaSession2 session = new MediaSession2.Builder(mContext)
1004fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
1005fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, callback)
1006fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId("testPlayFromMediaId").build()) {
1007fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            MediaController2 controller = createController(session.getToken());
1008fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            controller.playFromMediaId(request, bundle);
1009fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
1010fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
1011fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1012fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1013fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
1014fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testPrepareFromSearch() throws InterruptedException {
1015fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1016fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final String request = "random query";
1017fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final Bundle bundle = new Bundle();
1018fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        bundle.putString("key", "value");
1019fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
1020fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SessionCallback callback = new SessionCallback() {
1021fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
1022fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onPrepareFromSearch(MediaSession2 session, ControllerInfo controller,
1023fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    String query, Bundle extras) {
1024fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(mContext.getPackageName(), controller.getPackageName());
1025fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(request, query);
1026fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertTrue(TestUtils.equals(bundle, extras));
1027fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
1028fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
1029fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
1030fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try (MediaSession2 session = new MediaSession2.Builder(mContext)
1031fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
1032fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, callback)
1033fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId("testPrepareFromSearch").build()) {
1034fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            MediaController2 controller = createController(session.getToken());
1035fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            controller.prepareFromSearch(request, bundle);
1036fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
1037fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
1038fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1039fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1040fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
1041fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testPrepareFromUri() throws InterruptedException {
1042fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1043fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final Uri request = Uri.parse("foo://boo");
1044fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final Bundle bundle = new Bundle();
1045fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        bundle.putString("key", "value");
1046fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
1047fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SessionCallback callback = new SessionCallback() {
1048fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
1049fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onPrepareFromUri(MediaSession2 session, ControllerInfo controller, Uri uri,
1050fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    Bundle extras) {
1051fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(mContext.getPackageName(), controller.getPackageName());
1052fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(request, uri);
1053fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertTrue(TestUtils.equals(bundle, extras));
1054fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
1055fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
1056fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
1057fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try (MediaSession2 session = new MediaSession2.Builder(mContext)
1058fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
1059fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, callback)
1060fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId("testPrepareFromUri").build()) {
1061fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            MediaController2 controller = createController(session.getToken());
1062fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            controller.prepareFromUri(request, bundle);
1063fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
1064fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
1065fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1066fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1067fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
1068fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testPrepareFromMediaId() throws InterruptedException {
1069fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1070fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final String request = "media_id";
1071fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final Bundle bundle = new Bundle();
1072fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        bundle.putString("key", "value");
1073fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
1074fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SessionCallback callback = new SessionCallback() {
1075fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
1076fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onPrepareFromMediaId(MediaSession2 session, ControllerInfo controller,
1077fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    String mediaId, Bundle extras) {
1078fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(mContext.getPackageName(), controller.getPackageName());
1079fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(request, mediaId);
1080fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertTrue(TestUtils.equals(bundle, extras));
1081fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
1082fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
1083fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
1084fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try (MediaSession2 session = new MediaSession2.Builder(mContext)
1085fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
1086fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, callback)
1087fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId("testPrepareFromMediaId").build()) {
1088fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            MediaController2 controller = createController(session.getToken());
1089fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            controller.prepareFromMediaId(request, bundle);
1090fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
1091fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
1092fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1093fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1094fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
1095fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testSetRating() throws InterruptedException {
1096fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1097fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final int ratingType = Rating2.RATING_5_STARS;
1098fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final float ratingValue = 3.5f;
1099fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final Rating2 rating = Rating2.newStarRating(ratingType, ratingValue);
1100fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final String mediaId = "media_id";
1101fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1102fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
1103fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SessionCallback callback = new SessionCallback() {
1104fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
1105fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onSetRating(MediaSession2 session, ControllerInfo controller,
1106fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    String mediaIdOut, Rating2 ratingOut) {
1107fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(mContext.getPackageName(), controller.getPackageName());
1108fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(mediaId, mediaIdOut);
1109fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                assertEquals(rating, ratingOut);
1110fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
1111fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
1112fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
1113fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1114fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try (MediaSession2 session = new MediaSession2.Builder(mContext)
1115fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
1116fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, callback)
1117fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId("testSetRating").build()) {
1118fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            MediaController2 controller = createController(session.getToken());
1119fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            controller.setRating(mediaId, rating);
1120fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
1121fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
1122fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1123fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1124fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
1125fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testIsConnected() throws InterruptedException {
1126fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1127fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mController.isConnected());
1128fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        sHandler.postAndSync(new Runnable() {
1129fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
1130fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void run() {
1131fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                mSession.close();
1132fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
1133fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        });
1134fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        waitForDisconnect(mController, true);
1135fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertFalse(mController.isConnected());
1136fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1137fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1138fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    /**
1139fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     * Test potential deadlock for calls between controller and session.
1140fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang     */
1141fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
1142fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testDeadlock() throws InterruptedException {
1143fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1144fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        sHandler.postAndSync(new Runnable() {
1145fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
1146fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void run() {
1147fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                mSession.close();
1148fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                mSession = null;
1149fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
1150fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        });
1151fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1152fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // Two more threads are needed not to block test thread nor test wide thread (sHandler).
1153fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final HandlerThread sessionThread = new HandlerThread("testDeadlock_session");
1154fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final HandlerThread testThread = new HandlerThread("testDeadlock_test");
1155fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        sessionThread.start();
1156fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testThread.start();
1157fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final SyncHandler sessionHandler = new SyncHandler(sessionThread.getLooper());
1158fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final Handler testHandler = new Handler(testThread.getLooper());
1159fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
1160fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        try {
1161fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            final MockPlayer player = new MockPlayer(0);
1162fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            sessionHandler.postAndSync(new Runnable() {
1163fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                @Override
1164fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                public void run() {
1165fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    mSession = new MediaSession2.Builder(mContext)
1166fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                            .setPlayer(mPlayer)
1167fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                            .setSessionCallback(sHandlerExecutor, new SessionCallback() {})
1168fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                            .setId("testDeadlock").build();
1169fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                }
1170fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            });
1171fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            final MediaController2 controller = createController(mSession.getToken());
1172fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            testHandler.post(new Runnable() {
1173fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                @Override
1174fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                public void run() {
11754c2e24f0a0e63fa260e959395d27b6e0ec95555aDongwon Kang                    final int state = MediaPlayerInterface.PLAYER_STATE_ERROR;
1176fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    for (int i = 0; i < 100; i++) {
1177fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        // triggers call from session to controller.
1178fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        player.notifyPlaybackState(state);
1179fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        // triggers call from controller to session.
1180fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        controller.play();
1181fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1182fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        // Repeat above
1183fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        player.notifyPlaybackState(state);
1184fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        controller.pause();
1185fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        player.notifyPlaybackState(state);
1186fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        controller.reset();
1187fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        player.notifyPlaybackState(state);
1188fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        controller.skipToNextItem();
1189fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        player.notifyPlaybackState(state);
1190fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        controller.skipToPreviousItem();
1191fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    }
1192fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    // This may hang if deadlock happens.
1193fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    latch.countDown();
1194fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                }
1195fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            });
1196fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
1197fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        } finally {
1198fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            if (mSession != null) {
1199fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                sessionHandler.postAndSync(new Runnable() {
1200fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    @Override
1201fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    public void run() {
1202fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        // Clean up here because sessionHandler will be removed afterwards.
1203fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        mSession.close();
1204fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        mSession = null;
1205fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    }
1206fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                });
1207fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
12080607eb1068e49e97490c8923b68b883f45dba399Hyundo Moon
12090607eb1068e49e97490c8923b68b883f45dba399Hyundo Moon            if (Build.VERSION.SDK_INT >= 18) {
1210fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                sessionThread.quitSafely();
1211fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                testThread.quitSafely();
12120607eb1068e49e97490c8923b68b883f45dba399Hyundo Moon            } else {
12130607eb1068e49e97490c8923b68b883f45dba399Hyundo Moon                sessionThread.quit();
12140607eb1068e49e97490c8923b68b883f45dba399Hyundo Moon                testThread.quit();
1215fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
1216fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
1217fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1218fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1219fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
1220fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testGetServiceToken() {
1221fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1222fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        SessionToken2 token = TestUtils.getServiceToken(mContext, MockMediaSessionService2.ID);
1223fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertNotNull(token);
1224fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(mContext.getPackageName(), token.getPackageName());
1225fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(MockMediaSessionService2.ID, token.getId());
1226fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertEquals(SessionToken2.TYPE_SESSION_SERVICE, token.getType());
1227fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1228fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1229fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
1230fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testConnectToService_sessionService() throws InterruptedException {
1231fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1232fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testConnectToService(MockMediaSessionService2.ID);
1233fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1234fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1235fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
1236fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testConnectToService_libraryService() throws InterruptedException {
1237fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1238fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testConnectToService(MockMediaLibraryService2.ID);
1239fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1240fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1241fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testConnectToService(String id) throws InterruptedException {
1242fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1243fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
1244e57a84cc8a3c62a777d4dcf48d1c7f6e58657bf6Jaewan Kim        final MediaLibrarySessionCallback sessionCallback = new MediaLibrarySessionCallback() {
1245fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
1246fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public SessionCommandGroup2 onConnect(@NonNull MediaSession2 session,
1247fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    @NonNull ControllerInfo controller) {
1248fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                if (Process.myUid() == controller.getUid()) {
1249fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    if (mSession != null) {
1250fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                        mSession.close();
1251fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    }
1252fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    mSession = session;
1253fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    mPlayer = (MockPlayer) session.getPlayer();
1254fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    assertEquals(mContext.getPackageName(), controller.getPackageName());
1255fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    assertFalse(controller.isTrusted());
1256fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                    latch.countDown();
1257fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                }
1258fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                return super.onConnect(session, controller);
1259fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
1260fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        };
1261fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        TestServiceRegistry.getInstance().setSessionCallback(sessionCallback);
1262fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
12638138c8606070fc6193f0a9bc566c4b5f1d035457Jaewan Kim        final SessionCommand2 testCommand = new SessionCommand2("testConnectToService", null);
12648138c8606070fc6193f0a9bc566c4b5f1d035457Jaewan Kim        final CountDownLatch controllerLatch = new CountDownLatch(1);
12658138c8606070fc6193f0a9bc566c4b5f1d035457Jaewan Kim        mController = createController(TestUtils.getServiceToken(mContext, id), true,
12668138c8606070fc6193f0a9bc566c4b5f1d035457Jaewan Kim                new ControllerCallback() {
12678138c8606070fc6193f0a9bc566c4b5f1d035457Jaewan Kim                    @Override
12688138c8606070fc6193f0a9bc566c4b5f1d035457Jaewan Kim                    public void onCustomCommand(MediaController2 controller,
12698138c8606070fc6193f0a9bc566c4b5f1d035457Jaewan Kim                            SessionCommand2 command, Bundle args, ResultReceiver receiver) {
12708138c8606070fc6193f0a9bc566c4b5f1d035457Jaewan Kim                        if (testCommand.equals(command)) {
12718138c8606070fc6193f0a9bc566c4b5f1d035457Jaewan Kim                            controllerLatch.countDown();
12728138c8606070fc6193f0a9bc566c4b5f1d035457Jaewan Kim                        }
12738138c8606070fc6193f0a9bc566c4b5f1d035457Jaewan Kim                    }
12748138c8606070fc6193f0a9bc566c4b5f1d035457Jaewan Kim                }
12758138c8606070fc6193f0a9bc566c4b5f1d035457Jaewan Kim        );
1276fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
1277fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
12788138c8606070fc6193f0a9bc566c4b5f1d035457Jaewan Kim        // Test command from controller to session service.
1279fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.play();
1280fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mPlayer.mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
1281fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(mPlayer.mPlayCalled);
1282fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
12838138c8606070fc6193f0a9bc566c4b5f1d035457Jaewan Kim        // Test command from session service to controller.
12848138c8606070fc6193f0a9bc566c4b5f1d035457Jaewan Kim        mSession.sendCustomCommand(testCommand, null);
12858138c8606070fc6193f0a9bc566c4b5f1d035457Jaewan Kim        assertTrue(controllerLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
1286fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1287fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1288fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
1289fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testControllerAfterSessionIsGone_session() throws InterruptedException {
1290fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1291fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testControllerAfterSessionIsClosed(mSession.getToken().getId());
1292fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1293fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1294fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
1295fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testControllerAfterSessionIsClosed_sessionService() throws InterruptedException {
1296fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
12979d52d2ed9a9120a066cccaf0a544dec20a52b95aJaewan Kim        testConnectToService(MockMediaSessionService2.ID);
1298fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testControllerAfterSessionIsClosed(MockMediaSessionService2.ID);
1299fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1300fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1301fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
1302fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim    public void testSubscribeRouteInfo() throws InterruptedException {
1303fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        prepareLooper();
1304fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        final TestSessionCallback callback = new TestSessionCallback() {
1305fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim            @Override
1306fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim            public void onSubscribeRoutesInfo(@NonNull MediaSession2 session,
1307fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim                    @NonNull ControllerInfo controller) {
1308fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim                assertEquals(mContext.getPackageName(), controller.getPackageName());
1309fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim                mLatch.countDown();
1310fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim            }
1311fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim
1312fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim            @Override
1313fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim            public void onUnsubscribeRoutesInfo(@NonNull MediaSession2 session,
1314fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim                    @NonNull ControllerInfo controller) {
1315fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim                assertEquals(mContext.getPackageName(), controller.getPackageName());
1316fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim                mLatch.countDown();
1317fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim            }
1318fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        };
1319fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        mSession.close();
1320fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer)
1321fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim                .setSessionCallback(sHandlerExecutor, callback).setId(TAG).build();
1322fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        final MediaController2 controller = createController(mSession.getToken());
1323fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim
1324fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        callback.resetLatchCount(1);
1325fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        controller.subscribeRoutesInfo();
1326fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        assertTrue(callback.mLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
1327fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim
1328fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        callback.resetLatchCount(1);
1329fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        controller.unsubscribeRoutesInfo();
1330fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        assertTrue(callback.mLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
1331fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim    }
1332fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim
1333fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim    @Test
1334fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim    public void testSelectRouteInfo() throws InterruptedException {
1335fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        prepareLooper();
1336fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        final Bundle testRoute = new Bundle();
1337fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        testRoute.putString("id", "testRoute");
1338fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        final TestSessionCallback callback = new TestSessionCallback() {
1339fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim            @Override
1340fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim            public void onSelectRoute(@NonNull MediaSession2 session,
1341fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim                    @NonNull ControllerInfo controller, @NonNull Bundle route) {
1342fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim                assertEquals(mContext.getPackageName(), controller.getPackageName());
1343fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim                assertTrue(TestUtils.equals(route, testRoute));
1344fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim                mLatch.countDown();
1345fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim            }
1346fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        };
1347fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        mSession.close();
1348fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        mSession = new MediaSession2.Builder(mContext).setPlayer(mPlayer)
1349fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim                .setSessionCallback(sHandlerExecutor, callback).setId(TAG).build();
1350fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        final MediaController2 controller = createController(mSession.getToken());
1351fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim
1352fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        callback.resetLatchCount(1);
1353fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        controller.selectRoute(testRoute);
1354fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        assertTrue(callback.mLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
1355fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim    }
1356fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim
1357fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim    @Test
1358fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testClose_beforeConnected() throws InterruptedException {
1359fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1360fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        MediaController2 controller =
1361fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                createController(mSession.getToken(), false, null);
1362fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        controller.close();
1363fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1364fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1365fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
1366fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testClose_twice() {
1367fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1368fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.close();
1369fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.close();
1370fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1371fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1372fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
1373fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testClose_session() throws InterruptedException {
1374fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1375fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final String id = mSession.getToken().getId();
1376fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.close();
1377fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // close is done immediately for session.
1378fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testNoInteraction();
1379fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1380fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // Test whether the controller is notified about later close of the session or
1381fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // re-creation.
1382fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testControllerAfterSessionIsClosed(id);
1383fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1384fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1385fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
1386fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testClose_sessionService() throws InterruptedException {
1387fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1388fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testCloseFromService(MockMediaSessionService2.ID);
1389fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1390fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1391fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    @Test
1392fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    public void testClose_libraryService() throws InterruptedException {
1393fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        prepareLooper();
1394fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testCloseFromService(MockMediaLibraryService2.ID);
1395fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1396fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1397fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    private void testCloseFromService(String id) throws InterruptedException {
1398fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
1399fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        TestServiceRegistry.getInstance().setSessionServiceCallback(new SessionServiceCallback() {
1400fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
1401fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onCreated() {
1402fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                // Do nothing.
1403fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
1404fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1405fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
1406fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void onDestroyed() {
1407fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
1408fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
1409fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        });
1410fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController = createController(TestUtils.getServiceToken(mContext, id));
1411fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mController.close();
1412fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // Wait until close triggers onDestroy() of the session service.
1413fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
1414fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertNull(TestServiceRegistry.getInstance().getServiceInstance());
1415fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testNoInteraction();
1416fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1417fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // Test whether the controller is notified about later close of the session or
1418fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // re-creation.
1419fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testControllerAfterSessionIsClosed(id);
1420fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1421fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1422fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    private void testControllerAfterSessionIsClosed(final String id) throws InterruptedException {
1423fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // This cause session service to be died.
1424fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mSession.close();
1425fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        waitForDisconnect(mController, true);
1426fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testNoInteraction();
1427fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1428fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // Ensure that the controller cannot use newly create session with the same ID.
1429fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // Recreated session has different session stub, so previously created controller
1430fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // shouldn't be available.
1431fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mSession = new MediaSession2.Builder(mContext)
1432fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setPlayer(mPlayer)
1433fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setSessionCallback(sHandlerExecutor, new SessionCallback() {})
1434fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                .setId(id).build();
1435fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        testNoInteraction();
1436fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1437fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1438fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    // Test that mSession and mController doesn't interact.
1439fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    // Note that this method can be called after the mSession is died, so mSession may not have
1440fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    // valid player.
1441fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    private void testNoInteraction() throws InterruptedException {
1442fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // TODO: check that calls from the controller to session shouldn't be delivered.
1443fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1444fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        // Calls from the session to controller shouldn't be delivered.
1445fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch latch = new CountDownLatch(1);
1446fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        setRunnableForOnCustomCommand(mController, new Runnable() {
1447fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            @Override
1448fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            public void run() {
1449fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang                latch.countDown();
1450fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            }
1451fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        });
1452fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        SessionCommand2 customCommand = new SessionCommand2("testNoInteraction", null);
1453fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        mSession.sendCustomCommand(customCommand, null);
1454fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        assertFalse(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
1455fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        setRunnableForOnCustomCommand(mController, null);
1456fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1457fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1458fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    // TODO(jaewan): Add  test for service connect rejection, when we differentiate session
1459fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    //               active/inactive and connection accept/refuse
1460fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1461fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    class TestVolumeProvider extends VolumeProviderCompat {
1462fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        final CountDownLatch mLatch = new CountDownLatch(1);
1463fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        boolean mSetVolumeToCalled;
1464fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        boolean mAdjustVolumeCalled;
1465fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        int mVolume;
1466fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        int mDirection;
1467fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1468fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        TestVolumeProvider(int controlType, int maxVolume, int currentVolume) {
1469fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            super(controlType, maxVolume, currentVolume);
1470fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
1471fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1472fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        @Override
1473fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        public void onSetVolumeTo(int volume) {
1474fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            mSetVolumeToCalled = true;
1475fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            mVolume = volume;
1476fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            mLatch.countDown();
1477fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
1478fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang
1479fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        @Override
1480fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        public void onAdjustVolume(int direction) {
1481fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            mAdjustVolumeCalled = true;
1482fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            mDirection = direction;
1483fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang            mLatch.countDown();
1484fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang        }
1485fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang    }
1486fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim
1487fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim    class TestSessionCallback extends SessionCallback {
1488fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        CountDownLatch mLatch;
1489fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim
1490fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        void resetLatchCount(int count) {
1491fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim            mLatch = new CountDownLatch(count);
1492fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim        }
1493fa1b27e361831b01f2d97d816f48c39ccf0ff539Sungsoo Lim    }
1494fbbf807584a0fbe7a01a0aa9920330cad45689aaInsun Kang}
1495