From 0d758dfdb9f3f2a9c2f49a7723b9224e44471a51 Mon Sep 17 00:00:00 2001 From: Chaohui Wang Date: Wed, 12 Jun 2024 17:48:38 +0800 Subject: [PATCH] InternetPreferenceController V2 (4/n) Display different icon for different condition. Bug: 339884322 Flag: com.android.settings.flags.internet_preference_controller_v2 Test: manual - on Internet Test: unit test Change-Id: Ic06b0e349a284f8b4466bd0c19f318a6a0936a6e --- .../network/InternetPreferenceControllerV2.kt | 13 +++- .../network/InternetPreferenceRepository.kt | 58 +++++++++++++----- .../InternetPreferenceRepositoryTest.kt | 60 ++++++++++++++----- 3 files changed, 97 insertions(+), 34 deletions(-) diff --git a/src/com/android/settings/network/InternetPreferenceControllerV2.kt b/src/com/android/settings/network/InternetPreferenceControllerV2.kt index 351aca83526..a181abd2ef0 100644 --- a/src/com/android/settings/network/InternetPreferenceControllerV2.kt +++ b/src/com/android/settings/network/InternetPreferenceControllerV2.kt @@ -22,11 +22,13 @@ import androidx.preference.Preference import androidx.preference.PreferenceScreen import com.android.settings.R import com.android.settings.core.BasePreferenceController +import com.android.settingslib.Utils import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle class InternetPreferenceControllerV2(context: Context, preferenceKey: String) : BasePreferenceController(context, preferenceKey) { + private val repository = InternetPreferenceRepository(mContext) private var preference: Preference? = null override fun getAvailabilityStatus() = @@ -39,9 +41,14 @@ class InternetPreferenceControllerV2(context: Context, preferenceKey: String) : } override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) { - InternetPreferenceRepository(mContext).summaryFlow() - .collectLatestWithLifecycle(viewLifecycleOwner) { - preference?.summary = it + repository.displayInfoFlow().collectLatestWithLifecycle(viewLifecycleOwner) { displayInfo -> + preference?.apply { + summary = displayInfo.summary + icon = + mContext.getDrawable(displayInfo.iconResId)?.apply { + setTintList(Utils.getColorAttr(mContext, android.R.attr.colorControlNormal)) + } } + } } } diff --git a/src/com/android/settings/network/InternetPreferenceRepository.kt b/src/com/android/settings/network/InternetPreferenceRepository.kt index 6aa8db2c308..30b2f6a638e 100644 --- a/src/com/android/settings/network/InternetPreferenceRepository.kt +++ b/src/com/android/settings/network/InternetPreferenceRepository.kt @@ -21,6 +21,7 @@ import android.net.NetworkCapabilities import android.net.wifi.WifiManager import android.provider.Settings import android.util.Log +import androidx.annotation.DrawableRes import com.android.settings.R import com.android.settings.network.telephony.DataSubscriptionRepository import com.android.settings.wifi.WifiSummaryRepository @@ -33,6 +34,7 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.conflate import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach @OptIn(ExperimentalCoroutinesApi::class) @@ -47,42 +49,66 @@ class InternetPreferenceRepository( context.settingsGlobalBooleanFlow(Settings.Global.AIRPLANE_MODE_ON), ) { - fun summaryFlow(): Flow = + data class DisplayInfo( + val summary: String, + @DrawableRes val iconResId: Int, + ) + + fun displayInfoFlow(): Flow = connectivityRepository .networkCapabilitiesFlow() - .flatMapLatest { capabilities -> capabilities.summaryFlow() } - .onEach { Log.d(TAG, "summaryFlow: $it") } + .flatMapLatest { capabilities -> capabilities.displayInfoFlow() } + .onEach { Log.d(TAG, "displayInfoFlow: $it") } .conflate() .flowOn(Dispatchers.Default) - private fun NetworkCapabilities.summaryFlow(): Flow { + private fun NetworkCapabilities.displayInfoFlow(): Flow { if ( hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) ) { for (transportType in transportTypes) { when (transportType) { - NetworkCapabilities.TRANSPORT_WIFI -> return wifiSummaryRepository.summaryFlow() - NetworkCapabilities.TRANSPORT_CELLULAR -> - return dataSubscriptionRepository.dataSummaryFlow() + NetworkCapabilities.TRANSPORT_WIFI -> return wifiDisplayInfoFlow() + NetworkCapabilities.TRANSPORT_CELLULAR -> return cellularDisplayInfoFlow() } } } - return defaultSummaryFlow() + return defaultDisplayInfoFlow() } - private fun defaultSummaryFlow(): Flow = + private fun wifiDisplayInfoFlow() = + wifiSummaryRepository.summaryFlow().map { summary -> + DisplayInfo( + summary = summary, + iconResId = R.drawable.ic_wifi_signal_4, + ) + } + + private fun cellularDisplayInfoFlow() = + dataSubscriptionRepository.dataSummaryFlow().map { summary -> + DisplayInfo( + summary = summary, + iconResId = R.drawable.ic_network_cell, + ) + } + + private fun defaultDisplayInfoFlow(): Flow = combine( airplaneModeOnFlow, wifiRepository.wifiStateFlow(), ) { airplaneModeOn: Boolean, wifiState: Int -> - context.getString( - if (airplaneModeOn && wifiState != WifiManager.WIFI_STATE_ENABLED) { - R.string.condition_airplane_title - } else { - R.string.networks_available - } - ) + if (airplaneModeOn && wifiState != WifiManager.WIFI_STATE_ENABLED) { + DisplayInfo( + summary = context.getString(R.string.condition_airplane_title), + iconResId = R.drawable.ic_no_internet_unavailable, + ) + } else { + DisplayInfo( + summary = context.getString(R.string.networks_available), + iconResId = R.drawable.ic_no_internet_available, + ) + } } private companion object { diff --git a/tests/spa_unit/src/com/android/settings/network/InternetPreferenceRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/network/InternetPreferenceRepositoryTest.kt index aafd77f1a4a..58caea75a75 100644 --- a/tests/spa_unit/src/com/android/settings/network/InternetPreferenceRepositoryTest.kt +++ b/tests/spa_unit/src/com/android/settings/network/InternetPreferenceRepositoryTest.kt @@ -58,7 +58,7 @@ class InternetPreferenceRepositoryTest { ) @Test - fun summaryFlow_wifi() = runBlocking { + fun displayInfoFlow_wifi() = runBlocking { val wifiNetworkCapabilities = NetworkCapabilities.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) @@ -70,13 +70,19 @@ class InternetPreferenceRepositoryTest { } mockWifiSummaryRepository.stub { on { summaryFlow() } doReturn flowOf(SUMMARY) } - val summary = repository.summaryFlow().firstWithTimeoutOrNull() + val displayInfo = repository.displayInfoFlow().firstWithTimeoutOrNull() - assertThat(summary).isEqualTo(SUMMARY) + assertThat(displayInfo) + .isEqualTo( + InternetPreferenceRepository.DisplayInfo( + summary = SUMMARY, + iconResId = R.drawable.ic_wifi_signal_4, + ) + ) } @Test - fun summaryFlow_cellular() = runBlocking { + fun displayInfoFlow_cellular() = runBlocking { val wifiNetworkCapabilities = NetworkCapabilities.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) @@ -88,13 +94,19 @@ class InternetPreferenceRepositoryTest { } mockDataSubscriptionRepository.stub { on { dataSummaryFlow() } doReturn flowOf(SUMMARY) } - val summary = repository.summaryFlow().firstWithTimeoutOrNull() + val displayInfo = repository.displayInfoFlow().firstWithTimeoutOrNull() - assertThat(summary).isEqualTo(SUMMARY) + assertThat(displayInfo) + .isEqualTo( + InternetPreferenceRepository.DisplayInfo( + summary = SUMMARY, + iconResId = R.drawable.ic_network_cell, + ) + ) } @Test - fun summaryFlow_airplaneModeOnAndWifiOn() = runBlocking { + fun displayInfoFlow_airplaneModeOnAndWifiOn() = runBlocking { mockConnectivityRepository.stub { on { networkCapabilitiesFlow() } doReturn flowOf(NetworkCapabilities()) } @@ -103,13 +115,19 @@ class InternetPreferenceRepositoryTest { on { wifiStateFlow() } doReturn flowOf(WifiManager.WIFI_STATE_ENABLED) } - val summary = repository.summaryFlow().firstWithTimeoutOrNull() + val displayInfo = repository.displayInfoFlow().firstWithTimeoutOrNull() - assertThat(summary).isEqualTo(context.getString(R.string.networks_available)) + assertThat(displayInfo) + .isEqualTo( + InternetPreferenceRepository.DisplayInfo( + summary = context.getString(R.string.networks_available), + iconResId = R.drawable.ic_no_internet_available, + ) + ) } @Test - fun summaryFlow_airplaneModeOnAndWifiOff() = runBlocking { + fun displayInfoFlow_airplaneModeOnAndWifiOff() = runBlocking { mockConnectivityRepository.stub { on { networkCapabilitiesFlow() } doReturn flowOf(NetworkCapabilities()) } @@ -118,13 +136,19 @@ class InternetPreferenceRepositoryTest { on { wifiStateFlow() } doReturn flowOf(WifiManager.WIFI_STATE_DISABLED) } - val summary = repository.summaryFlow().firstWithTimeoutOrNull() + val displayInfo = repository.displayInfoFlow().firstWithTimeoutOrNull() - assertThat(summary).isEqualTo(context.getString(R.string.condition_airplane_title)) + assertThat(displayInfo) + .isEqualTo( + InternetPreferenceRepository.DisplayInfo( + summary = context.getString(R.string.condition_airplane_title), + iconResId = R.drawable.ic_no_internet_unavailable, + ) + ) } @Test - fun summaryFlow_airplaneModeOff() = runBlocking { + fun displayInfoFlow_airplaneModeOff() = runBlocking { mockConnectivityRepository.stub { on { networkCapabilitiesFlow() } doReturn flowOf(NetworkCapabilities()) } @@ -133,9 +157,15 @@ class InternetPreferenceRepositoryTest { on { wifiStateFlow() } doReturn flowOf(WifiManager.WIFI_STATE_DISABLED) } - val summary = repository.summaryFlow().firstWithTimeoutOrNull() + val displayInfo = repository.displayInfoFlow().firstWithTimeoutOrNull() - assertThat(summary).isEqualTo(context.getString(R.string.networks_available)) + assertThat(displayInfo) + .isEqualTo( + InternetPreferenceRepository.DisplayInfo( + summary = context.getString(R.string.networks_available), + iconResId = R.drawable.ic_no_internet_available, + ) + ) } private companion object {