Add CTS for MediaBrowser

Change-Id: Idfbedb14fec08f61cb5d2717030913bc2c0ef83c
diff --git a/tests/tests/media/AndroidManifest.xml b/tests/tests/media/AndroidManifest.xml
index d53b2c6..32df531 100644
--- a/tests/tests/media/AndroidManifest.xml
+++ b/tests/tests/media/AndroidManifest.xml
@@ -64,6 +64,11 @@
                 <action android:name="android.intent.action.MAIN"/>
             </intent-filter>
         </service>
+        <service android:name="android.media.cts.StubMediaBrowserService">
+            <intent-filter>
+                <action android:name="android.media.browse.MediaBrowserService" />
+            </intent-filter>
+        </service>
     </application>
 
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/media/src/android/media/cts/MediaBrowserTest.java b/tests/tests/media/src/android/media/cts/MediaBrowserTest.java
new file mode 100644
index 0000000..b53aa92
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaBrowserTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media.cts;
+
+import android.content.ComponentName;
+import android.cts.util.PollingCheck;
+import android.media.browse.MediaBrowser;
+import android.test.InstrumentationTestCase;
+
+/**
+ * Test {@link android.media.browse.MediaBrowser}.
+ */
+public class MediaBrowserTest extends InstrumentationTestCase {
+    // The maximum time to wait for an operation.
+    private static final long TIME_OUT_MS = 1000L;
+    private static final ComponentName TEST_BROWSER_SERVICE = new ComponentName(
+            "com.android.cts.media", "android.media.cts.StubMediaBrowserService");
+    private final StubConnectionCallback mConnectionCallback = new StubConnectionCallback();
+
+    private MediaBrowser mMediaBrowser;
+
+    public void testMediaBrowser() {
+        mConnectionCallback.resetCounts();
+        createMediaBrowser(TEST_BROWSER_SERVICE);
+        assertEquals(false, mMediaBrowser.isConnected());
+
+        connectMediaBrowserService();
+        assertEquals(true, mMediaBrowser.isConnected());
+
+        assertEquals(TEST_BROWSER_SERVICE, mMediaBrowser.getServiceComponent());
+        assertEquals(StubMediaBrowserService.MEDIA_ID_ROOT, mMediaBrowser.getRoot());
+        assertEquals(StubMediaBrowserService.EXTRAS_VALUE,
+                mMediaBrowser.getExtras().getString(StubMediaBrowserService.EXTRAS_KEY));
+        assertEquals(StubMediaBrowserService.sSession.getSessionToken(),
+                mMediaBrowser.getSessionToken());
+
+        mMediaBrowser.disconnect();
+        assertEquals(false, mMediaBrowser.isConnected());
+    }
+
+    public void testConnectTwice() {
+        mConnectionCallback.resetCounts();
+        createMediaBrowser(TEST_BROWSER_SERVICE);
+        connectMediaBrowserService();
+        try {
+            mMediaBrowser.connect();
+            fail();
+        } catch (IllegalStateException e) {
+            // expected
+        }
+    }
+
+    public void testGetServiceComponentBeforeConnection() {
+        mConnectionCallback.resetCounts();
+        createMediaBrowser(TEST_BROWSER_SERVICE);
+        try {
+            ComponentName serviceComponent = mMediaBrowser.getServiceComponent();
+            fail();
+        } catch (IllegalStateException e) {
+            // expected
+        }
+    }
+
+    private void createMediaBrowser(final ComponentName component) {
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                mMediaBrowser = new MediaBrowser(getInstrumentation().getTargetContext(),
+                        component, mConnectionCallback, null);
+            }
+        });
+    }
+
+    private void connectMediaBrowserService() {
+        mMediaBrowser.connect();
+        new PollingCheck(TIME_OUT_MS) {
+            @Override
+            protected boolean check() {
+                return mConnectionCallback.mConnectedCount > 0;
+            }
+        }.run();
+    }
+
+    private static class StubConnectionCallback extends MediaBrowser.ConnectionCallback {
+        volatile int mConnectedCount;
+        volatile int mConnectionFailedCount;
+        volatile int mConnectionSuspendedCount;
+
+        public void resetCounts() {
+            mConnectedCount = 0;
+            mConnectionFailedCount = 0;
+            mConnectionSuspendedCount = 0;
+        }
+
+        @Override
+        public void onConnected() {
+            mConnectedCount++;
+        }
+
+        @Override
+        public void onConnectionFailed() {
+            mConnectionFailedCount++;
+        }
+
+        @Override
+        public void onConnectionSuspended() {
+            mConnectionSuspendedCount++;
+        }
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/StubMediaBrowserService.java b/tests/tests/media/src/android/media/cts/StubMediaBrowserService.java
new file mode 100644
index 0000000..d559c72
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/StubMediaBrowserService.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.cts;
+
+import android.media.browse.MediaBrowser.MediaItem;
+import android.media.session.MediaSession;
+import android.os.Bundle;
+import android.service.media.MediaBrowserService;
+
+import java.util.List;
+
+/**
+ * Stub implementation of (@link android.service.media.MediaBrowserService}.
+ */
+public class StubMediaBrowserService extends MediaBrowserService {
+    static final String MEDIA_ID_ROOT = "test_media_id_root";
+    static final String EXTRAS_KEY = "test_extras_key";
+    static final String EXTRAS_VALUE = "test_extras_value";
+
+    /* package private */ static MediaSession sSession;
+    private Bundle mExtras;
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        sSession = new MediaSession(this, "MediaBrowserStubService");
+        setSessionToken(sSession.getSessionToken());
+    }
+
+    @Override
+    public BrowserRoot onGetRoot(String clientPackageName, int clientUid, Bundle rootHints) {
+        mExtras = new Bundle();
+        mExtras.putString(EXTRAS_KEY, EXTRAS_VALUE);
+        return new BrowserRoot(MEDIA_ID_ROOT, mExtras);
+    }
+
+    @Override
+    public void onLoadChildren(final String parentMediaId, final Result<List<MediaItem>> result) {
+    }
+}