Fix failing MediaRouter2ManagerTest
The test failed for several reasons:
- When other real cast device is present, tests are run before actual
routes arrive.
- Screen is not turned on during test.
- Test lacks MEDIA_CONTENT_CONTROL permission.
This CL fixes the test.
Bug: 186190171
Test: atest com.android.mediaroutertest.MediaRouter2ManagerTest \
--rerun-until-failure
Change-Id: I6f86ae7cba25871ffb7c8ee96f4c8db6bd86b816
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 232de0b..fbf7def 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -180,7 +180,7 @@
// SecurityException will be thrown if there's no permission.
serviceBinder.enforceMediaContentControlPermission();
} catch (RemoteException e) {
- Log.e(TAG, "Unable to check MEDIA_CONTENT_CONTROL permission.");
+ e.rethrowFromSystemServer();
}
PackageManager pm = context.getPackageManager();
diff --git a/media/tests/MediaRouter/Android.bp b/media/tests/MediaRouter/Android.bp
index d41bc02..2da6c98 100644
--- a/media/tests/MediaRouter/Android.bp
+++ b/media/tests/MediaRouter/Android.bp
@@ -18,7 +18,9 @@
],
static_libs: [
+ "androidx.test.core",
"androidx.test.rules",
+ "compatibility-device-util-axt",
"mockito-target-minus-junit4",
"testng",
"truth-prebuilt",
diff --git a/media/tests/MediaRouter/AndroidManifest.xml b/media/tests/MediaRouter/AndroidManifest.xml
index 02688d5..018f148 100644
--- a/media/tests/MediaRouter/AndroidManifest.xml
+++ b/media/tests/MediaRouter/AndroidManifest.xml
@@ -19,6 +19,7 @@
<application android:label="@string/app_name">
<uses-library android:name="android.test.runner" />
+ <activity android:name="com.android.mediaroutertest.MediaRouter2ManagerTestActivity" />
<service android:name=".StubMediaRoute2ProviderService"
android:exported="true">
<intent-filter>
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
index eaa4f03..3a34e75 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
@@ -16,7 +16,6 @@
package com.android.mediaroutertest;
-import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO;
import static android.media.MediaRoute2Info.FEATURE_REMOTE_PLAYBACK;
import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_FIXED;
import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE;
@@ -61,6 +60,8 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.compatibility.common.util.PollingCheck;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -94,6 +95,7 @@
private MediaRouter2 mRouter2;
private Executor mExecutor;
private String mPackageName;
+ private StubMediaRoute2ProviderService mService;
private final List<MediaRouter2Manager.Callback> mManagerCallbacks = new ArrayList<>();
private final List<RouteCallback> mRouteCallbacks = new ArrayList<>();
@@ -105,7 +107,6 @@
static {
FEATURES_ALL.add(FEATURE_SAMPLE);
FEATURES_ALL.add(FEATURE_SPECIAL);
- FEATURES_ALL.add(FEATURE_LIVE_AUDIO);
FEATURES_SPECIAL.add(FEATURE_SPECIAL);
}
@@ -115,26 +116,53 @@
mContext = InstrumentationRegistry.getTargetContext();
mUiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
mUiAutomation.adoptShellPermissionIdentity(Manifest.permission.MEDIA_CONTENT_CONTROL);
+ MediaRouter2ManagerTestActivity.startActivity(mContext);
+
mManager = MediaRouter2Manager.getInstance(mContext);
+ mManager.startScan();
mRouter2 = MediaRouter2.getInstance(mContext);
+
// If we need to support thread pool executors, change this to thread pool executor.
mExecutor = Executors.newSingleThreadExecutor();
mPackageName = mContext.getPackageName();
+
+ // In order to make the system bind to the test service,
+ // set a non-empty discovery preference while app is in foreground.
+ List<String> features = new ArrayList<>();
+ features.add("A test feature");
+ RouteDiscoveryPreference preference =
+ new RouteDiscoveryPreference.Builder(features, false).build();
+ mRouter2.registerRouteCallback(mExecutor, new RouteCallback() {}, preference);
+
+ new PollingCheck(TIMEOUT_MS) {
+ @Override
+ protected boolean check() {
+ StubMediaRoute2ProviderService service =
+ StubMediaRoute2ProviderService.getInstance();
+ if (service != null) {
+ mService = service;
+ return true;
+ }
+ return false;
+ }
+ }.run();
}
@After
public void tearDown() {
+ mManager.stopScan();
+
// order matters (callbacks should be cleared at the last)
releaseAllSessions();
// unregister callbacks
clearCallbacks();
- StubMediaRoute2ProviderService instance = StubMediaRoute2ProviderService.getInstance();
- if (instance != null) {
- instance.setProxy(null);
- instance.setSpy(null);
+ if (mService != null) {
+ mService.setProxy(null);
+ mService.setSpy(null);
}
+ MediaRouter2ManagerTestActivity.finishActivity();
mUiAutomation.dropShellPermissionIdentity();
}
@@ -179,13 +207,10 @@
MediaRoute2Info routeToRemove = routes.get(ROUTE_ID2);
assertNotNull(routeToRemove);
- StubMediaRoute2ProviderService sInstance =
- StubMediaRoute2ProviderService.getInstance();
- assertNotNull(sInstance);
- sInstance.removeRoute(ROUTE_ID2);
+ mService.removeRoute(ROUTE_ID2);
assertTrue(removedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
- sInstance.addRoute(routeToRemove);
+ mService.addRoute(routeToRemove);
assertTrue(addedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
}
@@ -218,10 +243,7 @@
MediaRoute2Info routeToRemove = routes.get(ROUTE_ID2);
assertNotNull(routeToRemove);
- StubMediaRoute2ProviderService sInstance =
- StubMediaRoute2ProviderService.getInstance();
- assertNotNull(sInstance);
- sInstance.removeRoute(ROUTE_ID2);
+ mService.removeRoute(ROUTE_ID2);
// Wait until the route is removed.
assertTrue(removedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
@@ -230,7 +252,7 @@
assertNull(newRoutes.get(ROUTE_ID2));
// Revert the removal.
- sInstance.addRoute(routeToRemove);
+ mService.addRoute(routeToRemove);
assertTrue(addedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
mRouter2.unregisterRouteCallback(routeCallback);
}
@@ -445,9 +467,7 @@
CountDownLatch serviceOnReleaseSessionLatch = new CountDownLatch(1);
List<RoutingSessionInfo> sessions = new ArrayList<>();
- StubMediaRoute2ProviderService instance = StubMediaRoute2ProviderService.getInstance();
- assertNotNull(instance);
- instance.setSpy(new StubMediaRoute2ProviderService.Spy() {
+ mService.setSpy(new StubMediaRoute2ProviderService.Spy() {
@Override
public void onReleaseSession(long requestId, String sessionId) {
serviceOnReleaseSessionLatch.countDown();
@@ -652,12 +672,9 @@
Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(FEATURES_ALL);
MediaRoute2Info volRoute = routes.get(ROUTE_ID_VARIABLE_VOLUME);
- StubMediaRoute2ProviderService instance = StubMediaRoute2ProviderService.getInstance();
- assertNotNull(instance);
-
final List<Long> requestIds = new ArrayList<>();
final CountDownLatch onSetRouteVolumeLatch = new CountDownLatch(1);
- instance.setProxy(new StubMediaRoute2ProviderService.Proxy() {
+ mService.setProxy(new StubMediaRoute2ProviderService.Proxy() {
@Override
public void onSetRouteVolume(String routeId, int volume, long requestId) {
requestIds.add(requestId);
@@ -687,16 +704,16 @@
});
final long invalidRequestId = REQUEST_ID_NONE;
- instance.notifyRequestFailed(invalidRequestId, failureReason);
+ mService.notifyRequestFailed(invalidRequestId, failureReason);
assertFalse(onRequestFailedLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
final long validRequestId = requestIds.get(0);
- instance.notifyRequestFailed(validRequestId, failureReason);
+ mService.notifyRequestFailed(validRequestId, failureReason);
assertTrue(onRequestFailedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
// Test calling notifyRequestFailed() multiple times with the same valid requestId.
// onRequestFailed() shouldn't be called since the requestId has been already handled.
- instance.notifyRequestFailed(validRequestId, failureReason);
+ mService.notifyRequestFailed(validRequestId, failureReason);
assertFalse(onRequestFailedSecondCallLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
}
@@ -813,7 +830,8 @@
@Override
public void onRoutesAdded(List<MediaRoute2Info> routes) {
for (MediaRoute2Info route : routes) {
- if (!route.isSystemRoute()) {
+ if (!route.isSystemRoute()
+ && hasMatchingFeature(route.getFeatures(), routeFeatures)) {
addedLatch.countDown();
break;
}
@@ -834,10 +852,10 @@
mRouter2.registerRouteCallback(mExecutor, routeCallback,
new RouteDiscoveryPreference.Builder(routeFeatures, true).build());
try {
- if (mManager.getAllRoutes().isEmpty()) {
+ featuresLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS);
+ if (mManager.getAvailableRoutes(mPackageName).isEmpty()) {
addedLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS);
}
- featuresLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS);
return createRouteMap(mManager.getAvailableRoutes(mPackageName));
} finally {
mRouter2.unregisterRouteCallback(routeCallback);
@@ -845,6 +863,15 @@
}
}
+ boolean hasMatchingFeature(List<String> features1, List<String> features2) {
+ for (String feature : features1) {
+ if (features2.contains(feature)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
void awaitOnRouteChangedManager(Runnable task, String routeId,
Predicate<MediaRoute2Info> predicate) throws Exception {
CountDownLatch latch = new CountDownLatch(1);
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTestActivity.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTestActivity.java
new file mode 100644
index 0000000..ac2a8bb
--- /dev/null
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTestActivity.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 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 com.android.mediaroutertest;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.WindowManager;
+
+import androidx.test.core.app.ActivityScenario;
+
+public class MediaRouter2ManagerTestActivity extends Activity {
+
+ private static ActivityScenario<MediaRouter2ManagerTestActivity> sActivityScenario;
+
+ public static ActivityScenario<MediaRouter2ManagerTestActivity> startActivity(Context context) {
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClass(context, MediaRouter2ManagerTestActivity.class);
+ sActivityScenario = ActivityScenario.launch(intent);
+ return sActivityScenario;
+ }
+
+ public static void finishActivity() {
+ if (sActivityScenario != null) {
+ // TODO: Sometimes calling this takes about 5 seconds. Need to figure out why.
+ sActivityScenario.close();
+ sActivityScenario = null;
+ }
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setTurnScreenOn(true);
+ setShowWhenLocked(true);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ }
+}