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
This commit is contained in:
@@ -22,11 +22,13 @@ import androidx.preference.Preference
|
|||||||
import androidx.preference.PreferenceScreen
|
import androidx.preference.PreferenceScreen
|
||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
import com.android.settings.core.BasePreferenceController
|
import com.android.settings.core.BasePreferenceController
|
||||||
|
import com.android.settingslib.Utils
|
||||||
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
|
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
|
||||||
|
|
||||||
class InternetPreferenceControllerV2(context: Context, preferenceKey: String) :
|
class InternetPreferenceControllerV2(context: Context, preferenceKey: String) :
|
||||||
BasePreferenceController(context, preferenceKey) {
|
BasePreferenceController(context, preferenceKey) {
|
||||||
|
|
||||||
|
private val repository = InternetPreferenceRepository(mContext)
|
||||||
private var preference: Preference? = null
|
private var preference: Preference? = null
|
||||||
|
|
||||||
override fun getAvailabilityStatus() =
|
override fun getAvailabilityStatus() =
|
||||||
@@ -39,9 +41,14 @@ class InternetPreferenceControllerV2(context: Context, preferenceKey: String) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
|
override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
|
||||||
InternetPreferenceRepository(mContext).summaryFlow()
|
repository.displayInfoFlow().collectLatestWithLifecycle(viewLifecycleOwner) { displayInfo ->
|
||||||
.collectLatestWithLifecycle(viewLifecycleOwner) {
|
preference?.apply {
|
||||||
preference?.summary = it
|
summary = displayInfo.summary
|
||||||
|
icon =
|
||||||
|
mContext.getDrawable(displayInfo.iconResId)?.apply {
|
||||||
|
setTintList(Utils.getColorAttr(mContext, android.R.attr.colorControlNormal))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -21,6 +21,7 @@ import android.net.NetworkCapabilities
|
|||||||
import android.net.wifi.WifiManager
|
import android.net.wifi.WifiManager
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import androidx.annotation.DrawableRes
|
||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
import com.android.settings.network.telephony.DataSubscriptionRepository
|
import com.android.settings.network.telephony.DataSubscriptionRepository
|
||||||
import com.android.settings.wifi.WifiSummaryRepository
|
import com.android.settings.wifi.WifiSummaryRepository
|
||||||
@@ -33,6 +34,7 @@ import kotlinx.coroutines.flow.combine
|
|||||||
import kotlinx.coroutines.flow.conflate
|
import kotlinx.coroutines.flow.conflate
|
||||||
import kotlinx.coroutines.flow.flatMapLatest
|
import kotlinx.coroutines.flow.flatMapLatest
|
||||||
import kotlinx.coroutines.flow.flowOn
|
import kotlinx.coroutines.flow.flowOn
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
@@ -47,42 +49,66 @@ class InternetPreferenceRepository(
|
|||||||
context.settingsGlobalBooleanFlow(Settings.Global.AIRPLANE_MODE_ON),
|
context.settingsGlobalBooleanFlow(Settings.Global.AIRPLANE_MODE_ON),
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun summaryFlow(): Flow<String> =
|
data class DisplayInfo(
|
||||||
|
val summary: String,
|
||||||
|
@DrawableRes val iconResId: Int,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun displayInfoFlow(): Flow<DisplayInfo> =
|
||||||
connectivityRepository
|
connectivityRepository
|
||||||
.networkCapabilitiesFlow()
|
.networkCapabilitiesFlow()
|
||||||
.flatMapLatest { capabilities -> capabilities.summaryFlow() }
|
.flatMapLatest { capabilities -> capabilities.displayInfoFlow() }
|
||||||
.onEach { Log.d(TAG, "summaryFlow: $it") }
|
.onEach { Log.d(TAG, "displayInfoFlow: $it") }
|
||||||
.conflate()
|
.conflate()
|
||||||
.flowOn(Dispatchers.Default)
|
.flowOn(Dispatchers.Default)
|
||||||
|
|
||||||
private fun NetworkCapabilities.summaryFlow(): Flow<String> {
|
private fun NetworkCapabilities.displayInfoFlow(): Flow<DisplayInfo> {
|
||||||
if (
|
if (
|
||||||
hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
|
hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
|
||||||
hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
|
hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
|
||||||
) {
|
) {
|
||||||
for (transportType in transportTypes) {
|
for (transportType in transportTypes) {
|
||||||
when (transportType) {
|
when (transportType) {
|
||||||
NetworkCapabilities.TRANSPORT_WIFI -> return wifiSummaryRepository.summaryFlow()
|
NetworkCapabilities.TRANSPORT_WIFI -> return wifiDisplayInfoFlow()
|
||||||
NetworkCapabilities.TRANSPORT_CELLULAR ->
|
NetworkCapabilities.TRANSPORT_CELLULAR -> return cellularDisplayInfoFlow()
|
||||||
return dataSubscriptionRepository.dataSummaryFlow()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return defaultSummaryFlow()
|
return defaultDisplayInfoFlow()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun defaultSummaryFlow(): Flow<String> =
|
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<DisplayInfo> =
|
||||||
combine(
|
combine(
|
||||||
airplaneModeOnFlow,
|
airplaneModeOnFlow,
|
||||||
wifiRepository.wifiStateFlow(),
|
wifiRepository.wifiStateFlow(),
|
||||||
) { airplaneModeOn: Boolean, wifiState: Int ->
|
) { airplaneModeOn: Boolean, wifiState: Int ->
|
||||||
context.getString(
|
if (airplaneModeOn && wifiState != WifiManager.WIFI_STATE_ENABLED) {
|
||||||
if (airplaneModeOn && wifiState != WifiManager.WIFI_STATE_ENABLED) {
|
DisplayInfo(
|
||||||
R.string.condition_airplane_title
|
summary = context.getString(R.string.condition_airplane_title),
|
||||||
} else {
|
iconResId = R.drawable.ic_no_internet_unavailable,
|
||||||
R.string.networks_available
|
)
|
||||||
}
|
} else {
|
||||||
)
|
DisplayInfo(
|
||||||
|
summary = context.getString(R.string.networks_available),
|
||||||
|
iconResId = R.drawable.ic_no_internet_available,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
|
@@ -58,7 +58,7 @@ class InternetPreferenceRepositoryTest {
|
|||||||
)
|
)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun summaryFlow_wifi() = runBlocking {
|
fun displayInfoFlow_wifi() = runBlocking {
|
||||||
val wifiNetworkCapabilities =
|
val wifiNetworkCapabilities =
|
||||||
NetworkCapabilities.Builder()
|
NetworkCapabilities.Builder()
|
||||||
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
|
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
|
||||||
@@ -70,13 +70,19 @@ class InternetPreferenceRepositoryTest {
|
|||||||
}
|
}
|
||||||
mockWifiSummaryRepository.stub { on { summaryFlow() } doReturn flowOf(SUMMARY) }
|
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
|
@Test
|
||||||
fun summaryFlow_cellular() = runBlocking {
|
fun displayInfoFlow_cellular() = runBlocking {
|
||||||
val wifiNetworkCapabilities =
|
val wifiNetworkCapabilities =
|
||||||
NetworkCapabilities.Builder()
|
NetworkCapabilities.Builder()
|
||||||
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
|
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
|
||||||
@@ -88,13 +94,19 @@ class InternetPreferenceRepositoryTest {
|
|||||||
}
|
}
|
||||||
mockDataSubscriptionRepository.stub { on { dataSummaryFlow() } doReturn flowOf(SUMMARY) }
|
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
|
@Test
|
||||||
fun summaryFlow_airplaneModeOnAndWifiOn() = runBlocking {
|
fun displayInfoFlow_airplaneModeOnAndWifiOn() = runBlocking {
|
||||||
mockConnectivityRepository.stub {
|
mockConnectivityRepository.stub {
|
||||||
on { networkCapabilitiesFlow() } doReturn flowOf(NetworkCapabilities())
|
on { networkCapabilitiesFlow() } doReturn flowOf(NetworkCapabilities())
|
||||||
}
|
}
|
||||||
@@ -103,13 +115,19 @@ class InternetPreferenceRepositoryTest {
|
|||||||
on { wifiStateFlow() } doReturn flowOf(WifiManager.WIFI_STATE_ENABLED)
|
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
|
@Test
|
||||||
fun summaryFlow_airplaneModeOnAndWifiOff() = runBlocking {
|
fun displayInfoFlow_airplaneModeOnAndWifiOff() = runBlocking {
|
||||||
mockConnectivityRepository.stub {
|
mockConnectivityRepository.stub {
|
||||||
on { networkCapabilitiesFlow() } doReturn flowOf(NetworkCapabilities())
|
on { networkCapabilitiesFlow() } doReturn flowOf(NetworkCapabilities())
|
||||||
}
|
}
|
||||||
@@ -118,13 +136,19 @@ class InternetPreferenceRepositoryTest {
|
|||||||
on { wifiStateFlow() } doReturn flowOf(WifiManager.WIFI_STATE_DISABLED)
|
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
|
@Test
|
||||||
fun summaryFlow_airplaneModeOff() = runBlocking {
|
fun displayInfoFlow_airplaneModeOff() = runBlocking {
|
||||||
mockConnectivityRepository.stub {
|
mockConnectivityRepository.stub {
|
||||||
on { networkCapabilitiesFlow() } doReturn flowOf(NetworkCapabilities())
|
on { networkCapabilitiesFlow() } doReturn flowOf(NetworkCapabilities())
|
||||||
}
|
}
|
||||||
@@ -133,9 +157,15 @@ class InternetPreferenceRepositoryTest {
|
|||||||
on { wifiStateFlow() } doReturn flowOf(WifiManager.WIFI_STATE_DISABLED)
|
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 {
|
private companion object {
|
||||||
|
Reference in New Issue
Block a user