diff --git a/src/com/android/settings/network/apn/ApnEditPageProvider.kt b/src/com/android/settings/network/apn/ApnEditPageProvider.kt index 81da0bf022f..0ed54e7bfb8 100644 --- a/src/com/android/settings/network/apn/ApnEditPageProvider.kt +++ b/src/com/android/settings/network/apn/ApnEditPageProvider.kt @@ -38,7 +38,6 @@ import com.android.settings.R import com.android.settings.network.apn.ApnNetworkTypes.getNetworkTypeDisplayNames import com.android.settings.network.apn.ApnNetworkTypes.getNetworkTypeSelectedOptionsState import com.android.settingslib.spa.framework.common.SettingsPageProvider -import com.android.settingslib.spa.framework.compose.stateOf import com.android.settingslib.spa.widget.editor.SettingsExposedDropdownMenuBox import com.android.settingslib.spa.widget.editor.SettingsExposedDropdownMenuCheckBox import com.android.settingslib.spa.widget.editor.SettingsOutlinedTextField @@ -186,10 +185,8 @@ fun ApnPage(apnDataInit: ApnData, apnDataCur: MutableState, uriInit: Ur SwitchPreference( object : SwitchPreferenceModel { override val title = context.resources.getString(R.string.carrier_enabled) - override val changeable = - stateOf(apnData.apnEnableEnabled) - override val checked = - stateOf(apnData.apnEnable) + override val changeable = { apnData.apnEnableEnabled } + override val checked = { apnData.apnEnable } override val onCheckedChange = { newChecked: Boolean -> apnData = apnData.copy(apnEnable = newChecked) } diff --git a/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreference.kt b/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreference.kt index 77d68b5fe23..78ca15b92f7 100644 --- a/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreference.kt +++ b/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreference.kt @@ -28,7 +28,7 @@ import android.permission.PermissionControllerManager.HIBERNATION_ELIGIBILITY_UN import android.provider.DeviceConfig import android.provider.DeviceConfig.NAMESPACE_APP_HIBERNATION import androidx.compose.runtime.Composable -import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -56,18 +56,14 @@ fun HibernationSwitchPreference(app: ApplicationInfo) { val presenter = remember { HibernationSwitchPresenter(context, app) } if (!presenter.isAvailable()) return - val isEligibleState = presenter.isEligibleFlow.collectAsStateWithLifecycle(initialValue = false) + val isEligibleState by presenter.isEligibleFlow.collectAsStateWithLifecycle(initialValue = false) val isCheckedState = presenter.isCheckedFlow.collectAsStateWithLifecycle(initialValue = null) SwitchPreference(remember { object : SwitchPreferenceModel { override val title = context.getString(R.string.unused_apps_switch) override val summary = { context.getString(R.string.unused_apps_switch_summary) } - override val changeable = isEligibleState - - override val checked = derivedStateOf { - if (!changeable.value) false else isCheckedState.value - } - + override val changeable = { isEligibleState } + override val checked = { if (changeable()) isCheckedState.value else false } override val onCheckedChange = presenter::onCheckedChange } }) diff --git a/src/com/android/settings/spa/app/specialaccess/AlarmsAndRemindersAppList.kt b/src/com/android/settings/spa/app/specialaccess/AlarmsAndRemindersAppList.kt index c31eb7a6ebc..c99092720f0 100644 --- a/src/com/android/settings/spa/app/specialaccess/AlarmsAndRemindersAppList.kt +++ b/src/com/android/settings/spa/app/specialaccess/AlarmsAndRemindersAppList.kt @@ -24,10 +24,9 @@ import android.content.Context import android.content.pm.ApplicationInfo import android.os.PowerExemptionManager import androidx.compose.runtime.Composable -import androidx.compose.runtime.livedata.observeAsState import com.android.settings.overlay.FeatureFactory.Companion.featureFactory import com.android.settingslib.R -import com.android.settingslib.spa.framework.compose.stateOf +import com.android.settingslib.spa.livedata.observeAsCallback import com.android.settingslib.spaprivileged.model.app.AppRecord import com.android.settingslib.spaprivileged.model.app.IPackageManagers import com.android.settingslib.spaprivileged.model.app.PackageManagers @@ -79,9 +78,10 @@ class AlarmsAndRemindersAppListModel( } @Composable - override fun isAllowed(record: AlarmsAndRemindersAppRecord) = - if (record.isTrumped) stateOf(true) - else record.controller.isAllowed.observeAsState() + override fun isAllowed(record: AlarmsAndRemindersAppRecord): () -> Boolean? = when { + record.isTrumped -> ({ true }) + else -> record.controller.isAllowed.observeAsCallback() + } override fun isChangeable(record: AlarmsAndRemindersAppRecord) = record.isChangeable diff --git a/src/com/android/settings/spa/app/specialaccess/InstallUnknownApps.kt b/src/com/android/settings/spa/app/specialaccess/InstallUnknownApps.kt index c98b2ee7a03..7f63e3898cb 100644 --- a/src/com/android/settings/spa/app/specialaccess/InstallUnknownApps.kt +++ b/src/com/android/settings/spa/app/specialaccess/InstallUnknownApps.kt @@ -24,8 +24,8 @@ import android.content.Context import android.content.pm.ApplicationInfo import android.os.UserManager import androidx.compose.runtime.Composable -import androidx.compose.runtime.livedata.observeAsState import com.android.settings.R +import com.android.settingslib.spa.livedata.observeAsCallback import com.android.settingslib.spaprivileged.model.app.AppOpsController import com.android.settingslib.spaprivileged.model.app.AppRecord import com.android.settingslib.spaprivileged.model.app.userId @@ -79,7 +79,7 @@ class InstallUnknownAppsListModel(private val context: Context) : @Composable override fun isAllowed(record: InstallUnknownAppsRecord) = - record.appOpsController.isAllowed.observeAsState() + record.appOpsController.isAllowed.observeAsCallback() override fun isChangeable(record: InstallUnknownAppsRecord) = isChangeable(record, getPotentialPackageNames(record.app.userId)) diff --git a/src/com/android/settings/spa/app/specialaccess/NfcTagAppsSettings.kt b/src/com/android/settings/spa/app/specialaccess/NfcTagAppsSettings.kt index 3dede42a34d..f02a6a1181c 100644 --- a/src/com/android/settings/spa/app/specialaccess/NfcTagAppsSettings.kt +++ b/src/com/android/settings/spa/app/specialaccess/NfcTagAppsSettings.kt @@ -23,8 +23,8 @@ import android.content.pm.PackageManager.PackageInfoFlags import android.nfc.NfcAdapter import android.util.Log import androidx.compose.runtime.Composable -import androidx.compose.runtime.livedata.observeAsState import com.android.settings.R +import com.android.settingslib.spa.livedata.observeAsCallback import com.android.settingslib.spaprivileged.model.app.AppRecord import com.android.settingslib.spaprivileged.model.app.userId import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListModel @@ -100,7 +100,7 @@ class NfcTagAppsSettingsListModel(private val context: Context) : @Composable override fun isAllowed(record: NfcTagAppsSettingsRecord) = - record.controller.isAllowed.observeAsState() + record.controller.isAllowed.observeAsCallback() override fun isChangeable(record: NfcTagAppsSettingsRecord) = true diff --git a/src/com/android/settings/spa/app/specialaccess/PictureInPicture.kt b/src/com/android/settings/spa/app/specialaccess/PictureInPicture.kt index 5ed361560d7..cd615919fe3 100644 --- a/src/com/android/settings/spa/app/specialaccess/PictureInPicture.kt +++ b/src/com/android/settings/spa/app/specialaccess/PictureInPicture.kt @@ -25,8 +25,8 @@ import android.content.pm.PackageManager.GET_ACTIVITIES import android.content.pm.PackageManager.PackageInfoFlags import android.util.Log import androidx.compose.runtime.Composable -import androidx.compose.runtime.livedata.observeAsState import com.android.settings.R +import com.android.settingslib.spa.livedata.observeAsCallback import com.android.settingslib.spaprivileged.model.app.AppOpsController import com.android.settingslib.spaprivileged.model.app.AppRecord import com.android.settingslib.spaprivileged.model.app.installed @@ -90,7 +90,7 @@ class PictureInPictureListModel(private val context: Context) : @Composable override fun isAllowed(record: PictureInPictureRecord) = - record.appOpsController.isAllowed.observeAsState() + record.appOpsController.isAllowed.observeAsCallback() override fun isChangeable(record: PictureInPictureRecord) = record.isSupport diff --git a/src/com/android/settings/spa/network/AirplaneModePreference.kt b/src/com/android/settings/spa/network/AirplaneModePreference.kt index 462c1216ef9..27261b6b20a 100644 --- a/src/com/android/settings/spa/network/AirplaneModePreference.kt +++ b/src/com/android/settings/spa/network/AirplaneModePreference.kt @@ -20,8 +20,9 @@ import android.content.pm.PackageManager import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.AirplanemodeActive import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember +import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData @@ -37,11 +38,12 @@ fun AirplaneModePreference() { val context = LocalContext.current val controller = remember { AirplaneModeController(context) } if (!controller.isAvailable()) return + val checked by controller.airplaneModeState.observeAsState( + initial = controller.isAirplaneModeOn() + ) SwitchPreference(object : SwitchPreferenceModel { override val title = context.getString(R.string.airplane_mode) - override val checked = controller.airplaneModeState.observeAsState( - initial = controller.isAirplaneModeOn() - ) + override val checked = { checked } override val onCheckedChange = { newChecked: Boolean -> controller.setChecked(newChecked) } diff --git a/src/com/android/settings/spa/notification/AppNotificationsListModel.kt b/src/com/android/settings/spa/notification/AppNotificationsListModel.kt index 692ffcb85c1..2f3de3a099e 100644 --- a/src/com/android/settings/spa/notification/AppNotificationsListModel.kt +++ b/src/com/android/settings/spa/notification/AppNotificationsListModel.kt @@ -21,7 +21,7 @@ import android.content.Context import android.content.pm.ApplicationInfo import android.icu.text.RelativeDateTimeFormatter import androidx.compose.runtime.Composable -import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.runtime.getValue import androidx.compose.runtime.produceState import com.android.settings.R import com.android.settings.applications.AppInfoBase @@ -29,6 +29,7 @@ import com.android.settings.notification.app.AppNotificationSettings import com.android.settings.spa.notification.SpinnerItem.Companion.toSpinnerItem import com.android.settingslib.spa.framework.util.asyncFilter import com.android.settingslib.spa.framework.util.asyncForEach +import com.android.settingslib.spa.livedata.observeAsCallback import com.android.settingslib.spa.widget.ui.SpinnerOption import com.android.settingslib.spaprivileged.model.app.AppEntry import com.android.settingslib.spaprivileged.model.app.AppListModel @@ -36,9 +37,11 @@ import com.android.settingslib.spaprivileged.model.app.AppRecord import com.android.settingslib.spaprivileged.template.app.AppListItemModel import com.android.settingslib.spaprivileged.template.app.AppListTwoTargetSwitchItem import com.android.settingslib.utils.StringUtil +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map +import kotlinx.coroutines.withContext data class AppNotificationsRecord( override val app: ApplicationInfo, @@ -117,12 +120,15 @@ class AppNotificationsListModel( @Composable override fun AppListItemModel.AppItem() { + val changeable by produceState(initialValue = false) { + withContext(Dispatchers.Default) { + value = repository.isChangeable(record.app) + } + } AppListTwoTargetSwitchItem( onClick = { navigateToAppNotificationSettings(app = record.app) }, - checked = record.controller.isEnabled.observeAsState(), - changeable = produceState(initialValue = false) { - value = repository.isChangeable(record.app) - }, + checked = record.controller.isEnabled.observeAsCallback(), + changeable = { changeable }, onCheckedChange = record.controller::setEnabled, ) } diff --git a/tests/spa_unit/src/com/android/settings/spa/app/WifiControlAppListModelTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/WifiControlAppListModelTest.kt index c5c48f5b70a..74aa86175eb 100644 --- a/tests/spa_unit/src/com/android/settings/spa/app/WifiControlAppListModelTest.kt +++ b/tests/spa_unit/src/com/android/settings/spa/app/WifiControlAppListModelTest.kt @@ -18,11 +18,8 @@ package com.android.settings.spa.app.specialaccess import android.Manifest import android.app.AppOpsManager -import android.app.AppOpsManager.MODE_ALLOWED -import android.app.AppOpsManager.MODE_DEFAULT import android.content.Context import android.content.pm.ApplicationInfo -import androidx.compose.runtime.State import androidx.compose.ui.test.junit4.createComposeRule import androidx.lifecycle.MutableLiveData import androidx.test.core.app.ApplicationProvider @@ -40,9 +37,9 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock -import org.mockito.Mockito.`when` as whenever import org.mockito.junit.MockitoJUnit import org.mockito.junit.MockitoRule +import org.mockito.Mockito.`when` as whenever @ExperimentalCoroutinesApi @RunWith(AndroidJUnit4::class) @@ -248,9 +245,9 @@ class WifiControlAppListModelTest { } private fun getIsAllowed(record: AppOpPermissionRecord): Boolean? { - lateinit var isAllowedState: State + lateinit var isAllowedState: () -> Boolean? composeTestRule.setContent { isAllowedState = listModel.isAllowed(record) } - return isAllowedState.value + return isAllowedState() } private companion object {