From 34029e0082d6b866e0b0409fe2d1eea2bb76aba4 Mon Sep 17 00:00:00 2001 From: Hyundo Moon Date: Tue, 20 Apr 2021 13:44:12 +0900 Subject: [PATCH] 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 --- media/java/android/media/MediaRouter2.java | 2 +- media/tests/MediaRouter/Android.bp | 2 + media/tests/MediaRouter/AndroidManifest.xml | 1 + .../MediaRouter2ManagerTest.java | 85 ++++++++++++------- .../MediaRouter2ManagerTestActivity.java | 53 ++++++++++++ 5 files changed, 113 insertions(+), 30 deletions(-) create mode 100644 media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTestActivity.java diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java index 232de0b7c57f5..fbf7def4093cc 100644 --- a/media/java/android/media/MediaRouter2.java +++ b/media/java/android/media/MediaRouter2.java @@ -180,7 +180,7 @@ public final class MediaRouter2 { // 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 d41bc02906aba..2da6c9884c0f8 100644 --- a/media/tests/MediaRouter/Android.bp +++ b/media/tests/MediaRouter/Android.bp @@ -18,7 +18,9 @@ android_test { ], 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 02688d5d641a4..018f148dd3d52 100644 --- a/media/tests/MediaRouter/AndroidManifest.xml +++ b/media/tests/MediaRouter/AndroidManifest.xml @@ -19,6 +19,7 @@ + diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java index eaa4f03ba81ac..3a34e756a50ad 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.LargeTest; 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 @@ public class MediaRouter2ManagerTest { private MediaRouter2 mRouter2; private Executor mExecutor; private String mPackageName; + private StubMediaRoute2ProviderService mService; private final List mManagerCallbacks = new ArrayList<>(); private final List mRouteCallbacks = new ArrayList<>(); @@ -105,7 +107,6 @@ public class MediaRouter2ManagerTest { 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 @@ public class MediaRouter2ManagerTest { 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 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 @@ public class MediaRouter2ManagerTest { 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 @@ public class MediaRouter2ManagerTest { 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 @@ public class MediaRouter2ManagerTest { 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 @@ public class MediaRouter2ManagerTest { CountDownLatch serviceOnReleaseSessionLatch = new CountDownLatch(1); List 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 @@ public class MediaRouter2ManagerTest { Map routes = waitAndGetRoutesWithManager(FEATURES_ALL); MediaRoute2Info volRoute = routes.get(ROUTE_ID_VARIABLE_VOLUME); - StubMediaRoute2ProviderService instance = StubMediaRoute2ProviderService.getInstance(); - assertNotNull(instance); - final List 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 @@ public class MediaRouter2ManagerTest { }); 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 @@ public class MediaRouter2ManagerTest { @Override public void onRoutesAdded(List routes) { for (MediaRoute2Info route : routes) { - if (!route.isSystemRoute()) { + if (!route.isSystemRoute() + && hasMatchingFeature(route.getFeatures(), routeFeatures)) { addedLatch.countDown(); break; } @@ -834,10 +852,10 @@ public class MediaRouter2ManagerTest { 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 @@ public class MediaRouter2ManagerTest { } } + boolean hasMatchingFeature(List features1, List features2) { + for (String feature : features1) { + if (features2.contains(feature)) { + return true; + } + } + return false; + } + void awaitOnRouteChangedManager(Runnable task, String routeId, Predicate 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 0000000000000..ac2a8bbd4e50f --- /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 sActivityScenario; + + public static ActivityScenario 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); + } +}