Merge "Use MobileDataEnabledFlow in BillingCyclePreference" into main
diff --git a/src/com/android/settings/datausage/BillingCyclePreference.kt b/src/com/android/settings/datausage/BillingCyclePreference.kt
index 619f7e9..a6904bc 100644
--- a/src/com/android/settings/datausage/BillingCyclePreference.kt
+++ b/src/com/android/settings/datausage/BillingCyclePreference.kt
@@ -16,15 +16,21 @@
 
 import android.app.settings.SettingsEnums
 import android.content.Context
-import android.content.Intent
 import android.net.NetworkTemplate
 import android.os.Bundle
 import android.util.AttributeSet
-import androidx.preference.Preference
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.remember
+import androidx.compose.ui.res.stringResource
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
 import com.android.settings.R
 import com.android.settings.core.SubSettingLauncher
 import com.android.settings.datausage.lib.BillingCycleRepository
-import com.android.settings.network.MobileDataEnabledListener
+import com.android.settings.network.mobileDataEnabledFlow
+import com.android.settings.spa.preference.ComposePreference
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+import kotlinx.coroutines.flow.map
 
 /**
  * Preference which displays billing cycle of subscription
@@ -36,45 +42,31 @@
     context: Context,
     attrs: AttributeSet?,
     private val repository: BillingCycleRepository = BillingCycleRepository(context),
-) : Preference(context, attrs), TemplatePreference {
-    private lateinit var template: NetworkTemplate
-    private var subId = 0
-
-    private val listener = MobileDataEnabledListener(context) {
-        updateEnabled()
-    }
+) : ComposePreference(context, attrs), TemplatePreference {
 
     override fun setTemplate(template: NetworkTemplate, subId: Int) {
-        this.template = template
-        this.subId = subId
-        summary = null
-        updateEnabled()
-        intent = intent
+        setContent {
+            val isModifiable by remember {
+                context.mobileDataEnabledFlow(subId).map { repository.isModifiable(subId) }
+            }.collectAsStateWithLifecycle(initialValue = false)
+
+            Preference(object : PreferenceModel {
+                override val title = stringResource(R.string.billing_cycle)
+                override val enabled = { isModifiable }
+                override val onClick = { launchBillingCycleSettings(template) }
+            })
+        }
     }
 
-    override fun onAttached() {
-        super.onAttached()
-        listener.start(subId)
-    }
-
-    override fun onDetached() {
-        listener.stop()
-        super.onDetached()
-    }
-
-    private fun updateEnabled() {
-        isEnabled = repository.isModifiable(subId)
-    }
-
-    override fun getIntent(): Intent {
+    private fun launchBillingCycleSettings(template: NetworkTemplate) {
         val args = Bundle().apply {
             putParcelable(DataUsageList.EXTRA_NETWORK_TEMPLATE, template)
         }
-        return SubSettingLauncher(context).apply {
+        SubSettingLauncher(context).apply {
             setDestination(BillingCycleSettings::class.java.name)
             setArguments(args)
             setTitleRes(R.string.billing_cycle)
             setSourceMetricsCategory(SettingsEnums.PAGE_UNKNOWN)
-        }.toIntent()
+        }.launch()
     }
 }
diff --git a/src/com/android/settings/spa/preference/ComposePreference.kt b/src/com/android/settings/spa/preference/ComposePreference.kt
index aec85a9..aa5c32c 100644
--- a/src/com/android/settings/spa/preference/ComposePreference.kt
+++ b/src/com/android/settings/spa/preference/ComposePreference.kt
@@ -18,6 +18,7 @@
 
 import android.content.Context
 import android.util.AttributeSet
+import androidx.annotation.VisibleForTesting
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.platform.ComposeView
 import androidx.compose.ui.platform.ViewCompositionStrategy
@@ -26,13 +27,23 @@
 import com.android.settings.R
 import com.android.settingslib.spa.framework.theme.SettingsTheme
 
-class ComposePreference @JvmOverloads constructor(
+open class ComposePreference @JvmOverloads constructor(
     context: Context,
     attrs: AttributeSet? = null,
     defStyleAttr: Int = 0,
     defStyleRes: Int = 0,
 ) : Preference(context, attrs, defStyleAttr, defStyleRes) {
-    var content: @Composable () -> Unit = {}
+    private var content: @Composable () -> Unit = {}
+
+    fun setContent(content: @Composable () -> Unit) {
+        this.content = content
+    }
+
+    @VisibleForTesting
+    @Composable
+    fun Content() {
+        content()
+    }
 
     init {
         layoutResource = R.layout.preference_compose
diff --git a/src/com/android/settings/spa/preference/ComposePreferenceController.kt b/src/com/android/settings/spa/preference/ComposePreferenceController.kt
index 3ddb66b..9dd8282 100644
--- a/src/com/android/settings/spa/preference/ComposePreferenceController.kt
+++ b/src/com/android/settings/spa/preference/ComposePreferenceController.kt
@@ -29,7 +29,7 @@
     override fun displayPreference(screen: PreferenceScreen) {
         super.displayPreference(screen)
         preference = screen.findPreference(preferenceKey)!!
-        preference.content = { Content() }
+        preference.setContent { Content() }
     }
 
     @Composable
diff --git a/tests/spa_unit/src/com/android/settings/datausage/BillingCyclePreferenceTest.kt b/tests/spa_unit/src/com/android/settings/datausage/BillingCyclePreferenceTest.kt
index 2e2620b..4bf3851 100644
--- a/tests/spa_unit/src/com/android/settings/datausage/BillingCyclePreferenceTest.kt
+++ b/tests/spa_unit/src/com/android/settings/datausage/BillingCyclePreferenceTest.kt
@@ -18,40 +18,69 @@
 
 import android.content.Context
 import android.net.NetworkTemplate
+import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.assertIsEnabled
+import androidx.compose.ui.test.assertIsNotEnabled
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithText
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.R
 import com.android.settings.datausage.lib.BillingCycleRepository
-import com.google.common.truth.Truth.assertThat
+import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.kotlin.doReturn
 import org.mockito.kotlin.mock
+import org.mockito.kotlin.stub
 
 @RunWith(AndroidJUnit4::class)
 class BillingCyclePreferenceTest {
+    @get:Rule
+    val composeTestRule = createComposeRule()
 
-    private val mockBillingCycleRepository = mock<BillingCycleRepository> {
-        on { isModifiable(SUB_ID) } doReturn false
-    }
+    private val mockBillingCycleRepository = mock<BillingCycleRepository>()
 
     private val context: Context = ApplicationProvider.getApplicationContext()
 
     private val preference = BillingCyclePreference(context, null, mockBillingCycleRepository)
 
     @Test
-    fun isEnabled_initialState() {
-        val enabled = preference.isEnabled
+    fun setTemplate_titleDisplayed() {
+        setTemplate()
 
-        assertThat(enabled).isTrue()
+        composeTestRule.onNodeWithText(context.getString(R.string.billing_cycle))
+            .assertIsDisplayed()
     }
 
     @Test
-    fun isEnabled_afterSetTemplate_updated() {
+    fun setTemplate_modifiable_enabled() {
+        mockBillingCycleRepository.stub {
+            on { isModifiable(SUB_ID) } doReturn true
+        }
+
+        setTemplate()
+
+        composeTestRule.onNodeWithText(context.getString(R.string.billing_cycle)).assertIsEnabled()
+    }
+
+    @Test
+    fun setTemplate_notModifiable_notEnabled() {
+        mockBillingCycleRepository.stub {
+            on { isModifiable(SUB_ID) } doReturn false
+        }
+
+        setTemplate()
+
+        composeTestRule.onNodeWithText(context.getString(R.string.billing_cycle))
+            .assertIsNotEnabled()
+    }
+
+    private fun setTemplate() {
         preference.setTemplate(mock<NetworkTemplate>(), SUB_ID)
-
-        val enabled = preference.isEnabled
-
-        assertThat(enabled).isFalse()
+        composeTestRule.setContent {
+            preference.Content()
+        }
     }
 
     private companion object {
diff --git a/tests/spa_unit/src/com/android/settings/spa/preference/ComposePreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/spa/preference/ComposePreferenceControllerTest.kt
index 36817d1..cdfa514 100644
--- a/tests/spa_unit/src/com/android/settings/spa/preference/ComposePreferenceControllerTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/preference/ComposePreferenceControllerTest.kt
@@ -61,7 +61,7 @@
         controller.displayPreference(preferenceScreen)
 
         composeTestRule.setContent {
-            preference.content()
+            preference.Content()
         }
         composeTestRule.onNodeWithText(TEXT).assertIsDisplayed()
     }
diff --git a/tests/spa_unit/src/com/android/settings/spa/preference/ComposePreferenceTest.kt b/tests/spa_unit/src/com/android/settings/spa/preference/ComposePreferenceTest.kt
index 28bde3a..a2fe752 100644
--- a/tests/spa_unit/src/com/android/settings/spa/preference/ComposePreferenceTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/preference/ComposePreferenceTest.kt
@@ -43,7 +43,7 @@
 
     @Test
     fun onBindViewHolder() {
-        preference.content = {
+        preference.setContent {
             Text(TEXT)
         }