Merge "Fix password toggle taking FOCUS_DOWN events" into nyc-support-25.1-dev
diff --git a/media-compat/build.gradle b/media-compat/build.gradle
index e26a1bc..9bec2a3 100644
--- a/media-compat/build.gradle
+++ b/media-compat/build.gradle
@@ -23,6 +23,8 @@
 
     defaultConfig {
         minSdkVersion 9
+
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
     }
 
     sourceSets {
@@ -38,6 +40,11 @@
                 'java'
         ]
         main.aidl.srcDirs = ['java']
+
+        androidTest.setRoot('tests')
+        androidTest.java.srcDir 'tests/src'
+        androidTest.res.srcDir 'tests/res'
+        androidTest.manifest.srcFile 'tests/AndroidManifest.xml'
     }
 
     compileOptions {
@@ -113,4 +120,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/media-compat/tests/AndroidManifest.xml b/media-compat/tests/AndroidManifest.xml
new file mode 100644
index 0000000..00de2db
--- /dev/null
+++ b/media-compat/tests/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+   Copyright (C) 2016 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          xmlns:tools="http://schemas.android.com/tools"
+          package="android.support.mediacompat.test">
+
+    <uses-sdk
+            android:minSdkVersion="9"
+            android:targetSdkVersion="23"
+            tools:overrideLibrary="android.support.test, android.app, android.support.test.rule,
+                      android.support.test.espresso, android.support.test.espresso.idling"/>
+
+    <application android:supportsRtl="true">
+        <uses-library android:name="android.test.runner"/>
+        <activity android:name="android.support.v4.media.session.TestActivity" />
+    </application>
+
+    <instrumentation
+            android:name="android.test.InstrumentationTestRunner"
+            android:targetPackage="android.support.mediacompat.test"/>
+
+</manifest>
diff --git a/media-compat/tests/NO_DOCS b/media-compat/tests/NO_DOCS
new file mode 100644
index 0000000..092a39c
--- /dev/null
+++ b/media-compat/tests/NO_DOCS
@@ -0,0 +1,17 @@
+# Copyright (C) 2016 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.
+
+Having this file, named NO_DOCS, in a directory will prevent
+Android javadocs from being generated for java files under
+the directory. This is especially useful for test projects.
diff --git a/media-compat/tests/src/android/support/v4/media/session/MediaSessionCompatTest.java b/media-compat/tests/src/android/support/v4/media/session/MediaSessionCompatTest.java
new file mode 100644
index 0000000..455a706
--- /dev/null
+++ b/media-compat/tests/src/android/support/v4/media/session/MediaSessionCompatTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v4.media.session;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Looper;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.rule.ActivityTestRule;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static junit.framework.Assert.fail;
+
+public class MediaSessionCompatTest {
+    @Rule
+    public ActivityTestRule<TestActivity> mActivityRule =
+            new ActivityTestRule<>(TestActivity.class);
+    Context mContext;
+    Map<String, LockedObject> results = new HashMap<>();
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getContext();
+    }
+
+    @Test
+    public void testSetNullCallback() throws Throwable {
+        initWait("testSetNullCallback");
+        mActivityRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    MediaSessionCompat session = new MediaSessionCompat(mContext, "TEST");
+                    session.setCallback(null);
+                } catch (Exception e) {
+                    fail("Fail with an exception: " + e);
+                } finally {
+                    setResultData("testSetNullCallback", true);
+                }
+            }
+        });
+        waitFor("testSetNullCallback");
+    }
+
+    private void initWait(String key) throws InterruptedException {
+        results.put(key, new LockedObject());
+    }
+
+    private Object[] waitFor(String key) throws InterruptedException {
+        return results.get(key).waitFor();
+    }
+
+    private void setResultData(String key, Object... args) {
+        if (results.containsKey(key)) {
+            results.get(key).set(args);
+        }
+    }
+
+    private class LockedObject {
+        private Semaphore mLock = new Semaphore(1);
+        private volatile Object[] mArgs;
+
+        public LockedObject() {
+            mLock.drainPermits();
+        }
+
+        public void set(Object... args) {
+            mArgs = args;
+            mLock.release(1);
+        }
+
+        public Object[] waitFor() throws InterruptedException {
+            mLock.tryAcquire(1, 2, TimeUnit.SECONDS);
+            return mArgs;
+        }
+    }
+}
diff --git a/media-compat/tests/src/android/support/v4/media/session/TestActivity.java b/media-compat/tests/src/android/support/v4/media/session/TestActivity.java
new file mode 100644
index 0000000..dd56467
--- /dev/null
+++ b/media-compat/tests/src/android/support/v4/media/session/TestActivity.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v4.media.session;
+
+import android.app.Activity;
+
+public class TestActivity extends Activity {
+}