From 6f3bd5f8a0d00d9e910a1ad6ba9aeda87d96f7cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Budnik?= Date: Thu, 27 Jul 2023 14:47:03 +0000 Subject: [PATCH] Add flag for MediaRouter2-based InfoMediaManager InfoMediaManager.createInstance() will gate MediaRouter2-based and MediaRouter2Manager-based instances based on the new flag. Also, return a NoOpInfoMediaManager when the target package name does not exist. Bug: 192657812 Test: Testmapping + Manual Flag Testing Change-Id: I8dcdd1c1366ee4246b8a4805f2347a810f51afec --- packages/SettingsLib/Android.bp | 14 ++ packages/SettingsLib/AndroidManifest.xml | 2 + ...ettingslib_media_flag_declarations.aconfig | 8 + .../settingslib/media/InfoMediaManager.java | 23 +++ .../settingslib/media/LocalMediaManager.java | 2 +- .../media/NoOpInfoMediaManager.java | 154 ++++++++++++++++++ packages/SettingsLib/tests/integ/Android.bp | 3 + .../media/InfoMediaManagerIntegTest.java | 93 +++++++++++ .../pipeline/LocalMediaManagerFactory.kt | 7 +- .../media/dialog/MediaOutputController.java | 3 +- 10 files changed, 302 insertions(+), 7 deletions(-) create mode 100644 packages/SettingsLib/aconfig/settingslib_media_flag_declarations.aconfig create mode 100644 packages/SettingsLib/src/com/android/settingslib/media/NoOpInfoMediaManager.java create mode 100644 packages/SettingsLib/tests/integ/src/com/android/settingslib/media/InfoMediaManagerIntegTest.java diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp index c244ca0505ed6..3d35bad68a73a 100644 --- a/packages/SettingsLib/Android.bp +++ b/packages/SettingsLib/Android.bp @@ -58,6 +58,7 @@ android_library { "setupdesign", "zxing-core-1.7", "androidx.room_room-runtime", + "settingslib_flags_lib", ], @@ -88,3 +89,16 @@ java_defaults { "SettingsLib", ], } + +aconfig_declarations { + name: "settingslib_media_flags", + package: "com.android.settingslib.media.flags", + srcs: [ + "aconfig/settingslib_media_flag_declarations.aconfig", + ], +} + +java_aconfig_library { + name: "settingslib_flags_lib", + aconfig_declarations: "settingslib_media_flags", +} diff --git a/packages/SettingsLib/AndroidManifest.xml b/packages/SettingsLib/AndroidManifest.xml index 13f8a372c9b57..322d6cfc2da70 100644 --- a/packages/SettingsLib/AndroidManifest.xml +++ b/packages/SettingsLib/AndroidManifest.xml @@ -18,6 +18,8 @@ + + This implementation is used when {@link RouterInfoMediaManager} throws a {@link + * InfoMediaManager.PackageNotAvailableException}. + */ +// TODO - b/293578081: Remove once PackageNotAvailableException is propagated to library clients. +/* package */ final class NoOpInfoMediaManager extends InfoMediaManager { + + NoOpInfoMediaManager( + Context context, + String packageName, + Notification notification, + LocalBluetoothManager localBluetoothManager) { + super(context, packageName, notification, localBluetoothManager); + } + + @Override + public void stopScan() { + // Do nothing. + } + + @Override + protected void startScanOnRouter() { + // Do nothing. + } + + @Override + protected boolean connectDeviceWithoutPackageName(@NonNull MediaDevice device) { + return false; + } + + @Override + protected void transferToRoute(@NonNull MediaRoute2Info route) { + // Do nothing. + } + + @Override + protected void selectRoute(@NonNull MediaRoute2Info route, @NonNull RoutingSessionInfo info) { + // Do nothing. + } + + @Override + protected void deselectRoute(@NonNull MediaRoute2Info route, @NonNull RoutingSessionInfo info) { + // Do nothing. + } + + @Override + protected void releaseSession(@NonNull RoutingSessionInfo sessionInfo) { + // Do nothing. + } + + @NonNull + @Override + protected List getSelectableRoutes(@NonNull RoutingSessionInfo info) { + return Collections.emptyList(); + } + + @NonNull + @Override + protected List getDeselectableRoutes(@NonNull RoutingSessionInfo info) { + return Collections.emptyList(); + } + + @NonNull + @Override + protected List getSelectedRoutes(@NonNull RoutingSessionInfo info) { + return Collections.emptyList(); + } + + @Override + protected void setSessionVolume(@NonNull RoutingSessionInfo info, int volume) { + // Do nothing. + } + + @Override + protected void setRouteVolume(@NonNull MediaRoute2Info route, int volume) { + // Do nothing. + } + + @Nullable + @Override + protected RouteListingPreference getRouteListingPreference() { + return null; + } + + @NonNull + @Override + protected List getRemoteSessions() { + return Collections.emptyList(); + } + + @NonNull + @Override + protected List getRoutingSessionsForPackage() { + return Collections.emptyList(); + } + + @Nullable + @Override + protected RoutingSessionInfo getRoutingSessionById(@NonNull String sessionId) { + return null; + } + + @NonNull + @Override + protected List getAllRoutes() { + return Collections.emptyList(); + } + + @NonNull + @Override + protected List getAvailableRoutesFromRouter() { + return Collections.emptyList(); + } + + @NonNull + @Override + protected List getTransferableRoutes(@NonNull String packageName) { + return Collections.emptyList(); + } +} diff --git a/packages/SettingsLib/tests/integ/Android.bp b/packages/SettingsLib/tests/integ/Android.bp index ff3eeec4171fe..8970debb3e2f6 100644 --- a/packages/SettingsLib/tests/integ/Android.bp +++ b/packages/SettingsLib/tests/integ/Android.bp @@ -48,11 +48,14 @@ android_test { "androidx.test.core", "androidx.test.rules", "androidx.test.espresso.core", + "flag-junit", "mockito-target-minus-junit4", + "platform-test-annotations", "truth-prebuilt", "SettingsLibDeviceStateRotationLock", "SettingsLibSettingsSpinner", "SettingsLibUsageProgressBarPreference", + "settingslib_flags_lib", ], dxflags: ["--multi-dex"], diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/media/InfoMediaManagerIntegTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/media/InfoMediaManagerIntegTest.java new file mode 100644 index 0000000000000..c647cbb5a0b11 --- /dev/null +++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/media/InfoMediaManagerIntegTest.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2023 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.settingslib.media; + +import static com.android.settingslib.media.flags.Flags.FLAG_USE_MEDIA_ROUTER2_FOR_INFO_MEDIA_MANAGER; + +import static com.google.common.truth.Truth.assertThat; + +import android.Manifest; +import android.app.UiAutomation; +import android.content.Context; +import android.platform.test.annotations.RequiresFlagsDisabled; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class InfoMediaManagerIntegTest { + + private static final String FAKE_PACKAGE = "FAKE_PACKAGE"; + + private Context mContext; + private UiAutomation mUiAutomation; + + @Rule + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); + + @Before + public void setUp() { + mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + mUiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); + mUiAutomation.adoptShellPermissionIdentity(Manifest.permission.MEDIA_CONTENT_CONTROL); + } + + @After + public void tearDown() { + mUiAutomation.dropShellPermissionIdentity(); + } + + @Test + @RequiresFlagsEnabled(FLAG_USE_MEDIA_ROUTER2_FOR_INFO_MEDIA_MANAGER) + public void createInstance_withMR2FlagOn_returnsRouterInfoMediaManager() { + InfoMediaManager manager = + InfoMediaManager.createInstance(mContext, mContext.getPackageName(), null, null); + assertThat(manager).isInstanceOf(RouterInfoMediaManager.class); + } + + @Test + @RequiresFlagsEnabled(FLAG_USE_MEDIA_ROUTER2_FOR_INFO_MEDIA_MANAGER) + public void createInstance_withMR2FlagOn_withFakePackage_returnsNoOpInfoMediaManager() { + InfoMediaManager manager = + InfoMediaManager.createInstance(mContext, FAKE_PACKAGE, null, null); + assertThat(manager).isInstanceOf(NoOpInfoMediaManager.class); + } + + @Test + @RequiresFlagsEnabled(FLAG_USE_MEDIA_ROUTER2_FOR_INFO_MEDIA_MANAGER) + public void createInstance_withMR2FlagOn_withNullPackage_returnsRouterInfoMediaManager() { + InfoMediaManager manager = InfoMediaManager.createInstance(mContext, null, null, null); + assertThat(manager).isInstanceOf(RouterInfoMediaManager.class); + } + + @Test + @RequiresFlagsDisabled(FLAG_USE_MEDIA_ROUTER2_FOR_INFO_MEDIA_MANAGER) + public void createInstance_withMR2FlagOff_returnsManagerInfoMediaManager() { + InfoMediaManager manager = + InfoMediaManager.createInstance(mContext, mContext.getPackageName(), null, null); + assertThat(manager).isInstanceOf(ManagerInfoMediaManager.class); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/LocalMediaManagerFactory.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/LocalMediaManagerFactory.kt index f908481d39129..785a1e8184657 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/LocalMediaManagerFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/LocalMediaManagerFactory.kt @@ -18,8 +18,8 @@ package com.android.systemui.media.controls.pipeline import android.content.Context import com.android.settingslib.bluetooth.LocalBluetoothManager +import com.android.settingslib.media.InfoMediaManager import com.android.settingslib.media.LocalMediaManager -import com.android.settingslib.media.ManagerInfoMediaManager import javax.inject.Inject /** Factory to create [LocalMediaManager] objects. */ @@ -31,8 +31,7 @@ constructor( ) { /** Creates a [LocalMediaManager] for the given package. */ fun create(packageName: String): LocalMediaManager { - return ManagerInfoMediaManager(context, packageName, null, localBluetoothManager).run { - LocalMediaManager(context, localBluetoothManager, this, packageName) - } + return InfoMediaManager.createInstance(context, packageName, null, localBluetoothManager) + .run { LocalMediaManager(context, localBluetoothManager, this, packageName) } } } diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java index 83631b0a1c1de..be42569db7b2f 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java @@ -76,7 +76,6 @@ import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastMetadata; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.media.InfoMediaManager; import com.android.settingslib.media.LocalMediaManager; -import com.android.settingslib.media.ManagerInfoMediaManager; import com.android.settingslib.media.MediaDevice; import com.android.settingslib.utils.ThreadUtils; import com.android.systemui.R; @@ -194,7 +193,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, mKeyGuardManager = keyGuardManager; mFeatureFlags = featureFlags; mUserTracker = userTracker; - InfoMediaManager imm = new ManagerInfoMediaManager(mContext, packageName, null, lbm); + InfoMediaManager imm = InfoMediaManager.createInstance(mContext, packageName, null, lbm); mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, packageName); mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName); mDialogLaunchAnimator = dialogLaunchAnimator;