Refactor data layer of device details page

1. Consolidate repository layer api
2. Use shared model in repository response

BUG: 343317785
Test: atest DeviceSettingRepositoryTest
Flag: com.android.settings.flags.enable_bluetooth_device_details_polish
Change-Id: I3d90dd9695868743f4c7656a4e838e85a7918319
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepository.kt b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepository.kt
index 9ff5c43..326bb31 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepository.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepository.kt
@@ -19,37 +19,39 @@
 import android.bluetooth.BluetoothAdapter
 import android.content.Context
 import com.android.settingslib.bluetooth.CachedBluetoothDevice
+import com.android.settingslib.bluetooth.devicesettings.ActionSwitchPreference
 import com.android.settingslib.bluetooth.devicesettings.DeviceSetting
 import com.android.settingslib.bluetooth.devicesettings.DeviceSettingId
-import com.android.settingslib.bluetooth.devicesettings.DeviceSettingPreferenceState
+import com.android.settingslib.bluetooth.devicesettings.DeviceSettingItem
 import com.android.settingslib.bluetooth.devicesettings.DeviceSettingsConfig
-import java.util.concurrent.ConcurrentHashMap
+import com.android.settingslib.bluetooth.devicesettings.MultiTogglePreference
+import com.android.settingslib.bluetooth.devicesettings.ToggleInfo
+import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigItemModel
+import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigModel
+import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingModel
+import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingStateModel
+import com.android.settingslib.bluetooth.devicesettings.shared.model.ToggleModel
+import com.google.common.cache.CacheBuilder
+import com.google.common.cache.CacheLoader
+import com.google.common.cache.LoadingCache
 import kotlin.coroutines.CoroutineContext
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.launch
 
 /** Provides functionality to control bluetooth device settings. */
 interface DeviceSettingRepository {
     /** Gets config for the bluetooth device, returns null if failed. */
-    suspend fun getDeviceSettingsConfig(cachedDevice: CachedBluetoothDevice): DeviceSettingsConfig?
-
-    /** Gets all device settings for the bluetooth device. */
-    fun getDeviceSettingList(
-        cachedDevice: CachedBluetoothDevice,
-    ): Flow<List<DeviceSetting>?>
+    suspend fun getDeviceSettingsConfig(
+        cachedDevice: CachedBluetoothDevice
+    ): DeviceSettingConfigModel?
 
     /** Gets device setting for the bluetooth device. */
     fun getDeviceSetting(
         cachedDevice: CachedBluetoothDevice,
         @DeviceSettingId settingId: Int
-    ): Flow<DeviceSetting?>
-
-    /** Updates device setting for the bluetooth device. */
-    suspend fun updateDeviceSettingState(
-        cachedDevice: CachedBluetoothDevice,
-        @DeviceSettingId deviceSettingId: Int,
-        deviceSettingPreferenceState: DeviceSettingPreferenceState,
-    )
+    ): Flow<DeviceSettingModel?>
 }
 
 class DeviceSettingRepositoryImpl(
@@ -58,40 +60,94 @@
     private val coroutineScope: CoroutineScope,
     private val backgroundCoroutineContext: CoroutineContext,
 ) : DeviceSettingRepository {
-    private val deviceSettings =
-        ConcurrentHashMap<CachedBluetoothDevice, DeviceSettingServiceConnection>()
+    private val connectionCache:
+        LoadingCache<CachedBluetoothDevice, DeviceSettingServiceConnection> =
+        CacheBuilder.newBuilder()
+            .weakValues()
+            .build(
+                object : CacheLoader<CachedBluetoothDevice, DeviceSettingServiceConnection>() {
+                    override fun load(
+                        cachedDevice: CachedBluetoothDevice
+                    ): DeviceSettingServiceConnection =
+                        DeviceSettingServiceConnection(
+                            cachedDevice,
+                            context,
+                            bluetoothAdaptor,
+                            coroutineScope,
+                            backgroundCoroutineContext,
+                        )
+                }
+            )
 
     override suspend fun getDeviceSettingsConfig(
         cachedDevice: CachedBluetoothDevice
-    ): DeviceSettingsConfig? = createConnectionIfAbsent(cachedDevice).getDeviceSettingsConfig()
-
-    override fun getDeviceSettingList(
-        cachedDevice: CachedBluetoothDevice
-    ): Flow<List<DeviceSetting>?> = createConnectionIfAbsent(cachedDevice).getDeviceSettingList()
+    ): DeviceSettingConfigModel? =
+        connectionCache.get(cachedDevice).getDeviceSettingsConfig()?.toModel()
 
     override fun getDeviceSetting(
         cachedDevice: CachedBluetoothDevice,
         settingId: Int
-    ): Flow<DeviceSetting?> = createConnectionIfAbsent(cachedDevice).getDeviceSetting(settingId)
-
-    override suspend fun updateDeviceSettingState(
-        cachedDevice: CachedBluetoothDevice,
-        @DeviceSettingId deviceSettingId: Int,
-        deviceSettingPreferenceState: DeviceSettingPreferenceState,
-    ) =
-        createConnectionIfAbsent(cachedDevice)
-            .updateDeviceSettings(deviceSettingId, deviceSettingPreferenceState)
-
-    private fun createConnectionIfAbsent(
-        cachedDevice: CachedBluetoothDevice
-    ): DeviceSettingServiceConnection =
-        deviceSettings.computeIfAbsent(cachedDevice) {
-            DeviceSettingServiceConnection(
-                cachedDevice,
-                context,
-                bluetoothAdaptor,
-                coroutineScope,
-                backgroundCoroutineContext,
-            )
+    ): Flow<DeviceSettingModel?> =
+        connectionCache.get(cachedDevice).let { connection ->
+            connection.getDeviceSetting(settingId).map { it?.toModel(cachedDevice, connection) }
         }
+
+    private fun DeviceSettingsConfig.toModel(): DeviceSettingConfigModel =
+        DeviceSettingConfigModel(
+            mainItems = mainContentItems.map { it.toModel() },
+            moreSettingsItems = moreSettingsItems.map { it.toModel() },
+            moreSettingsPageFooter = moreSettingsFooter
+        )
+
+    private fun DeviceSettingItem.toModel(): DeviceSettingConfigItemModel =
+        DeviceSettingConfigItemModel(settingId)
+
+    private fun DeviceSetting.toModel(
+        cachedDevice: CachedBluetoothDevice,
+        connection: DeviceSettingServiceConnection
+    ): DeviceSettingModel =
+        when (val pref = preference) {
+            is ActionSwitchPreference ->
+                DeviceSettingModel.ActionSwitchPreference(
+                    cachedDevice = cachedDevice,
+                    id = settingId,
+                    title = pref.title,
+                    summary = pref.summary,
+                    icon = pref.icon,
+                    isAllowedChangingState = pref.isAllowedChangingState,
+                    intent = pref.intent,
+                    switchState =
+                        if (pref.hasSwitch()) {
+                            DeviceSettingStateModel.ActionSwitchPreferenceState(pref.checked)
+                        } else {
+                            null
+                        },
+                    updateState = { newState ->
+                        coroutineScope.launch(backgroundCoroutineContext) {
+                            connection.updateDeviceSettings(
+                                settingId,
+                                newState.toParcelable(),
+                            )
+                        }
+                    },
+                )
+            is MultiTogglePreference ->
+                DeviceSettingModel.MultiTogglePreference(
+                    cachedDevice = cachedDevice,
+                    id = settingId,
+                    title = pref.title,
+                    toggles = pref.toggleInfos.map { it.toModel() },
+                    isAllowedChangingState = pref.isAllowedChangingState,
+                    isActive = true,
+                    state = DeviceSettingStateModel.MultiTogglePreferenceState(pref.state),
+                    updateState = { newState ->
+                        coroutineScope.launch(backgroundCoroutineContext) {
+                            connection.updateDeviceSettings(settingId, newState.toParcelable())
+                        }
+                    },
+                )
+            else -> DeviceSettingModel.Unknown(cachedDevice, settingId)
+        }
+
+    private fun ToggleInfo.toModel(): ToggleModel = ToggleModel(label, icon)
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingConfigModel.kt b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingConfigModel.kt
new file mode 100644
index 0000000..cd597ee
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingConfigModel.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 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.bluetooth.devicesettings.shared.model
+
+import com.android.settingslib.bluetooth.devicesettings.DeviceSettingId
+
+/** Models a device setting config. */
+data class DeviceSettingConfigModel(
+    /** Items need to be shown in device details main page. */
+    val mainItems: List<DeviceSettingConfigItemModel>,
+    /** Items need to be shown in device details more settings page. */
+    val moreSettingsItems: List<DeviceSettingConfigItemModel>,
+    /** Footer text in more settings page. */
+    val moreSettingsPageFooter: String)
+
+/** Models a device setting item in config. */
+data class DeviceSettingConfigItemModel(
+    @DeviceSettingId val settingId: Int,
+)
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepositoryTest.kt b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepositoryTest.kt
index b5457c5..fee2394 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepositoryTest.kt
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepositoryTest.kt
@@ -22,6 +22,7 @@
 import android.content.Context
 import android.content.Intent
 import android.content.ServiceConnection
+import android.graphics.Bitmap
 import com.android.settingslib.bluetooth.CachedBluetoothDevice
 import com.android.settingslib.bluetooth.devicesettings.ActionSwitchPreference
 import com.android.settingslib.bluetooth.devicesettings.ActionSwitchPreferenceState
@@ -34,6 +35,14 @@
 import com.android.settingslib.bluetooth.devicesettings.IDeviceSettingsConfigProviderService
 import com.android.settingslib.bluetooth.devicesettings.IDeviceSettingsListener
 import com.android.settingslib.bluetooth.devicesettings.IDeviceSettingsProviderService
+import com.android.settingslib.bluetooth.devicesettings.MultiTogglePreference
+import com.android.settingslib.bluetooth.devicesettings.MultiTogglePreferenceState
+import com.android.settingslib.bluetooth.devicesettings.ToggleInfo
+import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigItemModel
+import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigModel
+import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingModel
+import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingStateModel
+import com.android.settingslib.bluetooth.devicesettings.shared.model.ToggleModel
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.delay
@@ -148,7 +157,7 @@
 
             val config = underTest.getDeviceSettingsConfig(cachedDevice)
 
-            assertThat(config).isSameInstanceAs(DEVICE_SETTING_CONFIG)
+            assertConfig(config!!, DEVICE_SETTING_CONFIG)
         }
     }
 
@@ -163,7 +172,7 @@
                 )
                 .thenReturn("".toByteArray())
 
-            var config: DeviceSettingsConfig? = null
+            var config: DeviceSettingConfigModel? = null
             val job = launch { config = underTest.getDeviceSettingsConfig(cachedDevice) }
             delay(1000)
             verify(bluetoothAdapter)
@@ -185,7 +194,7 @@
                 .thenReturn(BLUETOOTH_DEVICE_METADATA.toByteArray())
 
             job.join()
-            assertThat(config).isSameInstanceAs(DEVICE_SETTING_CONFIG)
+            assertConfig(config!!, DEVICE_SETTING_CONFIG)
         }
     }
 
@@ -202,7 +211,7 @@
     }
 
     @Test
-    fun getDeviceSettingList_success() {
+    fun getDeviceSetting_actionSwitchPreference_success() {
         testScope.runTest {
             `when`(configService.getDeviceSettingsConfig(any())).thenReturn(DEVICE_SETTING_CONFIG)
             `when`(settingProviderService1.registerDeviceSettingsListener(any(), any())).then {
@@ -211,73 +220,7 @@
                     .getArgument<IDeviceSettingsListener>(1)
                     .onDeviceSettingsChanged(listOf(DEVICE_SETTING_1))
             }
-            `when`(settingProviderService2.registerDeviceSettingsListener(any(), any())).then {
-                input ->
-                input
-                    .getArgument<IDeviceSettingsListener>(1)
-                    .onDeviceSettingsChanged(listOf(DEVICE_SETTING_2))
-            }
-            var settings: List<DeviceSetting>? = null
-
-            underTest
-                .getDeviceSettingList(cachedDevice)
-                .onEach { settings = it }
-                .launchIn(backgroundScope)
-            runCurrent()
-
-            assertThat(settings?.map { it.settingId })
-                .containsExactly(
-                    DeviceSettingId.DEVICE_SETTING_ID_HEADER,
-                    DeviceSettingId.DEVICE_SETTING_ID_ANC
-                )
-            assertThat(settings?.map { (it.preference as ActionSwitchPreference).title })
-                .containsExactly(
-                    "title1",
-                    "title2",
-                )
-        }
-    }
-
-    @Test
-    fun getDeviceSetting_oneServiceFailed_returnPartialResult() {
-        testScope.runTest {
-            `when`(configService.getDeviceSettingsConfig(any())).thenReturn(DEVICE_SETTING_CONFIG)
-            `when`(settingProviderService1.registerDeviceSettingsListener(any(), any())).then {
-                input ->
-                input
-                    .getArgument<IDeviceSettingsListener>(1)
-                    .onDeviceSettingsChanged(listOf(DEVICE_SETTING_1))
-            }
-            var settings: List<DeviceSetting>? = null
-
-            underTest
-                .getDeviceSettingList(cachedDevice)
-                .onEach { settings = it }
-                .launchIn(backgroundScope)
-            runCurrent()
-
-            assertThat(settings?.map { it.settingId })
-                .containsExactly(
-                    DeviceSettingId.DEVICE_SETTING_ID_HEADER,
-                )
-            assertThat(settings?.map { (it.preference as ActionSwitchPreference).title })
-                .containsExactly(
-                    "title1",
-                )
-        }
-    }
-
-    @Test
-    fun getDeviceSetting_success() {
-        testScope.runTest {
-            `when`(configService.getDeviceSettingsConfig(any())).thenReturn(DEVICE_SETTING_CONFIG)
-            `when`(settingProviderService1.registerDeviceSettingsListener(any(), any())).then {
-                input ->
-                input
-                    .getArgument<IDeviceSettingsListener>(1)
-                    .onDeviceSettingsChanged(listOf(DEVICE_SETTING_1))
-            }
-            var setting: DeviceSetting? = null
+            var setting: DeviceSettingModel? = null
 
             underTest
                 .getDeviceSetting(cachedDevice, DeviceSettingId.DEVICE_SETTING_ID_HEADER)
@@ -285,13 +228,55 @@
                 .launchIn(backgroundScope)
             runCurrent()
 
-            assertThat(setting?.settingId).isEqualTo(DeviceSettingId.DEVICE_SETTING_ID_HEADER)
-            assertThat((setting?.preference as ActionSwitchPreference).title).isEqualTo("title1")
+            assertDeviceSetting(setting!!, DEVICE_SETTING_1)
         }
     }
 
     @Test
-    fun updateDeviceSetting_success() {
+    fun getDeviceSetting_multiTogglePreference_success() {
+        testScope.runTest {
+            `when`(configService.getDeviceSettingsConfig(any())).thenReturn(DEVICE_SETTING_CONFIG)
+            `when`(settingProviderService2.registerDeviceSettingsListener(any(), any())).then {
+                input ->
+                input
+                    .getArgument<IDeviceSettingsListener>(1)
+                    .onDeviceSettingsChanged(listOf(DEVICE_SETTING_2))
+            }
+            var setting: DeviceSettingModel? = null
+
+            underTest
+                .getDeviceSetting(cachedDevice, DeviceSettingId.DEVICE_SETTING_ID_ANC)
+                .onEach { setting = it }
+                .launchIn(backgroundScope)
+            runCurrent()
+
+            assertDeviceSetting(setting!!, DEVICE_SETTING_2)
+        }
+    }
+
+    @Test
+    fun getDeviceSetting_noConfig_returnNull() {
+        testScope.runTest {
+            `when`(settingProviderService1.registerDeviceSettingsListener(any(), any())).then {
+                input ->
+                input
+                    .getArgument<IDeviceSettingsListener>(1)
+                    .onDeviceSettingsChanged(listOf(DEVICE_SETTING_1))
+            }
+            var setting: DeviceSettingModel? = null
+
+            underTest
+                .getDeviceSetting(cachedDevice, DeviceSettingId.DEVICE_SETTING_ID_HEADER)
+                .onEach { setting = it }
+                .launchIn(backgroundScope)
+            runCurrent()
+
+            assertThat(setting).isNull()
+        }
+    }
+
+    @Test
+    fun updateDeviceSettingState_switchState_success() {
         testScope.runTest {
             `when`(configService.getDeviceSettingsConfig(any())).thenReturn(DEVICE_SETTING_CONFIG)
             `when`(settingProviderService1.registerDeviceSettingsListener(any(), any())).then {
@@ -300,12 +285,15 @@
                     .getArgument<IDeviceSettingsListener>(1)
                     .onDeviceSettingsChanged(listOf(DEVICE_SETTING_1))
             }
+            var setting: DeviceSettingModel? = null
 
-            underTest.updateDeviceSettingState(
-                cachedDevice,
-                DeviceSettingId.DEVICE_SETTING_ID_HEADER,
-                ActionSwitchPreferenceState.Builder().build()
-            )
+            underTest
+                .getDeviceSetting(cachedDevice, DeviceSettingId.DEVICE_SETTING_ID_HEADER)
+                .onEach { setting = it }
+                .launchIn(backgroundScope)
+            runCurrent()
+            val updateFunc = (setting as DeviceSettingModel.ActionSwitchPreference).updateState!!
+            updateFunc(DeviceSettingStateModel.ActionSwitchPreferenceState(false))
             runCurrent()
 
             verify(settingProviderService1)
@@ -313,12 +301,107 @@
                     DEVICE_INFO,
                     DeviceSettingState.Builder()
                         .setSettingId(DeviceSettingId.DEVICE_SETTING_ID_HEADER)
-                        .setPreferenceState(ActionSwitchPreferenceState.Builder().build())
+                        .setPreferenceState(
+                            ActionSwitchPreferenceState.Builder().setChecked(false).build()
+                        )
                         .build()
                 )
         }
     }
 
+    @Test
+    fun updateDeviceSettingState_multiToggleState_success() {
+        testScope.runTest {
+            `when`(configService.getDeviceSettingsConfig(any())).thenReturn(DEVICE_SETTING_CONFIG)
+            `when`(settingProviderService2.registerDeviceSettingsListener(any(), any())).then {
+                input ->
+                input
+                    .getArgument<IDeviceSettingsListener>(1)
+                    .onDeviceSettingsChanged(listOf(DEVICE_SETTING_2))
+            }
+            var setting: DeviceSettingModel? = null
+
+            underTest
+                .getDeviceSetting(cachedDevice, DeviceSettingId.DEVICE_SETTING_ID_ANC)
+                .onEach { setting = it }
+                .launchIn(backgroundScope)
+            runCurrent()
+            val updateFunc = (setting as DeviceSettingModel.MultiTogglePreference).updateState
+            updateFunc(DeviceSettingStateModel.MultiTogglePreferenceState(2))
+            runCurrent()
+
+            verify(settingProviderService2)
+                .updateDeviceSettings(
+                    DEVICE_INFO,
+                    DeviceSettingState.Builder()
+                        .setSettingId(DeviceSettingId.DEVICE_SETTING_ID_ANC)
+                        .setPreferenceState(
+                            MultiTogglePreferenceState.Builder().setState(2).build()
+                        )
+                        .build()
+                )
+        }
+    }
+
+    private fun assertDeviceSetting(actual: DeviceSettingModel, serviceResponse: DeviceSetting) {
+        assertThat(actual.id).isEqualTo(serviceResponse.settingId)
+        when (actual) {
+            is DeviceSettingModel.ActionSwitchPreference -> {
+                assertThat(serviceResponse.preference)
+                    .isInstanceOf(ActionSwitchPreference::class.java)
+                val pref = serviceResponse.preference as ActionSwitchPreference
+                assertThat(actual.title).isEqualTo(pref.title)
+                assertThat(actual.summary).isEqualTo(pref.summary)
+                assertThat(actual.icon).isEqualTo(pref.icon)
+                assertThat(actual.isAllowedChangingState).isEqualTo(pref.isAllowedChangingState)
+                if (pref.hasSwitch()) {
+                    assertThat(actual.switchState!!.checked).isEqualTo(pref.checked)
+                } else {
+                    assertThat(actual.switchState).isNull()
+                }
+            }
+            is DeviceSettingModel.MultiTogglePreference -> {
+                assertThat(serviceResponse.preference)
+                    .isInstanceOf(MultiTogglePreference::class.java)
+                val pref = serviceResponse.preference as MultiTogglePreference
+                assertThat(actual.title).isEqualTo(pref.title)
+                assertThat(actual.isAllowedChangingState).isEqualTo(pref.isAllowedChangingState)
+                assertThat(actual.toggles.size).isEqualTo(pref.toggleInfos.size)
+                for (i in 0..<actual.toggles.size) {
+                    assertToggle(actual.toggles[i], pref.toggleInfos[i])
+                }
+            }
+            else -> {}
+        }
+    }
+
+    private fun assertToggle(actual: ToggleModel, serviceResponse: ToggleInfo) {
+        assertThat(actual.label).isEqualTo(serviceResponse.label)
+        assertThat(actual.icon).isEqualTo(serviceResponse.icon)
+    }
+
+    private fun assertConfig(
+        actual: DeviceSettingConfigModel,
+        serviceResponse: DeviceSettingsConfig
+    ) {
+        assertThat(actual.mainItems.size).isEqualTo(serviceResponse.mainContentItems.size)
+        for (i in 0..<actual.mainItems.size) {
+            assertConfigItem(actual.mainItems[i], serviceResponse.mainContentItems[i])
+        }
+        assertThat(actual.moreSettingsItems.size).isEqualTo(serviceResponse.moreSettingsItems.size)
+        for (i in 0..<actual.moreSettingsItems.size) {
+            assertConfigItem(actual.moreSettingsItems[i], serviceResponse.moreSettingsItems[i])
+        }
+        assertThat(actual.moreSettingsPageFooter).isEqualTo(serviceResponse.moreSettingsFooter)
+    }
+
+    private fun assertConfigItem(
+        actual: DeviceSettingConfigItemModel,
+        serviceResponse: DeviceSettingItem
+    ) {
+        assertThat(actual.settingId).isEqualTo(serviceResponse.settingId)
+    }
+
     private companion object {
         const val BLUETOOTH_ADDRESS = "12:34:56:78"
         const val CONFIG_SERVICE_PACKAGE_NAME = "com.android.fake.configservice"
@@ -377,10 +460,21 @@
             DeviceSetting.Builder()
                 .setSettingId(DeviceSettingId.DEVICE_SETTING_ID_ANC)
                 .setPreference(
-                    ActionSwitchPreference.Builder()
-                        .setTitle("title2")
-                        .setHasSwitch(true)
-                        .setAllowedChangingState(true)
+                    MultiTogglePreference.Builder()
+                        .setTitle("title1")
+                        .setAllowChangingState(true)
+                        .addToggleInfo(
+                            ToggleInfo.Builder()
+                                .setLabel("label1")
+                                .setIcon(Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888))
+                                .build()
+                        )
+                        .addToggleInfo(
+                            ToggleInfo.Builder()
+                                .setLabel("label2")
+                                .setIcon(Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888))
+                                .build()
+                        )
                         .build()
                 )
                 .build()