[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,