[Spa] Fix State<T> as a parameter of SwitchPreference

Bug: 292036686
Test: manual - with Gallery
Test: manual - with Settings
Test: unit tests
Change-Id: Ia544909015aa9858224971084a5804103032ec49
diff --git a/packages/SettingsLib/Spa/build.gradle.kts b/packages/SettingsLib/Spa/build.gradle.kts
index 1c8ddcb..80b944f 100644
--- a/packages/SettingsLib/Spa/build.gradle.kts
+++ b/packages/SettingsLib/Spa/build.gradle.kts
@@ -1,5 +1,5 @@
 /*
- * Copyright 2022 The Android Open Source Project
+ * 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.
@@ -25,11 +25,16 @@
     alias(libs.plugins.kotlin.android) apply false
 }
 
+val androidTop : String = File(rootDir, "../../../../..").canonicalPath
+
 allprojects {
+    extra["androidTop"] = androidTop
     extra["jetpackComposeVersion"] = "1.6.0-alpha08"
 }
 
 subprojects {
+    layout.buildDirectory.set(file("$androidTop/out/gradle-spa/$name"))
+
     plugins.withType<AndroidBasePlugin> {
         configure<BaseExtension> {
             compileSdkVersion(34)
@@ -38,10 +43,11 @@
                 minSdk = 21
                 targetSdk = 34
             }
+        }
 
-            compileOptions {
-                sourceCompatibility = JavaVersion.VERSION_17
-                targetCompatibility = JavaVersion.VERSION_17
+        configure<JavaPluginExtension> {
+            toolchain {
+                languageVersion.set(JavaLanguageVersion.of(libs.versions.jvm.get()))
             }
         }
     }
@@ -60,7 +66,7 @@
 
     tasks.withType<KotlinCompile> {
         kotlinOptions {
-            jvmTarget = "17"
+            jvmTarget = libs.versions.jvm.get()
             freeCompilerArgs = listOf("-Xjvm-default=all")
         }
     }
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/itemList/ItemOperatePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/itemList/ItemOperatePage.kt
index 98b27b7..6caec07 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/itemList/ItemOperatePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/itemList/ItemOperatePage.kt
@@ -17,9 +17,11 @@
 package com.android.settingslib.spa.gallery.itemList
 
 import android.os.Bundle
+import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
 import androidx.core.os.bundleOf
 import androidx.navigation.NavType
 import androidx.navigation.navArgument
@@ -79,13 +81,13 @@
         entryList.add(
             SettingsEntryBuilder.create("ItemOp", owner)
                 .setUiLayoutFn {
-                    val checked = rememberSaveable { mutableStateOf(false) }
+                    var checked by rememberSaveable { mutableStateOf(false) }
                     SwitchPreference(remember {
                         object : SwitchPreferenceModel {
                             override val title = "Item operation: $opName"
-                            override val checked = checked
+                            override val checked = { checked }
                             override val onCheckedChange =
-                                { newChecked: Boolean -> checked.value = newChecked }
+                                { newChecked: Boolean -> checked = newChecked }
                         }
                     })
                 }.build(),
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/MainSwitchPreferencePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/MainSwitchPreferencePage.kt
index 442ace8..0d85c0e3 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/MainSwitchPreferencePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/MainSwitchPreferencePage.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * 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.
@@ -18,16 +18,17 @@
 
 import android.os.Bundle
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.tooling.preview.Preview
 import com.android.settingslib.spa.framework.common.SettingsEntry
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
 import com.android.settingslib.spa.framework.common.createSettingsPage
 import com.android.settingslib.spa.framework.compose.navigator
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.framework.theme.SettingsTheme
 import com.android.settingslib.spa.widget.preference.MainSwitchPreference
 import com.android.settingslib.spa.widget.preference.Preference
@@ -43,13 +44,13 @@
     override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
         val entryList = mutableListOf<SettingsEntry>()
         entryList.add(
-            SettingsEntryBuilder.create( "MainSwitchPreference", owner)
+            SettingsEntryBuilder.create("MainSwitchPreference", owner)
                 .setUiLayoutFn {
                     SampleMainSwitchPreference()
                 }.build()
         )
         entryList.add(
-            SettingsEntryBuilder.create( "MainSwitchPreference not changeable", owner)
+            SettingsEntryBuilder.create("MainSwitchPreference not changeable", owner)
                 .setUiLayoutFn {
                     SampleNotChangeableMainSwitchPreference()
                 }.build()
@@ -75,25 +76,25 @@
 
 @Composable
 private fun SampleMainSwitchPreference() {
-    val checked = rememberSaveable { mutableStateOf(false) }
+    var checked by rememberSaveable { mutableStateOf(false) }
     MainSwitchPreference(remember {
         object : SwitchPreferenceModel {
             override val title = "MainSwitchPreference"
-            override val checked = checked
-            override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+            override val checked = { checked }
+            override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
         }
     })
 }
 
 @Composable
 private fun SampleNotChangeableMainSwitchPreference() {
-    val checked = rememberSaveable { mutableStateOf(true) }
+    var checked by rememberSaveable { mutableStateOf(true) }
     MainSwitchPreference(remember {
         object : SwitchPreferenceModel {
             override val title = "Not changeable"
-            override val changeable = stateOf(false)
-            override val checked = checked
-            override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+            override val changeable = { false }
+            override val checked = { checked }
+            override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
         }
     })
 }
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/SwitchPreferencePageProvider.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/SwitchPreferencePageProvider.kt
index ce0ee18..f2225fa 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/SwitchPreferencePageProvider.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/SwitchPreferencePageProvider.kt
@@ -20,17 +20,18 @@
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.outlined.AirplanemodeActive
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.produceState
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.tooling.preview.Preview
 import com.android.settingslib.spa.framework.common.SettingsEntry
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
 import com.android.settingslib.spa.framework.common.createSettingsPage
 import com.android.settingslib.spa.framework.compose.navigator
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.framework.theme.SettingsTheme
 import com.android.settingslib.spa.widget.preference.Preference
 import com.android.settingslib.spa.widget.preference.PreferenceModel
@@ -98,32 +99,32 @@
 
 @Composable
 private fun SampleSwitchPreference() {
-    val checked = rememberSaveable { mutableStateOf(false) }
+    var checked by rememberSaveable { mutableStateOf(false) }
     SwitchPreference(remember {
         object : SwitchPreferenceModel {
             override val title = "SwitchPreference"
-            override val checked = checked
-            override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+            override val checked = { checked }
+            override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
         }
     })
 }
 
 @Composable
 private fun SampleSwitchPreferenceWithSummary() {
-    val checked = rememberSaveable { mutableStateOf(true) }
+    var checked by rememberSaveable { mutableStateOf(true) }
     SwitchPreference(remember {
         object : SwitchPreferenceModel {
             override val title = "SwitchPreference"
             override val summary = { "With summary" }
-            override val checked = checked
-            override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+            override val checked = { checked }
+            override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
         }
     })
 }
 
 @Composable
 private fun SampleSwitchPreferenceWithAsyncSummary() {
-    val checked = rememberSaveable { mutableStateOf(true) }
+    var checked by rememberSaveable { mutableStateOf(true) }
     val summary = produceState(initialValue = " ") {
         delay(1000L)
         value = "Async summary"
@@ -132,34 +133,34 @@
         object : SwitchPreferenceModel {
             override val title = "SwitchPreference"
             override val summary = { summary.value }
-            override val checked = checked
-            override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+            override val checked = { checked }
+            override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
         }
     })
 }
 
 @Composable
 private fun SampleNotChangeableSwitchPreference() {
-    val checked = rememberSaveable { mutableStateOf(true) }
+    var checked by rememberSaveable { mutableStateOf(true) }
     SwitchPreference(remember {
         object : SwitchPreferenceModel {
             override val title = "SwitchPreference"
             override val summary = { "Not changeable" }
-            override val changeable = stateOf(false)
-            override val checked = checked
-            override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+            override val changeable = { false }
+            override val checked = { checked }
+            override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
         }
     })
 }
 
 @Composable
 private fun SampleSwitchPreferenceWithIcon() {
-    val checked = rememberSaveable { mutableStateOf(true) }
+    var checked by rememberSaveable { mutableStateOf(true) }
     SwitchPreference(remember {
         object : SwitchPreferenceModel {
             override val title = "SwitchPreference"
-            override val checked = checked
-            override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+            override val checked = { checked }
+            override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
             override val icon = @Composable {
                 SettingsIcon(imageVector = Icons.Outlined.AirplanemodeActive)
             }
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/TwoTargetSwitchPreferencePageProvider.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/TwoTargetSwitchPreferencePageProvider.kt
index fc50745..19de31d 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/TwoTargetSwitchPreferencePageProvider.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/TwoTargetSwitchPreferencePageProvider.kt
@@ -18,17 +18,18 @@
 
 import android.os.Bundle
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.produceState
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.tooling.preview.Preview
 import com.android.settingslib.spa.framework.common.SettingsEntry
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
 import com.android.settingslib.spa.framework.common.createSettingsPage
 import com.android.settingslib.spa.framework.compose.navigator
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.framework.theme.SettingsTheme
 import com.android.settingslib.spa.widget.preference.Preference
 import com.android.settingslib.spa.widget.preference.PreferenceModel
@@ -89,32 +90,32 @@
 
 @Composable
 private fun SampleTwoTargetSwitchPreference() {
-    val checked = rememberSaveable { mutableStateOf(false) }
+    var checked by rememberSaveable { mutableStateOf(false) }
     TwoTargetSwitchPreference(remember {
         object : SwitchPreferenceModel {
             override val title = "TwoTargetSwitchPreference"
-            override val checked = checked
-            override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+            override val checked = { checked }
+            override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
         }
     }) {}
 }
 
 @Composable
 private fun SampleTwoTargetSwitchPreferenceWithSummary() {
-    val checked = rememberSaveable { mutableStateOf(true) }
+    var checked by rememberSaveable { mutableStateOf(true) }
     TwoTargetSwitchPreference(remember {
         object : SwitchPreferenceModel {
             override val title = "TwoTargetSwitchPreference"
             override val summary = { "With summary" }
-            override val checked = checked
-            override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+            override val checked = { checked }
+            override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
         }
     }) {}
 }
 
 @Composable
 private fun SampleTwoTargetSwitchPreferenceWithAsyncSummary() {
-    val checked = rememberSaveable { mutableStateOf(true) }
+    var checked by rememberSaveable { mutableStateOf(true) }
     val summary = produceState(initialValue = " ") {
         delay(1000L)
         value = "Async summary"
@@ -123,22 +124,22 @@
         object : SwitchPreferenceModel {
             override val title = "TwoTargetSwitchPreference"
             override val summary = { summary.value }
-            override val checked = checked
-            override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+            override val checked = { checked }
+            override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
         }
     }) {}
 }
 
 @Composable
 private fun SampleNotChangeableTwoTargetSwitchPreference() {
-    val checked = rememberSaveable { mutableStateOf(true) }
+    var checked by rememberSaveable { mutableStateOf(true) }
     TwoTargetSwitchPreference(remember {
         object : SwitchPreferenceModel {
             override val title = "TwoTargetSwitchPreference"
             override val summary = { "Not changeable" }
-            override val changeable = stateOf(false)
-            override val checked = checked
-            override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+            override val changeable = { false }
+            override val checked = { checked }
+            override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
         }
     }) {}
 }
diff --git a/packages/SettingsLib/Spa/gradle/libs.versions.toml b/packages/SettingsLib/Spa/gradle/libs.versions.toml
index aafae5f..fdb0471 100644
--- a/packages/SettingsLib/Spa/gradle/libs.versions.toml
+++ b/packages/SettingsLib/Spa/gradle/libs.versions.toml
@@ -18,6 +18,7 @@
 agp = "8.1.2"
 compose-compiler = "1.5.1"
 dexmaker-mockito = "2.28.3"
+jvm = "17"
 kotlin = "1.9.0"
 truth = "1.1.5"
 
diff --git a/packages/SettingsLib/Spa/screenshot/build.gradle.kts b/packages/SettingsLib/Spa/screenshot/build.gradle.kts
new file mode 100644
index 0000000..03e9d7d
--- /dev/null
+++ b/packages/SettingsLib/Spa/screenshot/build.gradle.kts
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+plugins {
+    alias(libs.plugins.android.library)
+    alias(libs.plugins.kotlin.android)
+}
+
+val androidTop: String by extra
+
+android {
+    namespace = "com.android.settingslib.spa.screenshot"
+
+    defaultConfig {
+        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+    }
+
+    sourceSets {
+        sourceSets.getByName("main") {
+            java.setSrcDirs(
+                listOf("$androidTop/platform_testing/libraries/screenshot/src/main/java")
+            )
+        }
+        sourceSets.getByName("androidTest") {
+            kotlin.setSrcDirs(listOf("src"))
+            res.setSrcDirs(listOf("res"))
+            manifest.srcFile("AndroidManifest.xml")
+        }
+    }
+    buildFeatures {
+        compose = true
+    }
+}
+
+dependencies {
+    androidTestImplementation(project(":spa"))
+    androidTestImplementation(project(":testutils"))
+    androidTestImplementation(libs.dexmaker.mockito)
+}
diff --git a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/MainSwitchPreferenceScreenshotTest.kt b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/MainSwitchPreferenceScreenshotTest.kt
index c1d7188..e547d26 100644
--- a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/MainSwitchPreferenceScreenshotTest.kt
+++ b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/MainSwitchPreferenceScreenshotTest.kt
@@ -17,7 +17,6 @@
 package com.android.settingslib.spa.screenshot.widget.preference
 
 import androidx.compose.foundation.layout.Column
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.screenshot.util.SettingsScreenshotTestRule
 import com.android.settingslib.spa.widget.preference.MainSwitchPreference
 import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
@@ -51,14 +50,14 @@
                 MainSwitchPreference(
                     object : SwitchPreferenceModel {
                         override val title = "MainSwitchPreference"
-                        override val checked = stateOf(false)
+                        override val checked = { false }
                         override val onCheckedChange = null
                     })
 
                 MainSwitchPreference(object : SwitchPreferenceModel {
                     override val title = "Not changeable"
-                    override val changeable = stateOf(false)
-                    override val checked = stateOf(true)
+                    override val changeable = { false }
+                    override val checked = { true }
                     override val onCheckedChange = null
                 })
             }
diff --git a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/SwitchPreferenceScreenshotTest.kt b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/SwitchPreferenceScreenshotTest.kt
index a688e11..6966a74 100644
--- a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/SwitchPreferenceScreenshotTest.kt
+++ b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/SwitchPreferenceScreenshotTest.kt
@@ -20,7 +20,6 @@
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.outlined.AirplanemodeActive
 import androidx.compose.runtime.Composable
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.screenshot.util.SettingsScreenshotTestRule
 import com.android.settingslib.spa.widget.preference.SwitchPreference
 import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
@@ -65,7 +64,7 @@
 private fun SampleSwitchPreference() {
     SwitchPreference(object : SwitchPreferenceModel {
         override val title = "SwitchPreference"
-        override val checked = stateOf(false)
+        override val checked = { false }
         override val onCheckedChange = null
     })
 }
@@ -75,7 +74,7 @@
     SwitchPreference(object : SwitchPreferenceModel {
         override val title = "SwitchPreference"
         override val summary = { "With summary" }
-        override val checked = stateOf(true)
+        override val checked = { true }
         override val onCheckedChange = null
     })
 }
@@ -85,8 +84,8 @@
     SwitchPreference(object : SwitchPreferenceModel {
         override val title = "SwitchPreference"
         override val summary = { "Not changeable" }
-        override val changeable = stateOf(false)
-        override val checked = stateOf(true)
+        override val changeable = { false }
+        override val checked = { true }
         override val onCheckedChange = null
     })
 }
@@ -95,7 +94,7 @@
 private fun SampleSwitchPreferenceWithIcon() {
     SwitchPreference(object : SwitchPreferenceModel {
         override val title = "SwitchPreference"
-        override val checked = stateOf(true)
+        override val checked = { true }
         override val onCheckedChange = null
         override val icon = @Composable {
             SettingsIcon(imageVector = Icons.Outlined.AirplanemodeActive)
diff --git a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/TwoTargetSwitchPreferenceScreenshotTest.kt b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/TwoTargetSwitchPreferenceScreenshotTest.kt
index 8f0abc0..72c5cb8 100644
--- a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/TwoTargetSwitchPreferenceScreenshotTest.kt
+++ b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/TwoTargetSwitchPreferenceScreenshotTest.kt
@@ -50,21 +50,21 @@
             Column {
                 TwoTargetSwitchPreference(object : SwitchPreferenceModel {
                     override val title = "TwoTargetSwitchPreference"
-                    override val checked = stateOf(false)
+                    override val checked = { false }
                     override val onCheckedChange = null
                 }) {}
 
                 TwoTargetSwitchPreference(object : SwitchPreferenceModel {
                     override val title = "TwoTargetSwitchPreference"
                     override val summary = { "With summary" }
-                    override val checked = stateOf(true)
+                    override val checked = { true }
                     override val onCheckedChange = null
                 }) {}
 
                 TwoTargetSwitchPreference(object : SwitchPreferenceModel {
                     override val title = "Not changeable"
-                    override val changeable = stateOf(false)
-                    override val checked = stateOf(true)
+                    override val changeable = { false }
+                    override val checked = { true }
                     override val onCheckedChange = null
                 }) {}
             }
diff --git a/packages/SettingsLib/Spa/settings.gradle.kts b/packages/SettingsLib/Spa/settings.gradle.kts
index b8dfae3..e003c81 100644
--- a/packages/SettingsLib/Spa/settings.gradle.kts
+++ b/packages/SettingsLib/Spa/settings.gradle.kts
@@ -1,5 +1,5 @@
 /*
- * Copyright 2022 The Android Open Source Project
+ * 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.
@@ -49,3 +49,6 @@
 include(":testutils")
 include(":SettingsLibColor")
 project(":SettingsLibColor").projectDir = File(rootDir, "../Color")
+
+// Uncomment this for screenshot
+// include(":screenshot")
\ No newline at end of file
diff --git a/packages/SettingsLib/Spa/spa/build.gradle.kts b/packages/SettingsLib/Spa/spa/build.gradle.kts
index 189c2dd..4335173 100644
--- a/packages/SettingsLib/Spa/spa/build.gradle.kts
+++ b/packages/SettingsLib/Spa/spa/build.gradle.kts
@@ -1,5 +1,5 @@
 /*
- * Copyright 2022 The Android Open Source Project
+ * 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.
@@ -63,7 +63,7 @@
     api("androidx.compose.ui:ui-tooling-preview:$jetpackComposeVersion")
     api("androidx.lifecycle:lifecycle-livedata-ktx")
     api("androidx.lifecycle:lifecycle-runtime-compose")
-    api("androidx.navigation:navigation-compose:2.7.4")
+    api("androidx.navigation:navigation-compose:2.7.5")
     api("com.github.PhilJay:MPAndroidChart:v3.1.0-alpha")
     api("com.google.android.material:material:1.7.0-alpha03")
     debugApi("androidx.compose.ui:ui-tooling:$jetpackComposeVersion")
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/livedata/LiveDataExt.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/livedata/LiveDataExt.kt
new file mode 100644
index 0000000..3d330fe
--- /dev/null
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/livedata/LiveDataExt.kt
@@ -0,0 +1,34 @@
+/*
+ * 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.settingslib.spa.livedata
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.livedata.observeAsState
+import androidx.lifecycle.LiveData
+
+/**
+ * Starts observing this LiveData and represents its values via State and Callback.
+ *
+ * Every time there would be new value posted into the LiveData the returned State will be updated
+ * causing recomposition of every Callback usage.
+ */
+@Composable
+fun <T> LiveData<T>.observeAsCallback(): () -> T? {
+    val isAllowed by observeAsState()
+    return { isAllowed }
+}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/MainSwitchPreference.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/MainSwitchPreference.kt
index 35c34d4..fc8de80 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/MainSwitchPreference.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/MainSwitchPreference.kt
@@ -24,7 +24,6 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
-import com.android.settingslib.spa.framework.compose.toState
 import com.android.settingslib.spa.framework.theme.SettingsDimension
 import com.android.settingslib.spa.framework.theme.SettingsShape
 import com.android.settingslib.spa.framework.theme.SettingsTheme
@@ -35,7 +34,7 @@
     EntryHighlight {
         Surface(
             modifier = Modifier.padding(SettingsDimension.itemPaddingEnd),
-            color = when (model.checked.value) {
+            color = when (model.checked()) {
                 true -> MaterialTheme.colorScheme.primaryContainer
                 else -> MaterialTheme.colorScheme.secondaryContainer
             },
@@ -43,8 +42,8 @@
         ) {
             InternalSwitchPreference(
                 title = model.title,
-                checked = model.checked.value,
-                changeable = model.changeable.value,
+                checked = model.checked(),
+                changeable = model.changeable(),
                 onCheckedChange = model.onCheckedChange,
                 paddingStart = 20.dp,
                 paddingEnd = 20.dp,
@@ -61,12 +60,12 @@
         Column {
             MainSwitchPreference(object : SwitchPreferenceModel {
                 override val title = "Use Dark theme"
-                override val checked = true.toState()
+                override val checked = { true }
                 override val onCheckedChange: (Boolean) -> Unit = {}
             })
             MainSwitchPreference(object : SwitchPreferenceModel {
                 override val title = "Use Dark theme"
-                override val checked = false.toState()
+                override val checked = { false }
                 override val onCheckedChange: (Boolean) -> Unit = {}
             })
         }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/SwitchPreference.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/SwitchPreference.kt
index 12afe92..aceb545 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/SwitchPreference.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/SwitchPreference.kt
@@ -25,13 +25,11 @@
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.outlined.AirplanemodeActive
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.State
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.semantics.Role
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.Dp
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.framework.theme.SettingsDimension
 import com.android.settingslib.spa.framework.theme.SettingsTheme
 import com.android.settingslib.spa.framework.util.EntryHighlight
@@ -67,15 +65,15 @@
      *
      * This can be `null` during the data loading before the data is available.
      */
-    val checked: State<Boolean?>
+    val checked: () -> Boolean?
 
     /**
      * Indicates whether this [SwitchPreference] is changeable.
      *
      * Not changeable [SwitchPreference] will be displayed in disabled style.
      */
-    val changeable: State<Boolean>
-        get() = stateOf(true)
+    val changeable: () -> Boolean
+        get() = { true }
 
     /**
      * The switch change handler of this [SwitchPreference].
@@ -97,8 +95,8 @@
             title = model.title,
             summary = model.summary,
             icon = model.icon,
-            checked = model.checked.value,
-            changeable = model.changeable.value,
+            checked = model.checked(),
+            changeable = model.changeable(),
             onCheckedChange = model.onCheckedChange,
         )
     }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreference.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreference.kt
index 9a6580c..7eed745 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreference.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreference.kt
@@ -34,8 +34,8 @@
             icon = icon,
         ) {
             SettingsSwitch(
-                checked = model.checked.value,
-                changeable = { model.changeable.value },
+                checked = model.checked(),
+                changeable = model.changeable,
                 onCheckedChange = model.onCheckedChange,
             )
         }
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/MainSwitchPreferenceTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/MainSwitchPreferenceTest.kt
index 6588cf5..8ce6979 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/MainSwitchPreferenceTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/MainSwitchPreferenceTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * 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.
@@ -17,9 +17,11 @@
 package com.android.settingslib.spa.widget.preference
 
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.test.assertIsDisplayed
 import androidx.compose.ui.test.assertIsOff
 import androidx.compose.ui.test.assertIsOn
@@ -28,7 +30,6 @@
 import androidx.compose.ui.test.onNodeWithText
 import androidx.compose.ui.test.performClick
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.settingslib.spa.framework.compose.stateOf
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -81,13 +82,13 @@
 
 @Composable
 private fun TestMainSwitchPreference(changeable: Boolean) {
-    val checked = rememberSaveable { mutableStateOf(false) }
+    var checked by rememberSaveable { mutableStateOf(false) }
     MainSwitchPreference(remember {
         object : SwitchPreferenceModel {
             override val title = TITLE
-            override val checked = checked
-            override val changeable = stateOf(changeable)
-            override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+            override val checked = { checked }
+            override val changeable = { changeable }
+            override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
         }
     })
 }
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/SwitchPreferenceTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/SwitchPreferenceTest.kt
index d6c8fbc..0b2127d 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/SwitchPreferenceTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/SwitchPreferenceTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * 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.
@@ -17,9 +17,11 @@
 package com.android.settingslib.spa.widget.preference
 
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.test.assertIsDisplayed
 import androidx.compose.ui.test.assertIsOff
 import androidx.compose.ui.test.assertIsOn
@@ -28,7 +30,6 @@
 import androidx.compose.ui.test.onNodeWithText
 import androidx.compose.ui.test.performClick
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.settingslib.spa.framework.compose.stateOf
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -79,13 +80,13 @@
 
 @Composable
 private fun TestSwitchPreference(changeable: Boolean) {
-    val checked = rememberSaveable { mutableStateOf(false) }
+    var checked by rememberSaveable { mutableStateOf(false) }
     SwitchPreference(remember {
         object : SwitchPreferenceModel {
             override val title = "SwitchPreference"
-            override val checked = checked
-            override val changeable = stateOf(changeable)
-            override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+            override val checked = { checked }
+            override val changeable = { changeable }
+            override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
         }
     })
 }
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreferenceTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreferenceTest.kt
index c49e92d..3455851 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreferenceTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreferenceTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * 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.
@@ -17,9 +17,11 @@
 package com.android.settingslib.spa.widget.preference
 
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.test.assertIsDisplayed
 import androidx.compose.ui.test.assertIsOff
 import androidx.compose.ui.test.assertIsOn
@@ -28,7 +30,6 @@
 import androidx.compose.ui.test.onNodeWithText
 import androidx.compose.ui.test.performClick
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
@@ -41,9 +42,8 @@
 
     @Test
     fun title_displayed() {
-        val checked = mutableStateOf(false)
         composeTestRule.setContent {
-            TestTwoTargetSwitchPreference(checked = checked, changeable = true)
+            TestTwoTargetSwitchPreference(changeable = true)
         }
 
         composeTestRule.onNodeWithText("TwoTargetSwitchPreference").assertIsDisplayed()
@@ -51,9 +51,8 @@
 
     @Test
     fun toggleable_initialStateIsCorrect() {
-        val checked = mutableStateOf(false)
         composeTestRule.setContent {
-            TestTwoTargetSwitchPreference(checked = checked, changeable = true)
+            TestTwoTargetSwitchPreference(changeable = true)
         }
 
         composeTestRule.onNode(isToggleable()).assertIsOff()
@@ -61,9 +60,8 @@
 
     @Test
     fun toggleable_changeable_withEffect() {
-        val checked = mutableStateOf(false)
         composeTestRule.setContent {
-            TestTwoTargetSwitchPreference(checked = checked, changeable = true)
+            TestTwoTargetSwitchPreference(changeable = true)
         }
 
         composeTestRule.onNode(isToggleable()).performClick()
@@ -72,9 +70,8 @@
 
     @Test
     fun toggleable_notChangeable_noEffect() {
-        val checked = mutableStateOf(false)
         composeTestRule.setContent {
-            TestTwoTargetSwitchPreference(checked = checked, changeable = false)
+            TestTwoTargetSwitchPreference(changeable = false)
         }
 
         composeTestRule.onNode(isToggleable()).performClick()
@@ -83,10 +80,9 @@
 
     @Test
     fun clickable_canBeClick() {
-        val checked = mutableStateOf(false)
         var clicked = false
         composeTestRule.setContent {
-            TestTwoTargetSwitchPreference(checked = checked, changeable = false) {
+            TestTwoTargetSwitchPreference(changeable = false) {
                 clicked = true
             }
         }
@@ -98,17 +94,17 @@
 
 @Composable
 private fun TestTwoTargetSwitchPreference(
-    checked: MutableState<Boolean>,
     changeable: Boolean,
     onClick: () -> Unit = {},
 ) {
+    var checked by rememberSaveable { mutableStateOf(false) }
     TwoTargetSwitchPreference(
         model = remember {
             object : SwitchPreferenceModel {
                 override val title = "TwoTargetSwitchPreference"
-                override val checked = checked
-                override val changeable = stateOf(changeable)
-                override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+                override val checked = { checked }
+                override val changeable = { changeable }
+                override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
             }
         },
         onClick = onClick,
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListSwitchItem.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListSwitchItem.kt
index 155905b..36877af 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListSwitchItem.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListSwitchItem.kt
@@ -17,7 +17,6 @@
 package com.android.settingslib.spaprivileged.template.app
 
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.State
 import com.android.settingslib.spa.framework.theme.SettingsDimension
 import com.android.settingslib.spa.widget.preference.SwitchPreference
 import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
@@ -25,8 +24,8 @@
 
 @Composable
 fun <T : AppRecord> AppListItemModel<T>.AppListSwitchItem(
-    checked: State<Boolean?>,
-    changeable: State<Boolean>,
+    checked: () -> Boolean?,
+    changeable: () -> Boolean,
     onCheckedChange: ((newChecked: Boolean) -> Unit)?,
 ) {
     SwitchPreference(
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListTwoTargetSwitchItem.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListTwoTargetSwitchItem.kt
index 99d3840..bea14c3 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListTwoTargetSwitchItem.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListTwoTargetSwitchItem.kt
@@ -17,7 +17,6 @@
 package com.android.settingslib.spaprivileged.template.app
 
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.State
 import com.android.settingslib.spa.framework.theme.SettingsDimension
 import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
 import com.android.settingslib.spa.widget.preference.TwoTargetSwitchPreference
@@ -26,8 +25,8 @@
 @Composable
 fun <T : AppRecord> AppListItemModel<T>.AppListTwoTargetSwitchItem(
     onClick: () -> Unit,
-    checked: State<Boolean?>,
-    changeable: State<Boolean>,
+    checked: () -> Boolean?,
+    changeable: () -> Boolean,
     onCheckedChange: ((newChecked: Boolean) -> Unit)?,
 ) {
     TwoTargetSwitchPreference(
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppList.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppList.kt
index e9da88e..7bd7fbe 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppList.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppList.kt
@@ -22,11 +22,7 @@
 import android.content.Context
 import android.content.pm.ApplicationInfo
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.State
-import androidx.compose.runtime.derivedStateOf
 import androidx.compose.runtime.livedata.observeAsState
-import androidx.compose.runtime.remember
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.framework.util.asyncMapItem
 import com.android.settingslib.spa.framework.util.filterItem
 import com.android.settingslib.spaprivileged.model.app.AppOpsController
@@ -97,8 +93,9 @@
         with(packageManagers) {
             AppOpPermissionRecord(
                 app = app,
-                hasRequestBroaderPermission =
-                    broaderPermission?.let { app.hasRequestPermission(it) } ?: false,
+                hasRequestBroaderPermission = broaderPermission?.let {
+                    app.hasRequestPermission(it)
+                } ?: false,
                 hasRequestPermission = hasRequestPermission,
                 appOpsController = createAppOpsController(app),
             )
@@ -138,22 +135,19 @@
      * (This means pre-M gets approval during install time; M apps gets approval during runtime).
      */
     @Composable
-    override fun isAllowed(record: AppOpPermissionRecord): State<Boolean?> {
+    override fun isAllowed(record: AppOpPermissionRecord): () -> Boolean? {
         if (record.hasRequestBroaderPermission) {
             // Broader permission trumps the specific permission.
-            return stateOf(true)
+            return { true }
         }
 
         val mode = record.appOpsController.mode.observeAsState()
-        return remember {
-            derivedStateOf {
-                when (mode.value) {
-                    null -> null
-                    MODE_ALLOWED -> true
-                    MODE_DEFAULT ->
-                        with(packageManagers) { record.app.hasGrantPermission(permission) }
-                    else -> false
-                }
+        return {
+            when (mode.value) {
+                null -> null
+                MODE_ALLOWED -> true
+                MODE_DEFAULT -> with(packageManagers) { record.app.hasGrantPermission(permission) }
+                else -> false
             }
         }
     }
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt
index 62c5f70..3380b7d 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt
@@ -22,9 +22,10 @@
 import androidx.annotation.VisibleForTesting
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.State
+import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.res.stringResource
 import androidx.core.os.bundleOf
@@ -165,14 +166,16 @@
     context: Context,
     private val listModel: TogglePermissionAppListModel<T>,
     private val record: T,
-    isAllowed: State<Boolean?>,
+    isAllowed: () -> Boolean?,
 ) : SwitchPreferenceModel {
+    private var appChangeable by mutableStateOf(true)
+
     override val title: String = context.getString(listModel.switchTitleResId)
     override val checked = isAllowed
-    override val changeable = mutableStateOf(true)
+    override val changeable = { appChangeable }
 
     fun initState() {
-        changeable.value = listModel.isChangeable(record)
+        appChangeable = listModel.isChangeable(record)
     }
 
     override val onCheckedChange: (Boolean) -> Unit = { newChecked ->
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt
index 1ab6230..8704f20 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt
@@ -19,7 +19,6 @@
 import android.content.Context
 import android.content.pm.ApplicationInfo
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.State
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
 import com.android.settingslib.spa.framework.compose.rememberContext
@@ -64,7 +63,7 @@
      * Gets whether the permission is allowed for the given app.
      */
     @Composable
-    fun isAllowed(record: T): State<Boolean?>
+    fun isAllowed(record: T): () -> Boolean?
 
     /**
      * Gets whether the permission on / off is changeable for the given app.
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt
index 3ab27367..785f779 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt
@@ -156,12 +156,12 @@
             )
         }
         val restrictedMode by restrictionsProviderFactory.rememberRestrictedMode(restrictions)
-        val allowed by listModel.isAllowed(record)
+        val allowed = listModel.isAllowed(record)
         return RestrictedSwitchPreference.getSummary(
             context = context,
             restrictedModeSupplier = { restrictedMode },
-            summaryIfNoRestricted = { getSummaryIfNoRestricted(allowed) },
-            checked = { allowed },
+            summaryIfNoRestricted = { getSummaryIfNoRestricted(allowed()) },
+            checked = allowed,
         )
     }
 
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreference.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreference.kt
index d17e0c7..e41976f 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreference.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreference.kt
@@ -28,7 +28,6 @@
 import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.semantics.toggleableState
 import androidx.compose.ui.state.ToggleableState
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.widget.preference.SwitchPreference
 import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
 import com.android.settingslib.spaprivileged.framework.compose.getPlaceholder
@@ -97,21 +96,21 @@
         context = context,
         restrictedModeSupplier = { restrictedMode },
         summaryIfNoRestricted = model.summary,
-        checked = { model.checked.value },
+        checked = model.checked,
     )
 
     override val checked = when (restrictedMode) {
-        null -> stateOf(null)
+        null -> ({ null })
         is NoRestricted -> model.checked
-        is BaseUserRestricted -> stateOf(false)
+        is BaseUserRestricted -> ({ false })
         is BlockedByAdmin -> model.checked
     }
 
     override val changeable = when (restrictedMode) {
-        null -> stateOf(false)
+        null -> ({ false })
         is NoRestricted -> model.changeable
-        is BaseUserRestricted -> stateOf(false)
-        is BlockedByAdmin -> stateOf(false)
+        is BaseUserRestricted -> ({ false })
+        is BlockedByAdmin -> ({ false })
     }
 
     override val onCheckedChange = when (restrictedMode) {
@@ -137,7 +136,7 @@
                     onClick = { restrictedMode.sendShowAdminSupportDetailsIntent() },
                 )
                 .semantics {
-                    this.toggleableState = ToggleableState(checked.value)
+                    this.toggleableState = ToggleableState(checked())
                 },
         ) { content() }
     }
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListSwitchItemTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListSwitchItemTest.kt
index c29d7c2..73dd295 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListSwitchItemTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListSwitchItemTest.kt
@@ -27,7 +27,6 @@
 import androidx.compose.ui.test.onNodeWithText
 import androidx.compose.ui.test.performClick
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spaprivileged.model.app.AppRecord
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
@@ -43,8 +42,8 @@
     fun appLabel_displayed() {
         composeTestRule.setContent {
             ITEM_MODEL.AppListSwitchItem(
-                checked = stateOf(null),
-                changeable = stateOf(false),
+                checked = { null },
+                changeable = { false },
                 onCheckedChange = {},
             )
         }
@@ -56,8 +55,8 @@
     fun summary_displayed() {
         composeTestRule.setContent {
             ITEM_MODEL.AppListSwitchItem(
-                checked = stateOf(null),
-                changeable = stateOf(false),
+                checked = { null },
+                changeable = { false },
                 onCheckedChange = {},
             )
         }
@@ -69,8 +68,8 @@
     fun switch_checkIsNull() {
         composeTestRule.setContent {
             ITEM_MODEL.AppListSwitchItem(
-                checked = stateOf(null),
-                changeable = stateOf(false),
+                checked = { null },
+                changeable = { false },
                 onCheckedChange = {},
             )
         }
@@ -82,8 +81,8 @@
     fun switch_checked() {
         composeTestRule.setContent {
             ITEM_MODEL.AppListSwitchItem(
-                checked = stateOf(true),
-                changeable = stateOf(false),
+                checked = { true },
+                changeable = { false },
                 onCheckedChange = {},
             )
         }
@@ -95,8 +94,8 @@
     fun switch_notChecked() {
         composeTestRule.setContent {
             ITEM_MODEL.AppListSwitchItem(
-                checked = stateOf(false),
-                changeable = stateOf(false),
+                checked = { false },
+                changeable = { false },
                 onCheckedChange = {},
             )
         }
@@ -108,8 +107,8 @@
     fun switch_changeable() {
         composeTestRule.setContent {
             ITEM_MODEL.AppListSwitchItem(
-                checked = stateOf(false),
-                changeable = stateOf(true),
+                checked = { false },
+                changeable = { true },
                 onCheckedChange = {},
             )
         }
@@ -121,8 +120,8 @@
     fun switch_notChangeable() {
         composeTestRule.setContent {
             ITEM_MODEL.AppListSwitchItem(
-                checked = stateOf(false),
-                changeable = stateOf(false),
+                checked = { false },
+                changeable = { false },
                 onCheckedChange = {},
             )
         }
@@ -135,8 +134,8 @@
         var switchClicked = false
         composeTestRule.setContent {
             ITEM_MODEL.AppListSwitchItem(
-                checked = stateOf(false),
-                changeable = stateOf(true),
+                checked = { false },
+                changeable = { true },
                 onCheckedChange = { switchClicked = true },
             )
         }
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListTwoTargetSwitchItemTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListTwoTargetSwitchItemTest.kt
index 644a2d7..d3cfb2d 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListTwoTargetSwitchItemTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListTwoTargetSwitchItemTest.kt
@@ -27,7 +27,6 @@
 import androidx.compose.ui.test.onNodeWithText
 import androidx.compose.ui.test.performClick
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spaprivileged.model.app.AppRecord
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
@@ -44,8 +43,8 @@
         composeTestRule.setContent {
             ITEM_MODEL.AppListTwoTargetSwitchItem(
                 onClick = {},
-                checked = stateOf(null),
-                changeable = stateOf(false),
+                checked = { null },
+                changeable = { false },
                 onCheckedChange = {},
             )
         }
@@ -58,8 +57,8 @@
         composeTestRule.setContent {
             ITEM_MODEL.AppListTwoTargetSwitchItem(
                 onClick = {},
-                checked = stateOf(null),
-                changeable = stateOf(false),
+                checked = { null },
+                changeable = { false },
                 onCheckedChange = {},
             )
         }
@@ -73,8 +72,8 @@
         composeTestRule.setContent {
             ITEM_MODEL.AppListTwoTargetSwitchItem(
                 onClick = { titleClicked = true },
-                checked = stateOf(false),
-                changeable = stateOf(false),
+                checked = { false },
+                changeable = { false },
                 onCheckedChange = {},
             )
         }
@@ -89,8 +88,8 @@
         composeTestRule.setContent {
             ITEM_MODEL.AppListTwoTargetSwitchItem(
                 onClick = {},
-                checked = stateOf(null),
-                changeable = stateOf(false),
+                checked = { null },
+                changeable = { false },
                 onCheckedChange = {},
             )
         }
@@ -103,8 +102,8 @@
         composeTestRule.setContent {
             ITEM_MODEL.AppListTwoTargetSwitchItem(
                 onClick = {},
-                checked = stateOf(true),
-                changeable = stateOf(false),
+                checked = { true },
+                changeable = { false },
                 onCheckedChange = {},
             )
         }
@@ -117,8 +116,8 @@
         composeTestRule.setContent {
             ITEM_MODEL.AppListTwoTargetSwitchItem(
                 onClick = {},
-                checked = stateOf(false),
-                changeable = stateOf(false),
+                checked = { false },
+                changeable = { false },
                 onCheckedChange = {},
             )
         }
@@ -131,8 +130,8 @@
         composeTestRule.setContent {
             ITEM_MODEL.AppListTwoTargetSwitchItem(
                 onClick = {},
-                checked = stateOf(false),
-                changeable = stateOf(true),
+                checked = { false },
+                changeable = { true },
                 onCheckedChange = {},
             )
         }
@@ -145,8 +144,8 @@
         composeTestRule.setContent {
             ITEM_MODEL.AppListTwoTargetSwitchItem(
                 onClick = {},
-                checked = stateOf(false),
-                changeable = stateOf(false),
+                checked = { false },
+                changeable = { false },
                 onCheckedChange = {},
             )
         }
@@ -160,8 +159,8 @@
         composeTestRule.setContent {
             ITEM_MODEL.AppListTwoTargetSwitchItem(
                 onClick = {},
-                checked = stateOf(false),
-                changeable = stateOf(true),
+                checked = { false },
+                changeable = { true },
                 onCheckedChange = { switchClicked = true },
             )
         }
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppListTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppListTest.kt
index eb2055f..3b2fe0f 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppListTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppListTest.kt
@@ -20,7 +20,6 @@
 import android.content.Context
 import android.content.pm.ApplicationInfo
 import android.content.pm.PackageManager
-import androidx.compose.runtime.State
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.lifecycle.MutableLiveData
 import androidx.test.core.app.ApplicationProvider
@@ -307,9 +306,9 @@
     }
 
     private fun getIsAllowed(record: AppOpPermissionRecord): Boolean? {
-        lateinit var isAllowedState: State<Boolean?>
+        lateinit var isAllowedState: () -> Boolean?
         composeTestRule.setContent { isAllowedState = listModel.isAllowed(record) }
-        return isAllowedState.value
+        return isAllowedState()
     }
 
     private inner class TestAppOpPermissionAppListModel :
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreferenceTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreferenceTest.kt
index a13c483..00ba9b4 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreferenceTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreferenceTest.kt
@@ -49,8 +49,9 @@
 
     private val switchPreferenceModel = object : SwitchPreferenceModel {
         override val title = TITLE
-        override val checked = mutableStateOf(true)
-        override val onCheckedChange: (Boolean) -> Unit = { checked.value = it }
+        private val checkedState = mutableStateOf(true)
+        override val checked = { checkedState.value }
+        override val onCheckedChange: (Boolean) -> Unit = { checkedState.value = it }
     }
 
     @Test
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/tests/testutils/TestTogglePermissionAppListModel.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/tests/testutils/TestTogglePermissionAppListModel.kt
index 1bfc7ed..1790313 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/tests/testutils/TestTogglePermissionAppListModel.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/tests/testutils/TestTogglePermissionAppListModel.kt
@@ -18,7 +18,9 @@
 
 import android.content.pm.ApplicationInfo
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
 import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListModel
 import com.android.settingslib.spaprivileged.test.R
 import kotlinx.coroutines.flow.Flow
@@ -31,7 +33,7 @@
     override val switchTitleResId = R.string.test_permission_switch_title
     override val footerResId = R.string.test_permission_footer
 
-    private val isAllowedState = mutableStateOf(isAllowed)
+    private var isAllowed by mutableStateOf(isAllowed)
 
     override fun transformItem(app: ApplicationInfo) = TestAppRecord(app = app)
 
@@ -39,11 +41,11 @@
         recordListFlow
 
     @Composable
-    override fun isAllowed(record: TestAppRecord) = isAllowedState
+    override fun isAllowed(record: TestAppRecord) = { isAllowed }
 
     override fun isChangeable(record: TestAppRecord) = isChangeable
 
     override fun setAllowed(record: TestAppRecord, newAllowed: Boolean) {
-        isAllowedState.value = newAllowed
+        isAllowed = newAllowed
     }
 }