diff options
| author | 2024-06-17 22:16:42 +0000 | |
|---|---|---|
| committer | 2024-06-17 22:16:42 +0000 | |
| commit | 39f039ccd77ee33d897dafd840bbd1ce10540999 (patch) | |
| tree | d06048b8c5aad4b1494c828505abe9119afdc404 | |
| parent | dfb1523f06f806c7b2cc16465b68bda22ad92591 (diff) | |
| parent | e093a979cad9f2e3bc402b264c9fcc3b8914b531 (diff) | |
Merge "[Misc] Convert CastDevice to a Kotlin data class." into main
13 files changed, 734 insertions, 168 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/CastAutoAddableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/CastAutoAddableTest.kt index 9bb591e1ae7c..8ad647dd4d26 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/CastAutoAddableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/autoaddable/CastAutoAddableTest.kt @@ -25,6 +25,7 @@ import com.android.systemui.qs.pipeline.domain.model.AutoAddSignal import com.android.systemui.qs.pipeline.shared.TileSpec import com.android.systemui.qs.tiles.CastTile import com.android.systemui.statusbar.policy.CastController +import com.android.systemui.statusbar.policy.CastDevice import com.android.systemui.util.mockito.capture import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat @@ -73,9 +74,12 @@ class CastAutoAddableTest : SysuiTestCase() { @Test fun onCastDevicesChanged_deviceNotConnectedOrConnecting_noSignal() = runTest { val device = - CastController.CastDevice().apply { - state = CastController.CastDevice.STATE_DISCONNECTED - } + CastDevice( + id = "id", + name = null, + state = CastDevice.CastState.Disconnected, + origin = CastDevice.CastOrigin.MediaProjection, + ) whenever(castController.castDevices).thenReturn(listOf(device)) val signal by collectLastValue(underTest.autoAddSignal(0)) @@ -91,11 +95,19 @@ class CastAutoAddableTest : SysuiTestCase() { @Test fun onCastDevicesChanged_someDeviceConnecting_addSignal() = runTest { val disconnectedDevice = - CastController.CastDevice().apply { - state = CastController.CastDevice.STATE_DISCONNECTED - } + CastDevice( + id = "id", + name = null, + state = CastDevice.CastState.Disconnected, + origin = CastDevice.CastOrigin.MediaProjection, + ) val connectingDevice = - CastController.CastDevice().apply { state = CastController.CastDevice.STATE_CONNECTING } + CastDevice( + id = "id", + name = null, + state = CastDevice.CastState.Connecting, + origin = CastDevice.CastOrigin.MediaProjection, + ) whenever(castController.castDevices) .thenReturn(listOf(disconnectedDevice, connectingDevice)) @@ -112,11 +124,19 @@ class CastAutoAddableTest : SysuiTestCase() { @Test fun onCastDevicesChanged_someDeviceConnected_addSignal() = runTest { val disconnectedDevice = - CastController.CastDevice().apply { - state = CastController.CastDevice.STATE_DISCONNECTED - } + CastDevice( + id = "id", + name = null, + state = CastDevice.CastState.Disconnected, + origin = CastDevice.CastOrigin.MediaProjection, + ) val connectedDevice = - CastController.CastDevice().apply { state = CastController.CastDevice.STATE_CONNECTED } + CastDevice( + id = "id", + name = null, + state = CastDevice.CastState.Connected, + origin = CastDevice.CastOrigin.MediaProjection, + ) whenever(castController.castDevices).thenReturn(listOf(disconnectedDevice, connectedDevice)) val signal by collectLastValue(underTest.autoAddSignal(0)) diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/autoaddable/CastAutoAddable.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/autoaddable/CastAutoAddable.kt index b5bef9f6ebe8..88f716951001 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/autoaddable/CastAutoAddable.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/autoaddable/CastAutoAddable.kt @@ -41,12 +41,7 @@ constructor( override fun ProducerScope<AutoAddSignal>.getCallback(): CastController.Callback { return CastController.Callback { - val isCasting = - controller.castDevices.any { - it.state == CastController.CastDevice.STATE_CONNECTED || - it.state == CastController.CastDevice.STATE_CONNECTING - } - if (isCasting) { + if (controller.castDevices.any { it.isCasting }) { sendAdd() } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java index 169cdc17c2c0..8a72e8db7216 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java @@ -60,7 +60,7 @@ import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.statusbar.pipeline.shared.data.model.DefaultConnectionModel; import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository; import com.android.systemui.statusbar.policy.CastController; -import com.android.systemui.statusbar.policy.CastController.CastDevice; +import com.android.systemui.statusbar.policy.CastDevice; import com.android.systemui.statusbar.policy.HotspotController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.DialogKt; @@ -193,14 +193,13 @@ public class CastTile extends QSTileImpl<BooleanState> { // case where multiple devices were active :-/. private boolean willPopDialog() { List<CastDevice> activeDevices = getActiveDevices(); - return activeDevices.isEmpty() || (activeDevices.get(0).tag instanceof RouteInfo); + return activeDevices.isEmpty() || (activeDevices.get(0).getTag() instanceof RouteInfo); } private List<CastDevice> getActiveDevices() { ArrayList<CastDevice> activeDevices = new ArrayList<>(); for (CastDevice device : mController.getCastDevices()) { - if (device.state == CastDevice.STATE_CONNECTED - || device.state == CastDevice.STATE_CONNECTING) { + if (device.isCasting()) { activeDevices.add(device); } } @@ -276,7 +275,7 @@ public class CastTile extends QSTileImpl<BooleanState> { // We always choose the first device that's in the CONNECTED state in the case where // multiple devices are CONNECTED at the same time. for (CastDevice device : devices) { - if (device.state == CastDevice.STATE_CONNECTED) { + if (device.getState() == CastDevice.CastState.Connected) { state.value = true; state.secondaryLabel = getDeviceName(device); state.stateDescription = state.stateDescription + "," @@ -284,7 +283,7 @@ public class CastTile extends QSTileImpl<BooleanState> { R.string.accessibility_cast_name, state.label); connecting = false; break; - } else if (device.state == CastDevice.STATE_CONNECTING) { + } else if (device.getState() == CastDevice.CastState.Connecting) { connecting = true; } } @@ -315,7 +314,7 @@ public class CastTile extends QSTileImpl<BooleanState> { } private String getDeviceName(CastDevice device) { - return device.name != null ? device.name + return device.getName() != null ? device.getName() : mContext.getString(R.string.quick_settings_cast_device_default_name); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java index 201133288de5..91b5d0be6f04 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java @@ -39,7 +39,7 @@ import com.android.systemui.qs.external.CustomTile; import com.android.systemui.qs.pipeline.shared.QSPipelineFlagsRepository; import com.android.systemui.res.R; import com.android.systemui.statusbar.policy.CastController; -import com.android.systemui.statusbar.policy.CastController.CastDevice; +import com.android.systemui.statusbar.policy.CastDevice; import com.android.systemui.statusbar.policy.DataSaverController; import com.android.systemui.statusbar.policy.DataSaverController.Listener; import com.android.systemui.statusbar.policy.DeviceControlsController; @@ -430,8 +430,7 @@ public class AutoTileManager implements UserAwareController { boolean isCasting = false; for (CastDevice device : mCastController.getCastDevices()) { - if (device.state == CastDevice.STATE_CONNECTED - || device.state == CastDevice.STATE_CONNECTING) { + if (device.isCasting()) { isCasting = true; break; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java index 3784132415d1..2371eed1ca03 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java @@ -62,7 +62,7 @@ import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.phone.ui.StatusBarIconController; import com.android.systemui.statusbar.policy.BluetoothController; import com.android.systemui.statusbar.policy.CastController; -import com.android.systemui.statusbar.policy.CastController.CastDevice; +import com.android.systemui.statusbar.policy.CastDevice; import com.android.systemui.statusbar.policy.DataSaverController; import com.android.systemui.statusbar.policy.DataSaverController.Listener; import com.android.systemui.statusbar.policy.DeviceProvisionedController; @@ -521,8 +521,7 @@ public class PhoneStatusBarPolicy private void updateCast() { boolean isCasting = false; for (CastDevice device : mCast.getCastDevices()) { - if (device.state == CastDevice.STATE_CONNECTING - || device.state == CastDevice.STATE_CONNECTED) { + if (device.isCasting()) { isCasting = true; break; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastController.java index abedd3220c93..a3dcc3b6f851 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastController.java @@ -37,15 +37,4 @@ public interface CastController extends CallbackController<Callback>, Dumpable { void onCastDevicesChanged(); } - public static final class CastDevice { - public static final int STATE_DISCONNECTED = 0; - public static final int STATE_CONNECTING = 1; - public static final int STATE_CONNECTED = 2; - - public String id; - public String name; - public String description; - public int state = STATE_DISCONNECTED; - public Object tag; - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java index 64bdf605e13d..45cb52a8b1ad 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java @@ -19,15 +19,12 @@ package com.android.systemui.statusbar.policy; import static android.media.MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY; import android.content.Context; -import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; import android.media.MediaRouter; import android.media.MediaRouter.RouteInfo; import android.media.projection.MediaProjectionInfo; import android.media.projection.MediaProjectionManager; import android.os.Handler; -import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; @@ -37,8 +34,6 @@ import androidx.annotation.VisibleForTesting; import com.android.internal.annotations.GuardedBy; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dump.DumpManager; -import com.android.systemui.res.R; -import com.android.systemui.util.Utils; import java.io.PrintWriter; import java.util.ArrayList; @@ -51,10 +46,11 @@ import javax.inject.Inject; /** Platform implementation of the cast controller. **/ @SysUISingleton public class CastControllerImpl implements CastController { - private static final String TAG = "CastController"; + public static final String TAG = "CastController"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private final Context mContext; + private final PackageManager mPackageManager; @GuardedBy("mCallbacks") private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>(); private final MediaRouter mMediaRouter; @@ -68,8 +64,12 @@ public class CastControllerImpl implements CastController { private MediaProjectionInfo mProjection; @Inject - public CastControllerImpl(Context context, DumpManager dumpManager) { + public CastControllerImpl( + Context context, + PackageManager packageManager, + DumpManager dumpManager) { mContext = context; + mPackageManager = packageManager; mMediaRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE); mMediaRouter.setRouterGroupId(MediaRouter.MIRRORING_GROUP_ID); mProjectionManager = (MediaProjectionManager) @@ -156,36 +156,17 @@ public class CastControllerImpl implements CastController { final ArrayList<CastDevice> devices = new ArrayList<>(); synchronized(mRoutes) { for (RouteInfo route : mRoutes.values()) { - final CastDevice device = new CastDevice(); - device.id = route.getTag().toString(); - final CharSequence name = route.getName(mContext); - device.name = name != null ? name.toString() : null; - final CharSequence description = route.getDescription(); - device.description = description != null ? description.toString() : null; - - int statusCode = route.getStatusCode(); - if (statusCode == RouteInfo.STATUS_CONNECTING) { - device.state = CastDevice.STATE_CONNECTING; - } else if (route.isSelected() || statusCode == RouteInfo.STATUS_CONNECTED) { - device.state = CastDevice.STATE_CONNECTED; - } else { - device.state = CastDevice.STATE_DISCONNECTED; - } - - device.tag = route; - devices.add(device); + devices.add(CastDevice.Companion.toCastDevice(route, mContext)); } } synchronized (mProjectionLock) { if (mProjection != null) { - final CastDevice device = new CastDevice(); - device.id = mProjection.getPackageName(); - device.name = getAppName(mProjection.getPackageName()); - device.description = mContext.getString(R.string.quick_settings_casting); - device.state = CastDevice.STATE_CONNECTED; - device.tag = mProjection; - devices.add(device); + devices.add( + CastDevice.Companion.toCastDevice( + mProjection, + mContext, + mPackageManager)); } } @@ -194,18 +175,18 @@ public class CastControllerImpl implements CastController { @Override public void startCasting(CastDevice device) { - if (device == null || device.tag == null) return; - final RouteInfo route = (RouteInfo) device.tag; + if (device == null || device.getTag() == null) return; + final RouteInfo route = (RouteInfo) device.getTag(); if (DEBUG) Log.d(TAG, "startCasting: " + routeToString(route)); mMediaRouter.selectRoute(ROUTE_TYPE_REMOTE_DISPLAY, route); } @Override public void stopCasting(CastDevice device) { - final boolean isProjection = device.tag instanceof MediaProjectionInfo; + final boolean isProjection = device.getTag() instanceof MediaProjectionInfo; if (DEBUG) Log.d(TAG, "stopCasting isProjection=" + isProjection); if (isProjection) { - final MediaProjectionInfo projection = (MediaProjectionInfo) device.tag; + final MediaProjectionInfo projection = (MediaProjectionInfo) device.getTag(); if (Objects.equals(mProjectionManager.getActiveProjectionInfo(), projection)) { mProjectionManager.stopActiveProjection(); } else { @@ -219,7 +200,7 @@ public class CastControllerImpl implements CastController { @Override public boolean hasConnectedCastDevice() { return getCastDevices().stream().anyMatch( - castDevice -> castDevice.state == CastDevice.STATE_CONNECTED); + castDevice -> castDevice.getState() == CastDevice.CastState.Connected); } private void setProjection(MediaProjectionInfo projection, boolean started) { @@ -241,27 +222,6 @@ public class CastControllerImpl implements CastController { } } - private String getAppName(String packageName) { - final PackageManager pm = mContext.getPackageManager(); - if (Utils.isHeadlessRemoteDisplayProvider(pm, packageName)) { - return ""; - } - - try { - final ApplicationInfo appInfo = pm.getApplicationInfo(packageName, 0); - if (appInfo != null) { - final CharSequence label = appInfo.loadLabel(pm); - if (!TextUtils.isEmpty(label)) { - return label.toString(); - } - } - Log.w(TAG, "No label found for package: " + packageName); - } catch (NameNotFoundException e) { - Log.w(TAG, "Error getting appName for package: " + packageName, e); - } - return packageName; - } - private void updateRemoteDisplays() { synchronized(mRoutes) { mRoutes.clear(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastDevice.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastDevice.kt new file mode 100644 index 000000000000..5fc160bd5da3 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastDevice.kt @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2024 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.systemui.statusbar.policy + +import android.content.Context +import android.content.pm.PackageManager +import android.media.MediaRouter +import android.media.projection.MediaProjectionInfo +import android.text.TextUtils +import android.util.Log +import com.android.systemui.res.R +import com.android.systemui.util.Utils + +/** Represents a specific cast session. */ +data class CastDevice( + val id: String, + /** A human-readable name of what is receiving the cast (e.g. "Home Speaker", "Abc App"). */ + val name: String?, + /** An optional description with more information about the cast. */ + val description: String? = null, + val state: CastState, + val origin: CastOrigin, + /** Optional tag to use as a comparison value between cast sessions. */ + val tag: Any? = null, +) { + val isCasting = state == CastState.Connecting || state == CastState.Connected + + companion object { + /** Creates a [CastDevice] based on the provided information from MediaRouter. */ + fun MediaRouter.RouteInfo.toCastDevice(context: Context): CastDevice { + val state = + when { + statusCode == MediaRouter.RouteInfo.STATUS_CONNECTING -> CastState.Connecting + this.isSelected || statusCode == MediaRouter.RouteInfo.STATUS_CONNECTED -> + CastState.Connected + else -> CastState.Disconnected + } + return CastDevice( + id = this.tag.toString(), + name = this.getName(context)?.toString(), + description = this.description?.toString(), + state = state, + tag = this, + origin = CastOrigin.MediaRouter, + ) + } + + /** Creates a [CastDevice] based on the provided information from MediaProjection. */ + fun MediaProjectionInfo.toCastDevice( + context: Context, + packageManager: PackageManager + ): CastDevice { + return CastDevice( + id = this.packageName, + name = getAppName(this.packageName, packageManager), + description = context.getString(R.string.quick_settings_casting), + state = CastState.Connected, + tag = this, + origin = CastOrigin.MediaProjection, + ) + } + + private fun getAppName(packageName: String, packageManager: PackageManager): String { + if (Utils.isHeadlessRemoteDisplayProvider(packageManager, packageName)) { + return "" + } + try { + val appInfo = packageManager.getApplicationInfo(packageName, 0) + val label = appInfo.loadLabel(packageManager) + if (!TextUtils.isEmpty(label)) { + return label.toString() + } + Log.w(CastControllerImpl.TAG, "No label found for package: $packageName") + } catch (e: PackageManager.NameNotFoundException) { + Log.w(CastControllerImpl.TAG, "Error getting appName for package: $packageName", e) + } + return packageName + } + } + + enum class CastState { + Disconnected, + Connecting, + Connected, + } + + enum class CastOrigin { + /** SysUI found out about this cast device from MediaRouter APIs. */ + MediaRouter, + /** SysUI found out about this cast device from MediaProjection APIs. */ + MediaProjection, + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java index 50cf5cc5672e..9f12b189d76a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java @@ -39,7 +39,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.internal.logging.MetricsLogger; -import com.android.keyguard.TestScopeProvider; import com.android.systemui.SysuiTestCase; import com.android.systemui.animation.DialogTransitionAnimator; import com.android.systemui.classifier.FalsingManagerFake; @@ -54,14 +53,11 @@ import com.android.systemui.statusbar.connectivity.NetworkController; import com.android.systemui.statusbar.connectivity.SignalCallback; import com.android.systemui.statusbar.connectivity.WifiIndicators; import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository; -import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor; import com.android.systemui.statusbar.policy.CastController; -import com.android.systemui.statusbar.policy.CastController.CastDevice; +import com.android.systemui.statusbar.policy.CastDevice; import com.android.systemui.statusbar.policy.HotspotController; import com.android.systemui.statusbar.policy.KeyguardStateController; -import kotlinx.coroutines.test.TestScope; - import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -105,12 +101,10 @@ public class CastTileTest extends SysuiTestCase { @Mock private QsEventLogger mUiEventLogger; - private WifiInteractor mWifiInteractor; private final TileJavaAdapter mJavaAdapter = new TileJavaAdapter(); private final FakeConnectivityRepository mConnectivityRepository = new FakeConnectivityRepository(); private final FakeFeatureFlags mFeatureFlags = new FakeFeatureFlags(); - private final TestScope mTestScope = TestScopeProvider.getTestScope(); private TestableLooper mTestableLooper; private CastTile mCastTile; @@ -172,8 +166,7 @@ public class CastTileTest extends SysuiTestCase { @Test public void testStateActive_wifiEnabledAndCasting() { createAndStartTileOldImpl(); - CastController.CastDevice device = new CastController.CastDevice(); - device.state = CastController.CastDevice.STATE_CONNECTED; + CastDevice device = createConnectedCastDevice(); List<CastDevice> devices = new ArrayList<>(); devices.add(device); when(mController.getCastDevices()).thenReturn(devices); @@ -232,8 +225,7 @@ public class CastTileTest extends SysuiTestCase { @Test public void stateActive_wifiConnectedAndCasting_newPipeline() { createAndStartTileNewImpl(); - CastController.CastDevice device = new CastController.CastDevice(); - device.state = CastDevice.STATE_CONNECTED; + CastDevice device = createConnectedCastDevice(); List<CastDevice> devices = new ArrayList<>(); devices.add(device); when(mController.getCastDevices()).thenReturn(devices); @@ -248,8 +240,7 @@ public class CastTileTest extends SysuiTestCase { @Test public void stateActive_ethernetConnectedAndCasting_newPipeline() { createAndStartTileNewImpl(); - CastController.CastDevice device = new CastController.CastDevice(); - device.state = CastDevice.STATE_CONNECTED; + CastDevice device = createConnectedCastDevice(); List<CastDevice> devices = new ArrayList<>(); devices.add(device); when(mController.getCastDevices()).thenReturn(devices); @@ -286,8 +277,7 @@ public class CastTileTest extends SysuiTestCase { @Test public void testStateActive_hotspotEnabledAndConnectedAndCasting() { createAndStartTileOldImpl(); - CastController.CastDevice device = new CastController.CastDevice(); - device.state = CastController.CastDevice.STATE_CONNECTED; + CastDevice device = createConnectedCastDevice(); List<CastDevice> devices = new ArrayList<>(); devices.add(device); when(mController.getCastDevices()).thenReturn(devices); @@ -309,9 +299,13 @@ public class CastTileTest extends SysuiTestCase { @Test public void testHandleClick_castDevicePresent() { createAndStartTileOldImpl(); - CastController.CastDevice device = new CastController.CastDevice(); - device.state = CastDevice.STATE_CONNECTED; - device.tag = mock(MediaRouter.RouteInfo.class); + CastDevice device = new CastDevice( + "id", + /* name= */ null, + /* description= */ null, + /* state= */ CastDevice.CastState.Connected, + /* origin= */ CastDevice.CastOrigin.MediaRouter, + /* tag= */ mock(MediaRouter.RouteInfo.class)); List<CastDevice> devices = new ArrayList<>(); devices.add(device); when(mController.getCastDevices()).thenReturn(devices); @@ -327,9 +321,13 @@ public class CastTileTest extends SysuiTestCase { @Test public void testHandleClick_projectionOnly() { createAndStartTileOldImpl(); - CastController.CastDevice device = new CastController.CastDevice(); - device.state = CastDevice.STATE_CONNECTED; - device.tag = mock(MediaProjectionInfo.class); + CastDevice device = new CastDevice( + "id", + /* name= */ null, + /* description= */ null, + /* state= */ CastDevice.CastState.Connected, + /* origin= */ CastDevice.CastOrigin.MediaProjection, + /* tag= */ mock(MediaProjectionInfo.class)); List<CastDevice> devices = new ArrayList<>(); devices.add(device); when(mController.getCastDevices()).thenReturn(devices); @@ -344,31 +342,40 @@ public class CastTileTest extends SysuiTestCase { @Test public void testUpdateState_projectionOnly() { createAndStartTileOldImpl(); - CastController.CastDevice device = new CastController.CastDevice(); - device.state = CastDevice.STATE_CONNECTED; - device.tag = mock(MediaProjectionInfo.class); - device.name = "Test Projection Device"; + CastDevice device = new CastDevice( + "id", + /* name= */ "Test Projection Device", + /* description= */ null, + /* state= */ CastDevice.CastState.Connected, + /* origin= */ CastDevice.CastOrigin.MediaProjection, + /* tag= */ mock(MediaProjectionInfo.class)); List<CastDevice> devices = new ArrayList<>(); devices.add(device); when(mController.getCastDevices()).thenReturn(devices); enableWifiAndProcessMessages(); assertEquals(Tile.STATE_ACTIVE, mCastTile.getState().state); - assertTrue(mCastTile.getState().secondaryLabel.toString().startsWith(device.name)); + assertTrue(mCastTile.getState().secondaryLabel.toString() + .startsWith("Test Projection Device")); } @Test public void testUpdateState_castingAndProjection() { createAndStartTileOldImpl(); - CastController.CastDevice casting = new CastController.CastDevice(); - casting.state = CastDevice.STATE_CONNECTED; - casting.tag = mock(RouteInfo.class); - casting.name = "Test Casting Device"; - - CastController.CastDevice projection = new CastController.CastDevice(); - projection.state = CastDevice.STATE_CONNECTED; - projection.tag = mock(MediaProjectionInfo.class); - projection.name = "Test Projection Device"; + CastDevice casting = new CastDevice( + "id1", + /* name= */ "Test Casting Device", + /* description= */ null, + /* state= */ CastDevice.CastState.Connected, + /* origin= */ CastDevice.CastOrigin.MediaRouter, + /* tag= */ mock(RouteInfo.class)); + CastDevice projection = new CastDevice( + "id2", + /* name= */ "Test Projection Device", + /* description= */ null, + /* state= */ CastDevice.CastState.Connected, + /* origin= */ CastDevice.CastOrigin.MediaProjection, + /* tag= */ mock(MediaProjectionInfo.class)); List<CastDevice> devices = new ArrayList<>(); devices.add(casting); @@ -379,22 +386,27 @@ public class CastTileTest extends SysuiTestCase { // Note here that the tile should be active, and should choose casting over projection. assertEquals(Tile.STATE_ACTIVE, mCastTile.getState().state); - assertTrue(mCastTile.getState().secondaryLabel.toString().startsWith(casting.name)); + assertTrue(mCastTile.getState().secondaryLabel.toString() + .startsWith("Test Casting Device")); } @Test public void testUpdateState_connectedAndConnecting() { createAndStartTileOldImpl(); - CastController.CastDevice connecting = new CastController.CastDevice(); - connecting.state = CastDevice.STATE_CONNECTING; - connecting.tag = mock(RouteInfo.class); - connecting.name = "Test Casting Device"; - - CastController.CastDevice connected = new CastController.CastDevice(); - connected.state = CastDevice.STATE_CONNECTED; - connected.tag = mock(RouteInfo.class); - connected.name = "Test Casting Device"; - + CastDevice connecting = new CastDevice( + "id", + /* name= */ "Test Connecting Device", + /* description= */ null, + /* state= */ CastDevice.CastState.Connecting, + /* origin= */ CastDevice.CastOrigin.MediaRouter, + /* tag= */ mock(RouteInfo.class)); + CastDevice connected = new CastDevice( + "id", + /* name= */ "Test Connected Device", + /* description= */ null, + /* state= */ CastDevice.CastState.Connected, + /* origin= */ CastDevice.CastOrigin.MediaRouter, + /* tag= */ mock(RouteInfo.class)); List<CastDevice> devices = new ArrayList<>(); devices.add(connecting); devices.add(connected); @@ -404,7 +416,8 @@ public class CastTileTest extends SysuiTestCase { // Tile should be connected and always prefer the connected device. assertEquals(Tile.STATE_ACTIVE, mCastTile.getState().state); - assertTrue(mCastTile.getState().secondaryLabel.toString().startsWith(connected.name)); + assertTrue(mCastTile.getState().secondaryLabel.toString() + .startsWith("Test Connected Device")); } @Test @@ -427,8 +440,7 @@ public class CastTileTest extends SysuiTestCase { @Test public void testExpandView_casting_projection() { createAndStartTileOldImpl(); - CastController.CastDevice device = new CastController.CastDevice(); - device.state = CastController.CastDevice.STATE_CONNECTED; + CastDevice device = createConnectedCastDevice(); List<CastDevice> devices = new ArrayList<>(); devices.add(device); when(mController.getCastDevices()).thenReturn(devices); @@ -441,9 +453,14 @@ public class CastTileTest extends SysuiTestCase { @Test public void testExpandView_connecting_projection() { createAndStartTileOldImpl(); - CastController.CastDevice connecting = new CastController.CastDevice(); - connecting.state = CastDevice.STATE_CONNECTING; - connecting.name = "Test Casting Device"; + CastDevice connecting = new CastDevice( + "id", + /* name= */ + "Test Projection Device", + /* description= */ null, + /* state= */ CastDevice.CastState.Connected, + /* origin= */ CastDevice.CastOrigin.MediaProjection, + /* tag= */ mock(MediaProjectionInfo.class)); List<CastDevice> devices = new ArrayList<>(); devices.add(connecting); @@ -457,9 +474,14 @@ public class CastTileTest extends SysuiTestCase { @Test public void testExpandView_casting_mediaRoute() { createAndStartTileOldImpl(); - CastController.CastDevice device = new CastController.CastDevice(); - device.state = CastDevice.STATE_CONNECTED; - device.tag = mock(MediaRouter.RouteInfo.class); + CastDevice device = new CastDevice( + "id", + /* name= */ "Test Router Device", + /* description= */ null, + /* state= */ CastDevice.CastState.Connected, + /* origin= */ CastDevice.CastOrigin.MediaRouter, + /* tag= */ mock(RouteInfo.class)); + List<CastDevice> devices = new ArrayList<>(); devices.add(device); when(mController.getCastDevices()).thenReturn(devices); @@ -472,11 +494,13 @@ public class CastTileTest extends SysuiTestCase { @Test public void testExpandView_connecting_mediaRoute() { createAndStartTileOldImpl(); - CastController.CastDevice connecting = new CastController.CastDevice(); - connecting.state = CastDevice.STATE_CONNECTING; - connecting.tag = mock(RouteInfo.class); - connecting.name = "Test Casting Device"; - + CastDevice connecting = new CastDevice( + "id", + /* name= */ "Test Router Device", + /* description= */ null, + /* state= */ CastDevice.CastState.Connecting, + /* origin= */ CastDevice.CastOrigin.MediaRouter, + /* tag= */ mock(RouteInfo.class)); List<CastDevice> devices = new ArrayList<>(); devices.add(connecting); when(mController.getCastDevices()).thenReturn(devices); @@ -567,4 +591,14 @@ public class CastTileTest extends SysuiTestCase { hotspotCallbackArgumentCaptor.capture()); mHotspotCallback = hotspotCallbackArgumentCaptor.getValue(); } + + private CastDevice createConnectedCastDevice() { + return new CastDevice( + "id", + /* name= */ null, + /* description= */ null, + /* state= */ CastDevice.CastState.Connected, + /* origin= */ CastDevice.CastOrigin.MediaProjection, + /* tag= */ null); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java index f0bc655a554d..665544d094e4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java @@ -61,7 +61,7 @@ import com.android.systemui.qs.UserSettingObserver; import com.android.systemui.qs.external.CustomTile; import com.android.systemui.res.R; import com.android.systemui.statusbar.policy.CastController; -import com.android.systemui.statusbar.policy.CastController.CastDevice; +import com.android.systemui.statusbar.policy.CastDevice; import com.android.systemui.statusbar.policy.DataSaverController; import com.android.systemui.statusbar.policy.DeviceControlsController; import com.android.systemui.statusbar.policy.HotspotController; @@ -422,9 +422,17 @@ public class AutoTileManagerTest extends SysuiTestCase { } private static List<CastDevice> buildFakeCastDevice(boolean isCasting) { - CastDevice cd = new CastDevice(); - cd.state = isCasting ? CastDevice.STATE_CONNECTED : CastDevice.STATE_DISCONNECTED; - return Collections.singletonList(cd); + CastDevice.CastState state = isCasting + ? CastDevice.CastState.Connected + : CastDevice.CastState.Disconnected; + return Collections.singletonList( + new CastDevice( + "id", + /* name= */ null, + /* description= */ null, + /* state= */ state, + /* origin= */ CastDevice.CastOrigin.MediaProjection, + /* tag= */ null)); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CastControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CastControllerImplTest.java index 68c1b8d3f44f..6894e6c304d0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CastControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CastControllerImplTest.java @@ -9,6 +9,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.content.pm.PackageManager; import android.media.MediaRouter; import android.media.projection.MediaProjectionInfo; import android.media.projection.MediaProjectionManager; @@ -52,8 +53,12 @@ public class CastControllerImplTest extends SysuiTestCase { mContext.addMockSystemService(MediaRouter.class, mMediaRouter); mContext.addMockSystemService(MediaProjectionManager.class, mMediaProjectionManager); when(mMediaProjectionManager.getActiveProjectionInfo()).thenReturn(mProjection); + when(mProjection.getPackageName()).thenReturn("fake.package"); - mController = new CastControllerImpl(mContext, mock(DumpManager.class)); + mController = new CastControllerImpl( + mContext, + mock(PackageManager.class), + mock(DumpManager.class)); } @Test @@ -148,16 +153,26 @@ public class CastControllerImplTest extends SysuiTestCase { @Test public void hasConnectedCastDevice_connected() { - CastController.CastDevice castDevice = new CastController.CastDevice(); - castDevice.state = CastController.CastDevice.STATE_CONNECTED; + CastDevice castDevice = new CastDevice( + "id", + /* name= */ null, + /* description= */ null, + /* state= */ CastDevice.CastState.Connected, + /* origin= */ CastDevice.CastOrigin.MediaProjection, + /* tag= */ null); mController.startCasting(castDevice); assertTrue(mController.hasConnectedCastDevice()); } @Test public void hasConnectedCastDevice_notConnected() { - CastController.CastDevice castDevice = new CastController.CastDevice(); - castDevice.state = CastController.CastDevice.STATE_CONNECTING; + CastDevice castDevice = new CastDevice( + "id", + /* name= */ null, + /* description= */ null, + /* state= */ CastDevice.CastState.Connecting, + /* origin= */ CastDevice.CastOrigin.MediaProjection, + /* tag= */ null); mController.startCasting(castDevice); assertTrue(mController.hasConnectedCastDevice()); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CastDeviceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CastDeviceTest.kt new file mode 100644 index 000000000000..03ad66cd4cce --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CastDeviceTest.kt @@ -0,0 +1,441 @@ +/* + * Copyright (C) 2024 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.systemui.statusbar.policy + +import android.Manifest +import android.content.Intent +import android.content.pm.ApplicationInfo +import android.content.pm.PackageManager +import android.content.pm.ResolveInfo +import android.media.MediaRouter +import android.media.projection.MediaProjectionInfo +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.res.R +import com.android.systemui.statusbar.policy.CastDevice.Companion.toCastDevice +import com.google.common.truth.Truth.assertThat +import kotlin.test.Test +import org.mockito.ArgumentMatchers +import org.mockito.Mockito.doAnswer +import org.mockito.kotlin.any +import org.mockito.kotlin.eq +import org.mockito.kotlin.mock +import org.mockito.kotlin.whenever + +@SmallTest +class CastDeviceTest : SysuiTestCase() { + private val mockAppInfo = + mock<ApplicationInfo>().apply { whenever(this.loadLabel(any())).thenReturn("") } + + private val packageManager = + mock<PackageManager>().apply { + whenever( + this.checkPermission( + Manifest.permission.REMOTE_DISPLAY_PROVIDER, + HEADLESS_REMOTE_PACKAGE, + ) + ) + .thenReturn(PackageManager.PERMISSION_GRANTED) + whenever( + this.checkPermission( + Manifest.permission.REMOTE_DISPLAY_PROVIDER, + NORMAL_PACKAGE, + ) + ) + .thenReturn(PackageManager.PERMISSION_DENIED) + + doAnswer { + // See Utils.isHeadlessRemoteDisplayProvider + if ((it.arguments[0] as Intent).`package` == HEADLESS_REMOTE_PACKAGE) { + emptyList() + } else { + listOf(mock<ResolveInfo>()) + } + } + .whenever(this) + .queryIntentActivities(any(), ArgumentMatchers.anyInt()) + + whenever(this.getApplicationInfo(any<String>(), any<Int>())).thenReturn(mockAppInfo) + } + + @Test + fun isCasting_disconnected_false() { + val device = + CastDevice( + id = "id", + name = "name", + state = CastDevice.CastState.Disconnected, + origin = CastDevice.CastOrigin.MediaRouter, + ) + + assertThat(device.isCasting).isFalse() + } + + @Test + fun isCasting_connecting_true() { + val device = + CastDevice( + id = "id", + name = "name", + state = CastDevice.CastState.Connecting, + origin = CastDevice.CastOrigin.MediaRouter, + ) + + assertThat(device.isCasting).isTrue() + } + + @Test + fun isCasting_connected_true() { + val device = + CastDevice( + id = "id", + name = "name", + state = CastDevice.CastState.Connected, + origin = CastDevice.CastOrigin.MediaRouter, + ) + + assertThat(device.isCasting).isTrue() + } + + @Test + fun routeToCastDevice_statusNone_stateDisconnected() { + val route = + mockRouteInfo().apply { + whenever(this.statusCode).thenReturn(MediaRouter.RouteInfo.STATUS_NONE) + } + + val device = route.toCastDevice(context) + + assertThat(device.state).isEqualTo(CastDevice.CastState.Disconnected) + } + + @Test + fun routeToCastDevice_statusNotAvailable_stateDisconnected() { + val route = + mockRouteInfo().apply { + whenever(this.statusCode).thenReturn(MediaRouter.RouteInfo.STATUS_NOT_AVAILABLE) + } + + val device = route.toCastDevice(context) + + assertThat(device.state).isEqualTo(CastDevice.CastState.Disconnected) + } + + @Test + fun routeToCastDevice_statusScanning_stateDisconnected() { + val route = + mockRouteInfo().apply { + whenever(this.statusCode).thenReturn(MediaRouter.RouteInfo.STATUS_SCANNING) + } + + val device = route.toCastDevice(context) + + assertThat(device.state).isEqualTo(CastDevice.CastState.Disconnected) + } + + @Test + fun routeToCastDevice_statusAvailable_isSelectedFalse_stateDisconnected() { + val route = + mockRouteInfo().apply { + whenever(this.statusCode).thenReturn(MediaRouter.RouteInfo.STATUS_AVAILABLE) + whenever(this.isSelected).thenReturn(false) + } + + val device = route.toCastDevice(context) + + assertThat(device.state).isEqualTo(CastDevice.CastState.Disconnected) + } + + @Test + fun routeToCastDevice_statusAvailable_isSelectedTrue_stateConnected() { + val route = + mockRouteInfo().apply { + whenever(this.statusCode).thenReturn(MediaRouter.RouteInfo.STATUS_AVAILABLE) + whenever(this.isSelected).thenReturn(true) + } + + val device = route.toCastDevice(context) + + assertThat(device.state).isEqualTo(CastDevice.CastState.Connected) + } + + @Test + fun routeToCastDevice_statusInUse_isSelectedFalse_stateDisconnected() { + val route = + mockRouteInfo().apply { + whenever(this.statusCode).thenReturn(MediaRouter.RouteInfo.STATUS_IN_USE) + whenever(this.isSelected).thenReturn(false) + } + + val device = route.toCastDevice(context) + + assertThat(device.state).isEqualTo(CastDevice.CastState.Disconnected) + } + + @Test + fun routeToCastDevice_statusInUse_isSelectedTrue_stateConnected() { + val route = + mockRouteInfo().apply { + whenever(this.statusCode).thenReturn(MediaRouter.RouteInfo.STATUS_IN_USE) + whenever(this.isSelected).thenReturn(true) + } + + val device = route.toCastDevice(context) + + assertThat(device.state).isEqualTo(CastDevice.CastState.Connected) + } + + @Test + fun routeToCastDevice_statusConnecting_isSelectedFalse_stateConnecting() { + val route = + mockRouteInfo().apply { + whenever(this.statusCode).thenReturn(MediaRouter.RouteInfo.STATUS_CONNECTING) + whenever(this.isSelected).thenReturn(false) + } + + val device = route.toCastDevice(context) + + assertThat(device.state).isEqualTo(CastDevice.CastState.Connecting) + } + + @Test + fun routeToCastDevice_statusConnecting_isSelectedTrue_stateConnecting() { + val route = + mockRouteInfo().apply { + whenever(this.statusCode).thenReturn(MediaRouter.RouteInfo.STATUS_CONNECTING) + whenever(this.isSelected).thenReturn(true) + } + + val device = route.toCastDevice(context) + + assertThat(device.state).isEqualTo(CastDevice.CastState.Connecting) + } + + @Test + fun routeToCastDevice_statusConnected_isSelectedFalse_stateConnected() { + val route = + mockRouteInfo().apply { + whenever(this.statusCode).thenReturn(MediaRouter.RouteInfo.STATUS_CONNECTED) + whenever(this.isSelected).thenReturn(false) + } + + val device = route.toCastDevice(context) + + assertThat(device.state).isEqualTo(CastDevice.CastState.Connected) + } + + @Test + fun routeToCastDevice_statusConnected_isSelectedTrue_stateConnected() { + val route = + mockRouteInfo().apply { + whenever(this.statusCode).thenReturn(MediaRouter.RouteInfo.STATUS_CONNECTED) + whenever(this.isSelected).thenReturn(true) + } + + val device = route.toCastDevice(context) + + assertThat(device.state).isEqualTo(CastDevice.CastState.Connected) + } + + @Test + fun routeToCastDevice_tagIsStringType_idMatchesTag() { + val route = mock<MediaRouter.RouteInfo>().apply { whenever(this.tag).thenReturn("FakeTag") } + + val device = route.toCastDevice(context) + + assertThat(device.id).isEqualTo("FakeTag") + } + + @Test + fun routeToCastDevice_tagIsOtherType_idMatchesTag() { + val tag = listOf("tag1", "tag2") + val route = mock<MediaRouter.RouteInfo>().apply { whenever(this.tag).thenReturn(tag) } + + val device = route.toCastDevice(context) + + assertThat(device.id).isEqualTo(tag.toString()) + } + + @Test + fun routeToCastDevice_nameMatchesName() { + val route = mockRouteInfo().apply { whenever(this.getName(context)).thenReturn("FakeName") } + + val device = route.toCastDevice(context) + + assertThat(device.name).isEqualTo("FakeName") + } + + @Test + fun routeToCastDevice_descriptionMatchesDescription() { + val route = + mockRouteInfo().apply { whenever(this.description).thenReturn("FakeDescription") } + + val device = route.toCastDevice(context) + + assertThat(device.description).isEqualTo("FakeDescription") + } + + @Test + fun routeToCastDevice_tagIsRoute() { + val route = mockRouteInfo() + + val device = route.toCastDevice(context) + + assertThat(device.tag).isEqualTo(route) + } + + @Test + fun routeToCastDevice_originIsMediaRouter() { + val route = mockRouteInfo() + + val device = route.toCastDevice(context) + + assertThat(device.origin).isEqualTo(CastDevice.CastOrigin.MediaRouter) + } + + @Test + fun routeToCastDevice_nullValues_ok() { + val device = mockRouteInfo().toCastDevice(context) + + assertThat(device.name).isNull() + assertThat(device.description).isNull() + } + + @Test + fun projectionToCastDevice_idMatchesPackage() { + val projection = + mock<MediaProjectionInfo>().apply { + whenever(this.packageName).thenReturn("fake.package") + } + + val device = projection.toCastDevice(context, packageManager) + + assertThat(device.id).isEqualTo("fake.package") + } + + @Test + fun projectionToCastDevice_name_packageIsHeadlessRemote_isEmpty() { + val projection = + mock<MediaProjectionInfo>().apply { + whenever(this.packageName).thenReturn(HEADLESS_REMOTE_PACKAGE) + } + + val device = projection.toCastDevice(context, packageManager) + + assertThat(device.name).isEmpty() + } + + @Test + fun projectionToCastDevice_name_packageMissingFromPackageManager_isPackageName() { + val projection = + mock<MediaProjectionInfo>().apply { + whenever(this.packageName).thenReturn(NORMAL_PACKAGE) + } + + whenever(packageManager.getApplicationInfo(eq(NORMAL_PACKAGE), any<Int>())) + .thenThrow(PackageManager.NameNotFoundException()) + + val device = projection.toCastDevice(context, packageManager) + + assertThat(device.name).isEqualTo(NORMAL_PACKAGE) + } + + @Test + fun projectionToCastDevice_name_nameFromPackageManagerEmpty_isPackageName() { + val projection = + mock<MediaProjectionInfo>().apply { + whenever(this.packageName).thenReturn(NORMAL_PACKAGE) + } + + val appInfo = mock<ApplicationInfo>() + whenever(appInfo.loadLabel(packageManager)).thenReturn("") + whenever(packageManager.getApplicationInfo(eq(NORMAL_PACKAGE), any<Int>())) + .thenReturn(appInfo) + + val device = projection.toCastDevice(context, packageManager) + + assertThat(device.name).isEqualTo(NORMAL_PACKAGE) + } + + @Test + fun projectionToCastDevice_name_packageManagerHasName_isName() { + val projection = + mock<MediaProjectionInfo>().apply { + whenever(this.packageName).thenReturn(NORMAL_PACKAGE) + } + + val appInfo = mock<ApplicationInfo>() + whenever(appInfo.loadLabel(packageManager)).thenReturn("Valid App Name") + whenever(packageManager.getApplicationInfo(eq(NORMAL_PACKAGE), any<Int>())) + .thenReturn(appInfo) + + val device = projection.toCastDevice(context, packageManager) + + assertThat(device.name).isEqualTo("Valid App Name") + } + + @Test + fun projectionToCastDevice_descriptionIsCasting() { + val projection = mockProjectionInfo() + + val device = projection.toCastDevice(context, packageManager) + + assertThat(device.description).isEqualTo(context.getString(R.string.quick_settings_casting)) + } + + @Test + fun projectionToCastDevice_stateIsConnected() { + val projection = mockProjectionInfo() + + val device = projection.toCastDevice(context, packageManager) + + assertThat(device.state).isEqualTo(CastDevice.CastState.Connected) + } + + @Test + fun projectionToCastDevice_tagIsProjection() { + val projection = mockProjectionInfo() + + val device = projection.toCastDevice(context, packageManager) + + assertThat(device.tag).isEqualTo(projection) + } + + @Test + fun projectionToCastDevice_originIsMediaProjection() { + val projection = mockProjectionInfo() + + val device = projection.toCastDevice(context, packageManager) + + assertThat(device.origin).isEqualTo(CastDevice.CastOrigin.MediaProjection) + } + + private fun mockRouteInfo(): MediaRouter.RouteInfo { + return mock<MediaRouter.RouteInfo>().apply { whenever(this.tag).thenReturn(Any()) } + } + + private fun mockProjectionInfo(): MediaProjectionInfo { + return mock<MediaProjectionInfo>().apply { + whenever(this.packageName).thenReturn("fake.package") + } + } + + private companion object { + const val HEADLESS_REMOTE_PACKAGE = "headless.remote.package" + const val NORMAL_PACKAGE = "normal.package" + } +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeCastController.java b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeCastController.java index 84ace7cc9540..5fae38f4a82b 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeCastController.java +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeCastController.java @@ -18,6 +18,7 @@ import android.testing.LeakCheck; import com.android.systemui.statusbar.policy.CastController; import com.android.systemui.statusbar.policy.CastController.Callback; +import com.android.systemui.statusbar.policy.CastDevice; import java.util.ArrayList; import java.util.List; |