diff options
11 files changed, 287 insertions, 14 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index 99e33ea8e619..27541e809902 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -374,6 +374,9 @@ object Flags { @JvmField val INCOMPATIBLE_CHARGING_BATTERY_ICON = unreleasedFlag(614, "incompatible_charging_battery_icon") + // TODO(b/293585143): Tracking Bug + val INSTANT_TETHER = unreleasedFlag(615, "instant_tether") + // 700 - dialer/calls // TODO(b/254512734): Tracking Bug val ONGOING_CALL_STATUS_BAR_CHIP = releasedFlag(700, "ongoing_call_status_bar_chip") diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoModeWifiDataSource.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoModeWifiDataSource.kt index 7d2501ca0e79..ab9b516b837f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoModeWifiDataSource.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoModeWifiDataSource.kt @@ -24,6 +24,7 @@ import com.android.systemui.demomode.DemoMode.COMMAND_NETWORK import com.android.systemui.demomode.DemoModeController import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.SharingStarted @@ -56,12 +57,14 @@ constructor( val activity = getString("activity").toActivity() val ssid = getString("ssid") val validated = getString("fully").toBoolean() + val hotspotDeviceType = getString("hotspot").toHotspotDeviceType() return FakeWifiEventModel.Wifi( level = level, activity = activity, ssid = ssid, validated = validated, + hotspotDeviceType, ) } @@ -82,6 +85,20 @@ constructor( else -> WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE } + private fun String?.toHotspotDeviceType(): WifiNetworkModel.HotspotDeviceType { + return when (this) { + null, + "none" -> WifiNetworkModel.HotspotDeviceType.NONE + "unknown" -> WifiNetworkModel.HotspotDeviceType.UNKNOWN + "phone" -> WifiNetworkModel.HotspotDeviceType.PHONE + "tablet" -> WifiNetworkModel.HotspotDeviceType.TABLET + "laptop" -> WifiNetworkModel.HotspotDeviceType.LAPTOP + "watch" -> WifiNetworkModel.HotspotDeviceType.WATCH + "auto" -> WifiNetworkModel.HotspotDeviceType.AUTO + else -> WifiNetworkModel.HotspotDeviceType.INVALID + } + } + companion object { const val DEFAULT_CARRIER_MERGED_SUB_ID = 10 } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoWifiRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoWifiRepository.kt index a57be665f105..99b680056d7f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoWifiRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoWifiRepository.kt @@ -97,6 +97,7 @@ constructor( isValidated = validated ?: true, level = level ?: 0, ssid = ssid ?: DEMO_NET_SSID, + hotspotDeviceType = hotspotDeviceType, // These fields below aren't supported in demo mode, since they aren't needed to satisfy // the interface. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/model/FakeWifiEventModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/model/FakeWifiEventModel.kt index f5035cbc0215..b2e843e283f7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/model/FakeWifiEventModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/model/FakeWifiEventModel.kt @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model import android.telephony.Annotation +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel /** * Model for demo wifi commands, ported from [NetworkControllerImpl] @@ -29,6 +30,8 @@ sealed interface FakeWifiEventModel { @Annotation.DataActivityType val activity: Int, val ssid: String?, val validated: Boolean?, + val hotspotDeviceType: WifiNetworkModel.HotspotDeviceType = + WifiNetworkModel.HotspotDeviceType.NONE, ) : FakeWifiEventModel data class CarrierMerged( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt index 9944c00c6ee7..946c571998ac 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt @@ -261,6 +261,8 @@ constructor( isValidated = networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED), level = wifiManager.calculateSignalLevel(wifiInfo.rssi), wifiInfo.ssid, + // This repository doesn't support any hotspot information. + WifiNetworkModel.HotspotDeviceType.NONE, wifiInfo.isPasspointAp, wifiInfo.isOsuAp, wifiInfo.passpointProviderFriendlyName diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLib.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLib.kt index 6f1ac34de9d3..43f8bc6ef3f8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLib.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLib.kt @@ -23,6 +23,8 @@ import androidx.lifecycle.LifecycleRegistry import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.flags.FeatureFlags +import com.android.systemui.flags.Flags import com.android.systemui.log.LogBuffer import com.android.systemui.log.core.LogLevel import com.android.systemui.log.table.TableLogBuffer @@ -37,6 +39,8 @@ import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiReposito import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl.Companion.WIFI_NETWORK_DEFAULT import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl.Companion.WIFI_STATE_DEFAULT import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel +import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel.Inactive.toHotspotDeviceType +import com.android.wifitrackerlib.HotspotNetworkEntry import com.android.wifitrackerlib.MergedCarrierEntry import com.android.wifitrackerlib.WifiEntry import com.android.wifitrackerlib.WifiPickerTracker @@ -61,6 +65,7 @@ import kotlinx.coroutines.flow.stateIn class WifiRepositoryViaTrackerLib @Inject constructor( + featureFlags: FeatureFlags, @Application private val scope: CoroutineScope, @Main private val mainExecutor: Executor, private val wifiPickerTrackerFactory: WifiPickerTrackerFactory, @@ -74,6 +79,8 @@ constructor( mainExecutor.execute { it.currentState = Lifecycle.State.CREATED } } + private val isInstantTetherEnabled = featureFlags.isEnabled(Flags.INSTANT_TETHER) + private var wifiPickerTracker: WifiPickerTracker? = null private val wifiPickerTrackerInfo: StateFlow<WifiPickerTrackerInfo> = run { @@ -181,11 +188,19 @@ constructor( numberOfLevels = wifiManager.maxSignalLevel + 1, ) } else { + val hotspotDeviceType = + if (isInstantTetherEnabled && this is HotspotNetworkEntry) { + this.deviceType.toHotspotDeviceType() + } else { + WifiNetworkModel.HotspotDeviceType.NONE + } + WifiNetworkModel.Active( networkId = NETWORK_ID, isValidated = this.hasInternetAccess(), level = this.level, ssid = this.title, + hotspotDeviceType = hotspotDeviceType, // With WifiTrackerLib, [WifiEntry.title] will appropriately fetch the SSID for // typical wifi networks *and* passpoint/OSU APs. So, the AP-specific values can // always be false/null in this repository. @@ -259,6 +274,7 @@ constructor( class Factory @Inject constructor( + private val featureFlags: FeatureFlags, @Application private val scope: CoroutineScope, @Main private val mainExecutor: Executor, private val wifiPickerTrackerFactory: WifiPickerTrackerFactory, @@ -267,6 +283,7 @@ constructor( ) { fun create(wifiManager: WifiManager): WifiRepositoryViaTrackerLib { return WifiRepositoryViaTrackerLib( + featureFlags, scope, mainExecutor, wifiPickerTrackerFactory, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModel.kt index 4b33c88cea30..c11640a31b82 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModel.kt @@ -17,11 +17,13 @@ package com.android.systemui.statusbar.pipeline.wifi.shared.model import android.net.wifi.WifiManager.UNKNOWN_SSID +import android.net.wifi.sharedconnectivity.app.NetworkProviderInfo import android.telephony.SubscriptionManager import androidx.annotation.VisibleForTesting import com.android.systemui.log.table.Diffable import com.android.systemui.log.table.TableRowLogger import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository +import com.android.wifitrackerlib.HotspotNetworkEntry.DeviceType /** Provides information about the current wifi network. */ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> { @@ -52,6 +54,7 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> { row.logChange(COL_LEVEL, LEVEL_DEFAULT) row.logChange(COL_NUM_LEVELS, NUM_LEVELS_DEFAULT) row.logChange(COL_SSID, null) + row.logChange(COL_HOTSPOT, null) row.logChange(COL_PASSPOINT_ACCESS_POINT, false) row.logChange(COL_ONLINE_SIGN_UP, false) row.logChange(COL_PASSPOINT_NAME, null) @@ -83,6 +86,7 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> { row.logChange(COL_LEVEL, LEVEL_DEFAULT) row.logChange(COL_NUM_LEVELS, NUM_LEVELS_DEFAULT) row.logChange(COL_SSID, null) + row.logChange(COL_HOTSPOT, null) row.logChange(COL_PASSPOINT_ACCESS_POINT, false) row.logChange(COL_ONLINE_SIGN_UP, false) row.logChange(COL_PASSPOINT_NAME, null) @@ -110,6 +114,7 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> { row.logChange(COL_LEVEL, LEVEL_DEFAULT) row.logChange(COL_NUM_LEVELS, NUM_LEVELS_DEFAULT) row.logChange(COL_SSID, null) + row.logChange(COL_HOTSPOT, null) row.logChange(COL_PASSPOINT_ACCESS_POINT, false) row.logChange(COL_ONLINE_SIGN_UP, false) row.logChange(COL_PASSPOINT_NAME, null) @@ -184,6 +189,7 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> { row.logChange(COL_LEVEL, level) row.logChange(COL_NUM_LEVELS, numberOfLevels) row.logChange(COL_SSID, null) + row.logChange(COL_HOTSPOT, null) row.logChange(COL_PASSPOINT_ACCESS_POINT, false) row.logChange(COL_ONLINE_SIGN_UP, false) row.logChange(COL_PASSPOINT_NAME, null) @@ -209,6 +215,12 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> { /** See [android.net.wifi.WifiInfo.ssid]. */ val ssid: String? = null, + /** + * The type of device providing a hotspot connection, or [HotspotDeviceType.NONE] if this + * isn't a hotspot connection. + */ + val hotspotDeviceType: HotspotDeviceType = WifiNetworkModel.HotspotDeviceType.NONE, + /** See [android.net.wifi.WifiInfo.isPasspointAp]. */ val isPasspointAccessPoint: Boolean = false, @@ -247,6 +259,9 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> { if (prevVal.ssid != ssid) { row.logChange(COL_SSID, ssid) } + if (prevVal.hotspotDeviceType != hotspotDeviceType) { + row.logChange(COL_HOTSPOT, hotspotDeviceType.name) + } // TODO(b/238425913): The passpoint-related values are frequently never used, so it // would be great to not log them when they're not used. @@ -272,6 +287,7 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> { row.logChange(COL_LEVEL, level) row.logChange(COL_NUM_LEVELS, null) row.logChange(COL_SSID, ssid) + row.logChange(COL_HOTSPOT, hotspotDeviceType.name) row.logChange(COL_PASSPOINT_ACCESS_POINT, isPasspointAccessPoint) row.logChange(COL_ONLINE_SIGN_UP, isOnlineSignUpForPasspointAccessPoint) row.logChange(COL_PASSPOINT_NAME, passpointProviderFriendlyName) @@ -305,6 +321,40 @@ sealed class WifiNetworkModel : Diffable<WifiNetworkModel> { companion object { @VisibleForTesting internal const val MIN_VALID_LEVEL = 0 } + + /** + * Enum for the type of device providing the hotspot connection, or [NONE] if this connection + * isn't a hotspot. + */ + enum class HotspotDeviceType { + /* This wifi connection isn't a hotspot. */ + NONE, + /** The device type for this hotspot is unknown. */ + UNKNOWN, + PHONE, + TABLET, + LAPTOP, + WATCH, + AUTO, + /** The device type sent for this hotspot is invalid to SysUI. */ + INVALID, + } + + /** + * Converts a device type from [com.android.wifitrackerlib.HotspotNetworkEntry.deviceType] to + * our internal representation. + */ + fun @receiver:DeviceType Int.toHotspotDeviceType(): HotspotDeviceType { + return when (this) { + NetworkProviderInfo.DEVICE_TYPE_UNKNOWN -> HotspotDeviceType.UNKNOWN + NetworkProviderInfo.DEVICE_TYPE_PHONE -> HotspotDeviceType.PHONE + NetworkProviderInfo.DEVICE_TYPE_TABLET -> HotspotDeviceType.TABLET + NetworkProviderInfo.DEVICE_TYPE_LAPTOP -> HotspotDeviceType.LAPTOP + NetworkProviderInfo.DEVICE_TYPE_WATCH -> HotspotDeviceType.WATCH + NetworkProviderInfo.DEVICE_TYPE_AUTO -> HotspotDeviceType.AUTO + else -> HotspotDeviceType.INVALID + } + } } const val TYPE_CARRIER_MERGED = "CarrierMerged" @@ -319,6 +369,7 @@ const val COL_VALIDATED = "isValidated" const val COL_LEVEL = "level" const val COL_NUM_LEVELS = "maxLevel" const val COL_SSID = "ssid" +const val COL_HOTSPOT = "hotspot" const val COL_PASSPOINT_ACCESS_POINT = "isPasspointAccessPoint" const val COL_ONLINE_SIGN_UP = "isOnlineSignUpForPasspointAccessPoint" const val COL_PASSPOINT_NAME = "passpointProviderFriendlyName" diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java index e7d420bcb32b..9016220b40cf 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java @@ -419,7 +419,15 @@ public class CarrierTextManagerTest extends SysuiTestCase { assertFalse(mWifiRepository.isWifiConnectedWithValidSsid()); mWifiRepository.setWifiNetwork( - new WifiNetworkModel.Active(0, false, 0, "", false, false, null)); + new WifiNetworkModel.Active( + /* networkId= */ 0, + /* isValidated= */ false, + /* level= */ 0, + /* ssid= */ "", + /* hotspotDeviceType= */ WifiNetworkModel.HotspotDeviceType.NONE, + /* isPasspointAccessPoint= */ false, + /* isOnlineSignUpForPasspointAccessPoint= */ false, + /* passpointProviderFriendlyName= */ null)); assertTrue(mWifiRepository.isWifiConnectedWithValidSsid()); mKeyguardUpdateMonitor.mServiceStates = new HashMap<>(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt index fef042be65a8..2dbeb7aa7e90 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt @@ -489,6 +489,26 @@ class WifiRepositoryImplTest : SysuiTestCase() { } @Test + fun wifiNetwork_neverHasHotspot() = + testScope.runTest { + val latest by collectLastValue(underTest.wifiNetwork) + + val wifiInfo = + mock<WifiInfo>().apply { + whenever(this.ssid).thenReturn(SSID) + whenever(this.isPrimary).thenReturn(true) + } + val network = mock<Network>().apply { whenever(this.getNetId()).thenReturn(NETWORK_ID) } + + getNetworkCallback() + .onCapabilitiesChanged(network, createWifiNetworkCapabilities(wifiInfo)) + + assertThat(latest is WifiNetworkModel.Active).isTrue() + assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType) + .isEqualTo(WifiNetworkModel.HotspotDeviceType.NONE) + } + + @Test fun wifiNetwork_isCarrierMerged_flowHasCarrierMerged() = testScope.runTest { val latest by collectLastValue(underTest.wifiNetwork) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLibTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLibTest.kt index bd20e415ab37..7a78ae368fa9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLibTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryViaTrackerLibTest.kt @@ -18,10 +18,13 @@ package com.android.systemui.statusbar.pipeline.wifi.data.repository.prod import android.net.wifi.WifiManager import android.net.wifi.WifiManager.UNKNOWN_SSID +import android.net.wifi.sharedconnectivity.app.NetworkProviderInfo import android.testing.TestableLooper import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.flags.FakeFeatureFlags +import com.android.systemui.flags.Flags import com.android.systemui.log.LogBuffer import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.statusbar.connectivity.WifiPickerTrackerFactory @@ -35,6 +38,8 @@ import com.android.systemui.util.mockito.capture import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.android.systemui.util.time.FakeSystemClock +import com.android.wifitrackerlib.HotspotNetworkEntry +import com.android.wifitrackerlib.HotspotNetworkEntry.DeviceType import com.android.wifitrackerlib.MergedCarrierEntry import com.android.wifitrackerlib.WifiEntry import com.android.wifitrackerlib.WifiPickerTracker @@ -59,10 +64,25 @@ import org.mockito.Mockito.verify @TestableLooper.RunWithLooper(setAsMainLooper = true) class WifiRepositoryViaTrackerLibTest : SysuiTestCase() { - private lateinit var underTest: WifiRepositoryViaTrackerLib + // Using lazy means that the class will only be constructed once it's fetched. Because the + // repository internally sets some values on construction, we need to set up some test + // parameters (like feature flags) *before* construction. Using lazy allows us to do that setup + // inside each test case without needing to manually recreate the repository. + private val underTest: WifiRepositoryViaTrackerLib by lazy { + WifiRepositoryViaTrackerLib( + featureFlags, + testScope.backgroundScope, + executor, + wifiPickerTrackerFactory, + wifiManager, + logger, + tableLogger, + ) + } private val executor = FakeExecutor(FakeSystemClock()) private val logger = LogBuffer("name", maxSize = 100, logcatEchoTracker = mock()) + private val featureFlags = FakeFeatureFlags() private val tableLogger = mock<TableLogBuffer>() private val wifiManager = mock<WifiManager>().apply { whenever(this.maxSignalLevel).thenReturn(10) } @@ -76,9 +96,9 @@ class WifiRepositoryViaTrackerLibTest : SysuiTestCase() { @Before fun setUp() { + featureFlags.set(Flags.INSTANT_TETHER, false) whenever(wifiPickerTrackerFactory.create(any(), capture(callbackCaptor))) .thenReturn(wifiPickerTracker) - underTest = createRepo() } @Test @@ -273,6 +293,136 @@ class WifiRepositoryViaTrackerLibTest : SysuiTestCase() { } @Test + fun wifiNetwork_notHotspot_none() = + testScope.runTest { + featureFlags.set(Flags.INSTANT_TETHER, true) + val latest by collectLastValue(underTest.wifiNetwork) + + val wifiEntry = + mock<WifiEntry>().apply { whenever(this.isPrimaryNetwork).thenReturn(true) } + whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) + getCallback().onWifiEntriesChanged() + + assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType) + .isEqualTo(WifiNetworkModel.HotspotDeviceType.NONE) + } + + @Test + fun wifiNetwork_hotspot_unknown() = + testScope.runTest { + featureFlags.set(Flags.INSTANT_TETHER, true) + val latest by collectLastValue(underTest.wifiNetwork) + + val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_UNKNOWN) + whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) + getCallback().onWifiEntriesChanged() + + assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType) + .isEqualTo(WifiNetworkModel.HotspotDeviceType.UNKNOWN) + } + + @Test + fun wifiNetwork_hotspot_phone() = + testScope.runTest { + featureFlags.set(Flags.INSTANT_TETHER, true) + val latest by collectLastValue(underTest.wifiNetwork) + + val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_PHONE) + whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) + getCallback().onWifiEntriesChanged() + + assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType) + .isEqualTo(WifiNetworkModel.HotspotDeviceType.PHONE) + } + + @Test + fun wifiNetwork_hotspot_tablet() = + testScope.runTest { + featureFlags.set(Flags.INSTANT_TETHER, true) + val latest by collectLastValue(underTest.wifiNetwork) + + val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_TABLET) + whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) + getCallback().onWifiEntriesChanged() + + assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType) + .isEqualTo(WifiNetworkModel.HotspotDeviceType.TABLET) + } + + @Test + fun wifiNetwork_hotspot_laptop() = + testScope.runTest { + featureFlags.set(Flags.INSTANT_TETHER, true) + val latest by collectLastValue(underTest.wifiNetwork) + + val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_LAPTOP) + whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) + getCallback().onWifiEntriesChanged() + + assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType) + .isEqualTo(WifiNetworkModel.HotspotDeviceType.LAPTOP) + } + + @Test + fun wifiNetwork_hotspot_watch() = + testScope.runTest { + featureFlags.set(Flags.INSTANT_TETHER, true) + val latest by collectLastValue(underTest.wifiNetwork) + + val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_WATCH) + whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) + getCallback().onWifiEntriesChanged() + + assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType) + .isEqualTo(WifiNetworkModel.HotspotDeviceType.WATCH) + } + + @Test + fun wifiNetwork_hotspot_auto() = + testScope.runTest { + featureFlags.set(Flags.INSTANT_TETHER, true) + val latest by collectLastValue(underTest.wifiNetwork) + + val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_AUTO) + whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) + getCallback().onWifiEntriesChanged() + + assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType) + .isEqualTo(WifiNetworkModel.HotspotDeviceType.AUTO) + } + + @Test + fun wifiNetwork_hotspot_invalid() = + testScope.runTest { + featureFlags.set(Flags.INSTANT_TETHER, true) + val latest by collectLastValue(underTest.wifiNetwork) + + val wifiEntry = createHotspotWithType(1234) + whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) + getCallback().onWifiEntriesChanged() + + assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType) + .isEqualTo(WifiNetworkModel.HotspotDeviceType.INVALID) + } + + @Test + fun wifiNetwork_hotspot_flagOff_valueNotUsed() = + testScope.runTest { + // WHEN the flag is off + featureFlags.set(Flags.INSTANT_TETHER, false) + + val latest by collectLastValue(underTest.wifiNetwork) + + val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_WATCH) + whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry) + getCallback().onWifiEntriesChanged() + + // THEN NONE is always used, even if the wifi entry does have a hotspot device type + assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType) + .isEqualTo(WifiNetworkModel.HotspotDeviceType.NONE) + } + + @Test fun wifiNetwork_isCarrierMerged_flowHasCarrierMerged() = testScope.runTest { val latest by collectLastValue(underTest.wifiNetwork) @@ -726,15 +876,11 @@ class WifiRepositoryViaTrackerLibTest : SysuiTestCase() { return callbackCaptor.value!! } - private fun createRepo(): WifiRepositoryViaTrackerLib { - return WifiRepositoryViaTrackerLib( - testScope.backgroundScope, - executor, - wifiPickerTrackerFactory, - wifiManager, - logger, - tableLogger, - ) + private fun createHotspotWithType(@DeviceType type: Int): HotspotNetworkEntry { + return mock<HotspotNetworkEntry>().apply { + whenever(this.isPrimaryNetwork).thenReturn(true) + whenever(this.deviceType).thenReturn(type) + } } private companion object { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModelTest.kt index 4e0c309512e8..ba035bec340c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModelTest.kt @@ -136,7 +136,8 @@ class WifiNetworkModelTest : SysuiTestCase() { networkId = 5, isValidated = true, level = 3, - ssid = "Test SSID" + ssid = "Test SSID", + hotspotDeviceType = WifiNetworkModel.HotspotDeviceType.LAPTOP, ) activeNetwork.logDiffs(prevVal = WifiNetworkModel.Inactive, logger) @@ -146,6 +147,7 @@ class WifiNetworkModelTest : SysuiTestCase() { assertThat(logger.changes).contains(Pair(COL_VALIDATED, "true")) assertThat(logger.changes).contains(Pair(COL_LEVEL, "3")) assertThat(logger.changes).contains(Pair(COL_SSID, "Test SSID")) + assertThat(logger.changes).contains(Pair(COL_HOTSPOT, "LAPTOP")) } @Test fun logDiffs_activeToInactive_resetsAllActiveFields() { @@ -165,6 +167,7 @@ class WifiNetworkModelTest : SysuiTestCase() { assertThat(logger.changes).contains(Pair(COL_VALIDATED, "false")) assertThat(logger.changes).contains(Pair(COL_LEVEL, LEVEL_DEFAULT.toString())) assertThat(logger.changes).contains(Pair(COL_SSID, "null")) + assertThat(logger.changes).contains(Pair(COL_HOTSPOT, "null")) } @Test @@ -175,7 +178,8 @@ class WifiNetworkModelTest : SysuiTestCase() { networkId = 5, isValidated = true, level = 3, - ssid = "Test SSID" + ssid = "Test SSID", + hotspotDeviceType = WifiNetworkModel.HotspotDeviceType.AUTO, ) val prevVal = WifiNetworkModel.CarrierMerged( @@ -191,6 +195,7 @@ class WifiNetworkModelTest : SysuiTestCase() { assertThat(logger.changes).contains(Pair(COL_VALIDATED, "true")) assertThat(logger.changes).contains(Pair(COL_LEVEL, "3")) assertThat(logger.changes).contains(Pair(COL_SSID, "Test SSID")) + assertThat(logger.changes).contains(Pair(COL_HOTSPOT, "AUTO")) } @Test fun logDiffs_activeToCarrierMerged_logsAllFields() { |