New MobileDataEnabledFlow
To easily collect the mobile data enabled setting changes. Bug: 308903704 Test: manual - on DataUsageList Test: unit tests Change-Id: I31327f59ac32c1a621e2853e64bd30d7d17e079c
This commit is contained in:
@@ -31,9 +31,10 @@ import androidx.preference.Preference
|
|||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
import com.android.settings.datausage.lib.BillingCycleRepository
|
import com.android.settings.datausage.lib.BillingCycleRepository
|
||||||
import com.android.settings.datausage.lib.NetworkUsageData
|
import com.android.settings.datausage.lib.NetworkUsageData
|
||||||
import com.android.settings.network.MobileDataEnabledListener
|
|
||||||
import com.android.settings.network.MobileNetworkRepository
|
import com.android.settings.network.MobileNetworkRepository
|
||||||
|
import com.android.settings.network.mobileDataEnabledFlow
|
||||||
import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity
|
import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity
|
||||||
|
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
|
||||||
import com.android.settingslib.spaprivileged.framework.common.userManager
|
import com.android.settingslib.spaprivileged.framework.common.userManager
|
||||||
import com.android.settingslib.utils.ThreadUtils
|
import com.android.settingslib.utils.ThreadUtils
|
||||||
import kotlin.jvm.optionals.getOrNull
|
import kotlin.jvm.optionals.getOrNull
|
||||||
@@ -43,10 +44,7 @@ import kotlin.jvm.optionals.getOrNull
|
|||||||
* to inspect based on usage cycle and control through [NetworkPolicy].
|
* to inspect based on usage cycle and control through [NetworkPolicy].
|
||||||
*/
|
*/
|
||||||
@OpenForTesting
|
@OpenForTesting
|
||||||
open class DataUsageList : DataUsageBaseFragment(), MobileDataEnabledListener.Client {
|
open class DataUsageList : DataUsageBaseFragment() {
|
||||||
@VisibleForTesting
|
|
||||||
lateinit var dataStateListener: MobileDataEnabledListener
|
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
var template: NetworkTemplate? = null
|
var template: NetworkTemplate? = null
|
||||||
@@ -89,7 +87,6 @@ open class DataUsageList : DataUsageBaseFragment(), MobileDataEnabledListener.Cl
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
updateSubscriptionInfoEntity()
|
updateSubscriptionInfoEntity()
|
||||||
dataStateListener = MobileDataEnabledListener(activity, this)
|
|
||||||
dataUsageListAppsController = use(DataUsageListAppsController::class.java).apply {
|
dataUsageListAppsController = use(DataUsageListAppsController::class.java).apply {
|
||||||
init(template)
|
init(template)
|
||||||
}
|
}
|
||||||
@@ -103,6 +100,9 @@ open class DataUsageList : DataUsageBaseFragment(), MobileDataEnabledListener.Cl
|
|||||||
override fun onViewCreated(v: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(v: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(v, savedInstanceState)
|
super.onViewCreated(v, savedInstanceState)
|
||||||
|
|
||||||
|
requireContext().mobileDataEnabledFlow(subId)
|
||||||
|
.collectLatestWithLifecycle(viewLifecycleOwner) { updatePolicy() }
|
||||||
|
|
||||||
val template = template ?: return
|
val template = template ?: return
|
||||||
dataUsageListHeaderController = DataUsageListHeaderController(
|
dataUsageListHeaderController = DataUsageListHeaderController(
|
||||||
setPinnedHeaderView(R.layout.apps_filter_spinner),
|
setPinnedHeaderView(R.layout.apps_filter_spinner),
|
||||||
@@ -114,17 +114,6 @@ open class DataUsageList : DataUsageBaseFragment(), MobileDataEnabledListener.Cl
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
dataStateListener.start(subId)
|
|
||||||
updatePolicy()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPause() {
|
|
||||||
super.onPause()
|
|
||||||
dataStateListener.stop()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getPreferenceScreenResId() = R.xml.data_usage_list
|
override fun getPreferenceScreenResId() = R.xml.data_usage_list
|
||||||
|
|
||||||
override fun getLogTag() = TAG
|
override fun getLogTag() = TAG
|
||||||
@@ -154,13 +143,6 @@ open class DataUsageList : DataUsageBaseFragment(), MobileDataEnabledListener.Cl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of `MobileDataEnabledListener.Client`
|
|
||||||
*/
|
|
||||||
override fun onMobileDataEnabledChange() {
|
|
||||||
updatePolicy()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Update chart sweeps and cycle list to reflect [NetworkPolicy] for current [template]. */
|
/** Update chart sweeps and cycle list to reflect [NetworkPolicy] for current [template]. */
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
fun updatePolicy() {
|
fun updatePolicy() {
|
||||||
|
43
src/com/android/settings/network/MobileDataEnabledFlow.kt
Normal file
43
src/com/android/settings/network/MobileDataEnabledFlow.kt
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.network
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.provider.Settings
|
||||||
|
import android.telephony.SubscriptionManager
|
||||||
|
import com.android.settingslib.spaprivileged.settingsprovider.settingsGlobalChangeFlow
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.merge
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flow for mobile data enabled changed event.
|
||||||
|
*
|
||||||
|
* Note: This flow can only notify enabled status changes, cannot provide the latest status.
|
||||||
|
*/
|
||||||
|
fun Context.mobileDataEnabledFlow(subId: Int): Flow<Unit> {
|
||||||
|
val flow = settingsGlobalChangeFlow(Settings.Global.MOBILE_DATA)
|
||||||
|
return when (subId) {
|
||||||
|
SubscriptionManager.INVALID_SUBSCRIPTION_ID -> flow
|
||||||
|
else -> {
|
||||||
|
val subIdFlow = settingsGlobalChangeFlow(
|
||||||
|
name = Settings.Global.MOBILE_DATA + subId,
|
||||||
|
sendInitialValue = false,
|
||||||
|
)
|
||||||
|
merge(flow, subIdFlow)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -20,7 +20,12 @@ import android.content.Context;
|
|||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.telephony.SubscriptionManager;
|
import android.telephony.SubscriptionManager;
|
||||||
|
|
||||||
/** Helper class to listen for changes in the enabled state of mobile data. */
|
/**
|
||||||
|
* Helper class to listen for changes in the enabled state of mobile data.
|
||||||
|
*
|
||||||
|
* @deprecated use {@link MobileDataEnabledFlowKt} instead
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public class MobileDataEnabledListener {
|
public class MobileDataEnabledListener {
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private Client mClient;
|
private Client mClient;
|
||||||
|
@@ -28,15 +28,16 @@ import com.android.settings.SettingsPreferenceFragment
|
|||||||
import com.android.settings.dashboard.DashboardFragment
|
import com.android.settings.dashboard.DashboardFragment
|
||||||
import com.android.settings.network.telephony.MobileNetworkUtils
|
import com.android.settings.network.telephony.MobileNetworkUtils
|
||||||
import com.android.settings.search.BaseSearchIndexProvider
|
import com.android.settings.search.BaseSearchIndexProvider
|
||||||
import com.android.settings.utils.observeSettingsGlobalBoolean
|
|
||||||
import com.android.settingslib.search.SearchIndexable
|
import com.android.settingslib.search.SearchIndexable
|
||||||
|
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
|
||||||
import com.android.settingslib.spaprivileged.framework.common.userManager
|
import com.android.settingslib.spaprivileged.framework.common.userManager
|
||||||
|
import com.android.settingslib.spaprivileged.settingsprovider.settingsGlobalBooleanFlow
|
||||||
|
|
||||||
@SearchIndexable(forTarget = SearchIndexable.ALL and SearchIndexable.ARC.inv())
|
@SearchIndexable(forTarget = SearchIndexable.ALL and SearchIndexable.ARC.inv())
|
||||||
class MobileNetworkListFragment : DashboardFragment() {
|
class MobileNetworkListFragment : DashboardFragment() {
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
observeAirplaneModeAndFinishIfOn()
|
collectAirplaneModeAndFinishIfOn()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
@@ -59,15 +60,13 @@ class MobileNetworkListFragment : DashboardFragment() {
|
|||||||
private const val KEY_ADD_SIM = "add_sim"
|
private const val KEY_ADD_SIM = "add_sim"
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun SettingsPreferenceFragment.observeAirplaneModeAndFinishIfOn() {
|
fun SettingsPreferenceFragment.collectAirplaneModeAndFinishIfOn() {
|
||||||
requireContext().observeSettingsGlobalBoolean(
|
requireContext().settingsGlobalBooleanFlow(Settings.Global.AIRPLANE_MODE_ON)
|
||||||
name = Settings.Global.AIRPLANE_MODE_ON,
|
.collectLatestWithLifecycle(viewLifecycleOwner) { isAirplaneModeOn ->
|
||||||
lifecycle = viewLifecycleOwner.lifecycle,
|
if (isAirplaneModeOn) {
|
||||||
) { isAirplaneModeOn: Boolean ->
|
finish()
|
||||||
if (isAirplaneModeOn) {
|
}
|
||||||
finish()
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
|
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
package com.android.settings.network.telephony;
|
package com.android.settings.network.telephony;
|
||||||
|
|
||||||
import static com.android.settings.network.MobileNetworkListFragment.observeAirplaneModeAndFinishIfOn;
|
import static com.android.settings.network.MobileNetworkListFragment.collectAirplaneModeAndFinishIfOn;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.settings.SettingsEnums;
|
import android.app.settings.SettingsEnums;
|
||||||
@@ -334,7 +334,7 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme
|
|||||||
@Override
|
@Override
|
||||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
observeAirplaneModeAndFinishIfOn(this);
|
collectAirplaneModeAndFinishIfOn(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2023 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.android.settings.utils
|
|
||||||
|
|
||||||
import android.content.ContentResolver
|
|
||||||
import android.content.Context
|
|
||||||
import android.database.ContentObserver
|
|
||||||
import android.os.Handler
|
|
||||||
import android.provider.Settings
|
|
||||||
import androidx.lifecycle.DefaultLifecycleObserver
|
|
||||||
import androidx.lifecycle.Lifecycle
|
|
||||||
import androidx.lifecycle.LifecycleOwner
|
|
||||||
import kotlin.properties.ReadWriteProperty
|
|
||||||
import kotlin.reflect.KProperty
|
|
||||||
|
|
||||||
fun Context.observeSettingsGlobalBoolean(
|
|
||||||
name: String,
|
|
||||||
lifecycle: Lifecycle,
|
|
||||||
onChange: (newValue: Boolean) -> Unit,
|
|
||||||
) {
|
|
||||||
val field by settingsGlobalBoolean(name)
|
|
||||||
val contentObserver = object : ContentObserver(Handler.getMain()) {
|
|
||||||
override fun onChange(selfChange: Boolean) {
|
|
||||||
onChange(field)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val uri = Settings.Global.getUriFor(name)
|
|
||||||
lifecycle.addObserver(object : DefaultLifecycleObserver {
|
|
||||||
override fun onStart(owner: LifecycleOwner) {
|
|
||||||
contentResolver.registerContentObserver(uri, false, contentObserver)
|
|
||||||
onChange(field)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStop(owner: LifecycleOwner) {
|
|
||||||
contentResolver.unregisterContentObserver(contentObserver)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Context.settingsGlobalBoolean(name: String): ReadWriteProperty<Any?, Boolean> =
|
|
||||||
SettingsGlobalBooleanDelegate(this, name)
|
|
||||||
|
|
||||||
private class SettingsGlobalBooleanDelegate(context: Context, private val name: String) :
|
|
||||||
ReadWriteProperty<Any?, Boolean> {
|
|
||||||
|
|
||||||
private val contentResolver: ContentResolver = context.contentResolver
|
|
||||||
|
|
||||||
override fun getValue(thisRef: Any?, property: KProperty<*>): Boolean =
|
|
||||||
Settings.Global.getInt(contentResolver, name, 0) != 0
|
|
||||||
|
|
||||||
override fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean) {
|
|
||||||
Settings.Global.putInt(contentResolver, name, if (value) 1 else 0)
|
|
||||||
}
|
|
||||||
}
|
|
@@ -23,22 +23,18 @@ import android.os.Bundle
|
|||||||
import android.os.UserManager
|
import android.os.UserManager
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import androidx.preference.PreferenceManager
|
|
||||||
import androidx.test.core.app.ApplicationProvider
|
import androidx.test.core.app.ApplicationProvider
|
||||||
import com.android.settings.datausage.DataUsageListTest.ShadowDataUsageBaseFragment
|
import com.android.settings.datausage.DataUsageListTest.ShadowDataUsageBaseFragment
|
||||||
import com.android.settings.datausage.TemplatePreference.NetworkServices
|
import com.android.settings.datausage.TemplatePreference.NetworkServices
|
||||||
import com.android.settings.datausage.lib.BillingCycleRepository
|
import com.android.settings.datausage.lib.BillingCycleRepository
|
||||||
import com.android.settings.network.MobileDataEnabledListener
|
|
||||||
import com.android.settings.testutils.FakeFeatureFactory
|
import com.android.settings.testutils.FakeFeatureFactory
|
||||||
import com.android.settingslib.NetworkPolicyEditor
|
import com.android.settingslib.NetworkPolicyEditor
|
||||||
import com.android.settingslib.core.AbstractPreferenceController
|
import com.android.settingslib.core.AbstractPreferenceController
|
||||||
import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.mockito.ArgumentMatchers
|
|
||||||
import org.mockito.Mock
|
import org.mockito.Mock
|
||||||
import org.mockito.Mockito.doNothing
|
import org.mockito.Mockito.doNothing
|
||||||
import org.mockito.Mockito.doReturn
|
import org.mockito.Mockito.doReturn
|
||||||
@@ -61,9 +57,6 @@ class DataUsageListTest {
|
|||||||
@get:Rule
|
@get:Rule
|
||||||
val mockito: MockitoRule = MockitoJUnit.rule()
|
val mockito: MockitoRule = MockitoJUnit.rule()
|
||||||
|
|
||||||
@Mock
|
|
||||||
private lateinit var mobileDataEnabledListener: MobileDataEnabledListener
|
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var networkServices: NetworkServices
|
private lateinit var networkServices: NetworkServices
|
||||||
|
|
||||||
@@ -86,7 +79,6 @@ class DataUsageListTest {
|
|||||||
fun setUp() {
|
fun setUp() {
|
||||||
FakeFeatureFactory.setupForTest()
|
FakeFeatureFactory.setupForTest()
|
||||||
networkServices.mPolicyEditor = mock(NetworkPolicyEditor::class.java)
|
networkServices.mPolicyEditor = mock(NetworkPolicyEditor::class.java)
|
||||||
dataUsageList.dataStateListener = mobileDataEnabledListener
|
|
||||||
doReturn(context).`when`(dataUsageList).context
|
doReturn(context).`when`(dataUsageList).context
|
||||||
doReturn(userManager).`when`(context).getSystemService(UserManager::class.java)
|
doReturn(userManager).`when`(context).getSystemService(UserManager::class.java)
|
||||||
doReturn(false).`when`(userManager).isGuestUser
|
doReturn(false).`when`(userManager).isGuestUser
|
||||||
@@ -112,46 +104,6 @@ class DataUsageListTest {
|
|||||||
verify(dataUsageList).finish()
|
verify(dataUsageList).finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun resume_shouldListenDataStateChange() {
|
|
||||||
dataUsageList.template = mock(NetworkTemplate::class.java)
|
|
||||||
dataUsageList.onCreate(null)
|
|
||||||
dataUsageList.dataStateListener = mobileDataEnabledListener
|
|
||||||
ReflectionHelpers.setField(
|
|
||||||
dataUsageList,
|
|
||||||
"mVisibilityLoggerMixin",
|
|
||||||
mock(VisibilityLoggerMixin::class.java),
|
|
||||||
)
|
|
||||||
ReflectionHelpers.setField(
|
|
||||||
dataUsageList,
|
|
||||||
"mPreferenceManager",
|
|
||||||
mock(PreferenceManager::class.java),
|
|
||||||
)
|
|
||||||
dataUsageList.onResume()
|
|
||||||
verify(mobileDataEnabledListener).start(ArgumentMatchers.anyInt())
|
|
||||||
dataUsageList.onPause()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun pause_shouldUnlistenDataStateChange() {
|
|
||||||
dataUsageList.template = mock(NetworkTemplate::class.java)
|
|
||||||
dataUsageList.onCreate(null)
|
|
||||||
dataUsageList.dataStateListener = mobileDataEnabledListener
|
|
||||||
ReflectionHelpers.setField(
|
|
||||||
dataUsageList, "mVisibilityLoggerMixin", mock(
|
|
||||||
VisibilityLoggerMixin::class.java
|
|
||||||
)
|
|
||||||
)
|
|
||||||
ReflectionHelpers.setField(
|
|
||||||
dataUsageList, "mPreferenceManager", mock(
|
|
||||||
PreferenceManager::class.java
|
|
||||||
)
|
|
||||||
)
|
|
||||||
dataUsageList.onResume()
|
|
||||||
dataUsageList.onPause()
|
|
||||||
verify(mobileDataEnabledListener).stop()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun processArgument_shouldGetTemplateFromArgument() {
|
fun processArgument_shouldGetTemplateFromArgument() {
|
||||||
val args = Bundle()
|
val args = Bundle()
|
||||||
|
@@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.network
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.provider.Settings
|
||||||
|
import android.telephony.SubscriptionManager
|
||||||
|
import androidx.test.core.app.ApplicationProvider
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import com.android.settingslib.spa.testutils.firstWithTimeoutOrNull
|
||||||
|
import com.android.settingslib.spa.testutils.toListWithTimeout
|
||||||
|
import com.android.settingslib.spaprivileged.settingsprovider.settingsGlobalBoolean
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import kotlinx.coroutines.async
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class MobileDataEnabledFlowTest {
|
||||||
|
private val context: Context = ApplicationProvider.getApplicationContext()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun mobileDataEnabledFlow_notified(): Unit = runBlocking {
|
||||||
|
val flow = context.mobileDataEnabledFlow(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
|
||||||
|
|
||||||
|
assertThat(flow.firstWithTimeoutOrNull()).isNotNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun mobileDataEnabledFlow_changed_notified(): Unit = runBlocking {
|
||||||
|
var mobileDataEnabled by context.settingsGlobalBoolean(Settings.Global.MOBILE_DATA)
|
||||||
|
mobileDataEnabled = false
|
||||||
|
|
||||||
|
val flow = context.mobileDataEnabledFlow(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
|
||||||
|
mobileDataEnabled = true
|
||||||
|
|
||||||
|
assertThat(flow.firstWithTimeoutOrNull()).isNotNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun mobileDataEnabledFlow_forSubIdNotChanged(): Unit = runBlocking {
|
||||||
|
var mobileDataEnabled by context.settingsGlobalBoolean(Settings.Global.MOBILE_DATA)
|
||||||
|
mobileDataEnabled = false
|
||||||
|
var mobileDataEnabledForSubId
|
||||||
|
by context.settingsGlobalBoolean(Settings.Global.MOBILE_DATA + SUB_ID)
|
||||||
|
mobileDataEnabledForSubId = false
|
||||||
|
|
||||||
|
val listDeferred = async {
|
||||||
|
context.mobileDataEnabledFlow(SUB_ID).toListWithTimeout()
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(listDeferred.await()).hasSize(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun mobileDataEnabledFlow_forSubIdChanged(): Unit = runBlocking {
|
||||||
|
var mobileDataEnabled by context.settingsGlobalBoolean(Settings.Global.MOBILE_DATA)
|
||||||
|
mobileDataEnabled = false
|
||||||
|
var mobileDataEnabledForSubId
|
||||||
|
by context.settingsGlobalBoolean(Settings.Global.MOBILE_DATA + SUB_ID)
|
||||||
|
mobileDataEnabledForSubId = false
|
||||||
|
|
||||||
|
val listDeferred = async {
|
||||||
|
context.mobileDataEnabledFlow(SUB_ID).toListWithTimeout()
|
||||||
|
}
|
||||||
|
delay(100)
|
||||||
|
mobileDataEnabledForSubId = true
|
||||||
|
|
||||||
|
assertThat(listDeferred.await()).hasSize(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
const val SUB_ID = 123
|
||||||
|
}
|
||||||
|
}
|
@@ -1,99 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2023 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.android.settings.utils
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.provider.Settings
|
|
||||||
import androidx.lifecycle.testing.TestLifecycleOwner
|
|
||||||
import androidx.test.core.app.ApplicationProvider
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
|
||||||
class SettingsGlobalBooleanDelegateTest {
|
|
||||||
|
|
||||||
private val context: Context = ApplicationProvider.getApplicationContext()
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun getValue_setTrue_returnTrue() {
|
|
||||||
Settings.Global.putInt(context.contentResolver, TEST_NAME, 1)
|
|
||||||
|
|
||||||
val value by context.settingsGlobalBoolean(TEST_NAME)
|
|
||||||
|
|
||||||
assertThat(value).isTrue()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun getValue_setFalse_returnFalse() {
|
|
||||||
Settings.Global.putInt(context.contentResolver, TEST_NAME, 0)
|
|
||||||
|
|
||||||
val value by context.settingsGlobalBoolean(TEST_NAME)
|
|
||||||
|
|
||||||
assertThat(value).isFalse()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun setValue_setTrue_returnTrue() {
|
|
||||||
var value by context.settingsGlobalBoolean(TEST_NAME)
|
|
||||||
|
|
||||||
value = true
|
|
||||||
|
|
||||||
assertThat(Settings.Global.getInt(context.contentResolver, TEST_NAME, 0)).isEqualTo(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun setValue_setFalse_returnFalse() {
|
|
||||||
var value by context.settingsGlobalBoolean(TEST_NAME)
|
|
||||||
|
|
||||||
value = false
|
|
||||||
|
|
||||||
assertThat(Settings.Global.getInt(context.contentResolver, TEST_NAME, 1)).isEqualTo(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun observeSettingsGlobalBoolean_valueNotChanged() {
|
|
||||||
var value by context.settingsGlobalBoolean(TEST_NAME)
|
|
||||||
value = false
|
|
||||||
var newValue: Boolean? = null
|
|
||||||
|
|
||||||
context.observeSettingsGlobalBoolean(TEST_NAME, TestLifecycleOwner().lifecycle) {
|
|
||||||
newValue = it
|
|
||||||
}
|
|
||||||
|
|
||||||
assertThat(newValue).isFalse()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun observeSettingsGlobalBoolean_valueChanged() {
|
|
||||||
var value by context.settingsGlobalBoolean(TEST_NAME)
|
|
||||||
value = false
|
|
||||||
var newValue: Boolean? = null
|
|
||||||
|
|
||||||
context.observeSettingsGlobalBoolean(TEST_NAME, TestLifecycleOwner().lifecycle) {
|
|
||||||
newValue = it
|
|
||||||
}
|
|
||||||
value = true
|
|
||||||
|
|
||||||
assertThat(newValue).isFalse()
|
|
||||||
}
|
|
||||||
|
|
||||||
private companion object {
|
|
||||||
const val TEST_NAME = "test_boolean_delegate"
|
|
||||||
}
|
|
||||||
}
|
|
Reference in New Issue
Block a user