diff --git a/res/values/strings.xml b/res/values/strings.xml index ac63cbff4f6..7b7dd196e91 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1868,6 +1868,8 @@ More settings Firmware updates, about, and more + + Tips & support Device\'s Bluetooth address: %1$s diff --git a/src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.kt b/src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.kt index 42287333f12..25c586e06bc 100644 --- a/src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.kt +++ b/src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.kt @@ -101,6 +101,12 @@ open class BluetoothFeatureProviderImpl : BluetoothFeatureProvider { bluetoothAdapter: BluetoothAdapter, cachedDevice: CachedBluetoothDevice ): DeviceDetailsFragmentFormatter { - return DeviceDetailsFragmentFormatterImpl(context, fragment, bluetoothAdapter, cachedDevice) + return DeviceDetailsFragmentFormatterImpl( + context, + fragment, + bluetoothAdapter, + cachedDevice, + Dispatchers.IO + ) } } diff --git a/src/com/android/settings/bluetooth/ui/model/DeviceSettingPreferenceModel.kt b/src/com/android/settings/bluetooth/ui/model/DeviceSettingPreferenceModel.kt index 6612591fce4..f6e6f168144 100644 --- a/src/com/android/settings/bluetooth/ui/model/DeviceSettingPreferenceModel.kt +++ b/src/com/android/settings/bluetooth/ui/model/DeviceSettingPreferenceModel.kt @@ -66,4 +66,11 @@ sealed interface DeviceSettingPreferenceModel { data class MoreSettingsPreference( @DeviceSettingId override val id: Int, ) : DeviceSettingPreferenceModel + + /** Models a help button on the top right corner of the fragment. */ + data class HelpPreference( + @DeviceSettingId override val id: Int, + val icon: DeviceSettingIcon, + val onClick: (() -> Unit), + ) : DeviceSettingPreferenceModel } diff --git a/src/com/android/settings/bluetooth/ui/view/DeviceDetailsFragmentFormatter.kt b/src/com/android/settings/bluetooth/ui/view/DeviceDetailsFragmentFormatter.kt index c933c754b7e..8f0bf3e9dc6 100644 --- a/src/com/android/settings/bluetooth/ui/view/DeviceDetailsFragmentFormatter.kt +++ b/src/com/android/settings/bluetooth/ui/view/DeviceDetailsFragmentFormatter.kt @@ -52,10 +52,15 @@ import com.android.settingslib.spa.widget.preference.SwitchPreference import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel import com.android.settingslib.spa.widget.preference.TwoTargetSwitchPreference import com.android.settingslib.spa.widget.ui.Footer +import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.emitAll import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.map import kotlinx.coroutines.runBlocking /** Handles device details fragment layout according to config. */ @@ -65,6 +70,11 @@ interface DeviceDetailsFragmentFormatter { /** Updates device details fragment layout. */ fun updateLayout(fragmentType: FragmentTypeModel) + + /** Gets the menu items of the fragment. */ + fun getMenuItem( + fragmentType: FragmentTypeModel + ): Flow } @OptIn(ExperimentalCoroutinesApi::class) @@ -72,7 +82,8 @@ class DeviceDetailsFragmentFormatterImpl( private val context: Context, private val fragment: SettingsPreferenceFragment, bluetoothAdapter: BluetoothAdapter, - private val cachedDevice: CachedBluetoothDevice + private val cachedDevice: CachedBluetoothDevice, + private val backgroundCoroutineContext: CoroutineContext, ) : DeviceDetailsFragmentFormatter { private val repository = featureFactory.bluetoothFeatureProvider.getDeviceSettingRepository( @@ -88,6 +99,7 @@ class DeviceDetailsFragmentFormatterImpl( repository, spatialAudioInteractor, cachedDevice, + backgroundCoroutineContext, )) .get(BluetoothDeviceDetailsViewModel::class.java) @@ -135,6 +147,19 @@ class DeviceDetailsFragmentFormatterImpl( fragment.preferenceScreen.addPreference(Preference(context).apply { order = 10000 }) } + override fun getMenuItem( + fragmentType: FragmentTypeModel + ): Flow = flow { + val t = viewModel.getHelpItem(fragmentType) + + t?.let { item -> + emitAll( + viewModel.getDeviceSetting(cachedDevice, item.settingId).map { + it as? DeviceSettingPreferenceModel.HelpPreference + }) + } ?: emit(null) + } + @Composable private fun buildPreference(layout: DeviceSettingLayout, row: Int) { val contents by @@ -174,6 +199,7 @@ class DeviceDetailsFragmentFormatterImpl( is DeviceSettingPreferenceModel.MoreSettingsPreference -> { buildMoreSettingsPreference() } + is DeviceSettingPreferenceModel.HelpPreference -> {} null -> {} } } diff --git a/src/com/android/settings/bluetooth/ui/view/DeviceDetailsMoreSettingsFragment.kt b/src/com/android/settings/bluetooth/ui/view/DeviceDetailsMoreSettingsFragment.kt index c648a3e9b43..f69f023d482 100644 --- a/src/com/android/settings/bluetooth/ui/view/DeviceDetailsMoreSettingsFragment.kt +++ b/src/com/android/settings/bluetooth/ui/view/DeviceDetailsMoreSettingsFragment.kt @@ -19,26 +19,65 @@ package com.android.settings.bluetooth.ui.view import android.bluetooth.BluetoothDevice import android.bluetooth.BluetoothManager import android.content.Context +import android.graphics.PorterDuff import android.os.Bundle +import android.view.Menu +import android.view.MenuInflater +import android.view.MenuItem +import androidx.lifecycle.lifecycleScope import com.android.settings.R import com.android.settings.bluetooth.BluetoothDetailsProfilesController import com.android.settings.bluetooth.Utils +import com.android.settings.bluetooth.ui.model.DeviceSettingPreferenceModel import com.android.settings.bluetooth.ui.model.FragmentTypeModel import com.android.settings.dashboard.DashboardFragment import com.android.settings.overlay.FeatureFactory.Companion.featureFactory import com.android.settingslib.bluetooth.CachedBluetoothDevice import com.android.settingslib.bluetooth.LocalBluetoothManager +import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingIcon import com.android.settingslib.core.AbstractPreferenceController import com.android.settingslib.core.lifecycle.LifecycleObserver +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.filterNotNull +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.launch class DeviceDetailsMoreSettingsFragment : DashboardFragment() { private lateinit var formatter: DeviceDetailsFragmentFormatter private lateinit var localBluetoothManager: LocalBluetoothManager private lateinit var cachedDevice: CachedBluetoothDevice + private lateinit var helpItem: StateFlow // TODO(b/343317785): add metrics category override fun getMetricsCategory(): Int = 0 + override fun onPrepareOptionsMenu(menu: Menu) { + super.onPrepareOptionsMenu(menu) + lifecycleScope.launch { + helpItem.filterNotNull().collect { item -> + val iconRes = item.icon as? DeviceSettingIcon.ResourceIcon ?: return@collect + val item: MenuItem = + menu.add(0, MENU_HELP_ITEM_ID, 0, R.string.bluetooth_device_tip_support) + item.setIcon(iconRes.resId) + item.icon?.setColorFilter( + resources.getColor( + com.android.settingslib.widget.theme.R.color + .settingslib_materialColorOnSurface), + PorterDuff.Mode.SRC_ATOP) + item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS) + } + } + } + + override fun onOptionsItemSelected(menuItem: MenuItem): Boolean { + if (menuItem.itemId == MENU_HELP_ITEM_ID) { + helpItem.value?.let { it.onClick() } + return true + } + return super.onOptionsItemSelected(menuItem) + } + override fun getPreferenceScreenResId(): Int { return R.xml.bluetooth_device_more_settings_fragment } @@ -78,6 +117,10 @@ class DeviceDetailsMoreSettingsFragment : DashboardFragment() { formatter = featureFactory.bluetoothFeatureProvider.getDeviceDetailsFragmentFormatter( requireContext(), this, bluetoothManager.adapter, cachedDevice) + helpItem = + formatter + .getMenuItem(FragmentTypeModel.DeviceDetailsMoreSettingsFragment) + .stateIn(lifecycleScope, SharingStarted.WhileSubscribed(), initialValue = null) return listOf( BluetoothDetailsProfilesController( context, this, localBluetoothManager, cachedDevice, settingsLifecycle)) @@ -88,5 +131,6 @@ class DeviceDetailsMoreSettingsFragment : DashboardFragment() { companion object { const val TAG: String = "DeviceMoreSettingsFrg" const val KEY_DEVICE_ADDRESS: String = "device_address" + const val MENU_HELP_ITEM_ID = Menu.FIRST } } diff --git a/src/com/android/settings/bluetooth/ui/viewmodel/BluetoothDeviceDetailsViewModel.kt b/src/com/android/settings/bluetooth/ui/viewmodel/BluetoothDeviceDetailsViewModel.kt index c85015cc71b..1071adce37f 100644 --- a/src/com/android/settings/bluetooth/ui/viewmodel/BluetoothDeviceDetailsViewModel.kt +++ b/src/com/android/settings/bluetooth/ui/viewmodel/BluetoothDeviceDetailsViewModel.kt @@ -21,6 +21,7 @@ import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope +import com.android.settings.R import com.android.settings.bluetooth.domain.interactor.SpatialAudioInteractor import com.android.settings.bluetooth.ui.layout.DeviceSettingLayout import com.android.settings.bluetooth.ui.layout.DeviceSettingLayoutRow @@ -30,8 +31,10 @@ import com.android.settingslib.bluetooth.CachedBluetoothDevice import com.android.settingslib.bluetooth.devicesettings.DeviceSettingId import com.android.settingslib.bluetooth.devicesettings.data.repository.DeviceSettingRepository import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigItemModel +import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingIcon import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingModel import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingStateModel +import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async @@ -47,10 +50,11 @@ class BluetoothDeviceDetailsViewModel( private val deviceSettingRepository: DeviceSettingRepository, private val spatialAudioInteractor: SpatialAudioInteractor, private val cachedDevice: CachedBluetoothDevice, + backgroundCoroutineContext: CoroutineContext, ) : AndroidViewModel(application){ private val items = - viewModelScope.async(Dispatchers.IO, start = CoroutineStart.LAZY) { + viewModelScope.async(backgroundCoroutineContext, start = CoroutineStart.LAZY) { deviceSettingRepository.getDeviceSettingsConfig(cachedDevice) } @@ -61,6 +65,13 @@ class BluetoothDeviceDetailsViewModel( items.await()?.moreSettingsItems } + suspend fun getHelpItem(fragment: FragmentTypeModel): DeviceSettingConfigItemModel? = + when (fragment) { + is FragmentTypeModel.DeviceDetailsMainFragment -> null + is FragmentTypeModel.DeviceDetailsMoreSettingsFragment -> + items.await()?.moreSettingsHelpItem + } + fun getDeviceSetting( cachedDevice: CachedBluetoothDevice, @DeviceSettingId settingId: Int @@ -101,6 +112,13 @@ class BluetoothDeviceDetailsViewModel( } is DeviceSettingModel.FooterPreference -> DeviceSettingPreferenceModel.FooterPreference(id = id, footerText = footerText) + is DeviceSettingModel.HelpPreference -> + DeviceSettingPreferenceModel.HelpPreference( + id = id, + icon = DeviceSettingIcon.ResourceIcon(R.drawable.ic_help), + onClick = { + application.startActivity(intent) + }) is DeviceSettingModel.MultiTogglePreference -> DeviceSettingPreferenceModel.MultiTogglePreference( id = id, @@ -163,11 +181,14 @@ class BluetoothDeviceDetailsViewModel( private val deviceSettingRepository: DeviceSettingRepository, private val spatialAudioInteractor: SpatialAudioInteractor, private val cachedDevice: CachedBluetoothDevice, + private val backgroundCoroutineContext: CoroutineContext, ) : ViewModelProvider.Factory { override fun create(modelClass: Class): T { @Suppress("UNCHECKED_CAST") return BluetoothDeviceDetailsViewModel( - application, deviceSettingRepository, spatialAudioInteractor, cachedDevice) + application, deviceSettingRepository, spatialAudioInteractor, + cachedDevice, + backgroundCoroutineContext) as T } } diff --git a/tests/robotests/src/com/android/settings/bluetooth/ui/view/DeviceDetailsFragmentFormatterTest.kt b/tests/robotests/src/com/android/settings/bluetooth/ui/view/DeviceDetailsFragmentFormatterTest.kt index 251b814f972..a5bc2463cdd 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/ui/view/DeviceDetailsFragmentFormatterTest.kt +++ b/tests/robotests/src/com/android/settings/bluetooth/ui/view/DeviceDetailsFragmentFormatterTest.kt @@ -18,14 +18,17 @@ package com.android.settings.bluetooth.ui.view import android.bluetooth.BluetoothAdapter import android.content.Context +import android.content.Intent import android.graphics.Bitmap import android.media.AudioManager +import android.net.Uri import androidx.fragment.app.FragmentActivity import androidx.preference.Preference import androidx.preference.PreferenceManager import androidx.preference.PreferenceScreen import androidx.test.core.app.ApplicationProvider import com.android.settings.bluetooth.domain.interactor.SpatialAudioInteractor +import com.android.settings.bluetooth.ui.model.DeviceSettingPreferenceModel import com.android.settings.bluetooth.ui.model.FragmentTypeModel import com.android.settings.dashboard.DashboardFragment import com.android.settings.testutils.FakeFeatureFactory @@ -39,8 +42,12 @@ import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSetti 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.delay import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Rule @@ -49,13 +56,17 @@ import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.eq import org.mockito.Mock import org.mockito.Mockito.any +import org.mockito.Mockito.verify import org.mockito.Mockito.`when` import org.mockito.junit.MockitoJUnit import org.mockito.junit.MockitoRule import org.robolectric.Robolectric import org.robolectric.RobolectricTestRunner +import org.robolectric.Shadows +import org.robolectric.shadows.ShadowLooper import org.robolectric.shadows.ShadowLooper.shadowMainLooper + @RunWith(RobolectricTestRunner::class) class DeviceDetailsFragmentFormatterTest { @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule() @@ -68,6 +79,7 @@ class DeviceDetailsFragmentFormatterTest { private lateinit var fragment: TestFragment private lateinit var underTest: DeviceDetailsFragmentFormatter private lateinit var featureFactory: FakeFeatureFactory + private lateinit var fragmentActivity: FragmentActivity private val testScope = TestScope() @Before @@ -79,10 +91,10 @@ class DeviceDetailsFragmentFormatterTest { eq(context), eq(bluetoothAdapter), any())) .thenReturn(repository) `when`( - featureFactory.bluetoothFeatureProvider.getSpatialAudioInteractor( - eq(context), any(AudioManager::class.java), any())) + featureFactory.bluetoothFeatureProvider.getSpatialAudioInteractor( + eq(context), any(AudioManager::class.java), any())) .thenReturn(spatialAudioInteractor) - val fragmentActivity = Robolectric.setupActivity(FragmentActivity::class.java) + fragmentActivity = Robolectric.setupActivity(FragmentActivity::class.java) assertThat(fragmentActivity.applicationContext).isNotNull() fragment = TestFragment(context) fragmentActivity.supportFragmentManager.beginTransaction().add(fragment, null).commit() @@ -95,7 +107,12 @@ class DeviceDetailsFragmentFormatterTest { } underTest = - DeviceDetailsFragmentFormatterImpl(context, fragment, bluetoothAdapter, cachedDevice) + DeviceDetailsFragmentFormatterImpl( + context, + fragment, + bluetoothAdapter, + cachedDevice, + testScope.testScheduler) } @Test @@ -111,9 +128,11 @@ class DeviceDetailsFragmentFormatterTest { DeviceSettingConfigItemModel.BuiltinItem( DeviceSettingId.DEVICE_SETTING_ID_ACTION_BUTTONS, "action_buttons"), ), - listOf())) + listOf(), + null)) - val keys = underTest.getVisiblePreferenceKeys(FragmentTypeModel.DeviceDetailsMainFragment) + val keys = + underTest.getVisiblePreferenceKeys(FragmentTypeModel.DeviceDetailsMainFragment) assertThat(keys).containsExactly("bluetooth_device_header", "action_buttons") } @@ -124,12 +143,47 @@ class DeviceDetailsFragmentFormatterTest { testScope.runTest { `when`(repository.getDeviceSettingsConfig(cachedDevice)).thenReturn(null) - val keys = underTest.getVisiblePreferenceKeys(FragmentTypeModel.DeviceDetailsMainFragment) + val keys = + underTest.getVisiblePreferenceKeys(FragmentTypeModel.DeviceDetailsMainFragment) assertThat(keys).isNull() } } + @Test + fun getMenuItem_returnItem() { + testScope.runTest { + `when`(repository.getDeviceSettingsConfig(cachedDevice)) + .thenReturn( + DeviceSettingConfigModel( + listOf(), listOf(), DeviceSettingConfigItemModel.AppProvidedItem(12345))) + val intent = Intent().apply { + setAction(Intent.ACTION_VIEW) + setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + `when`(repository.getDeviceSetting(cachedDevice, 12345)) + .thenReturn( + flowOf( + DeviceSettingModel.HelpPreference( + cachedDevice = cachedDevice, + id = 12345, + intent = intent, + ))) + + var helpPreference: DeviceSettingPreferenceModel.HelpPreference? = null + underTest.getMenuItem(FragmentTypeModel.DeviceDetailsMoreSettingsFragment).onEach { + helpPreference = it + }.launchIn(testScope.backgroundScope) + delay(100) + runCurrent() + helpPreference!!.onClick() + ShadowLooper.idleMainLooper() + + val shadowActivity = Shadows.shadowOf(fragmentActivity) + assertThat(shadowActivity.nextStartedActivity).isSameInstanceAs(intent) + } + } + @Test fun updateLayout_configIsNull_notChange() { testScope.runTest { @@ -156,7 +210,8 @@ class DeviceDetailsFragmentFormatterTest { DeviceSettingId.DEVICE_SETTING_ID_KEYBOARD_SETTINGS, "keyboard_settings"), ), - listOf())) + listOf(), + null)) underTest.updateLayout(FragmentTypeModel.DeviceDetailsMainFragment) @@ -181,7 +236,8 @@ class DeviceDetailsFragmentFormatterTest { DeviceSettingId.DEVICE_SETTING_ID_KEYBOARD_SETTINGS, "keyboard_settings"), ), - listOf())) + listOf(), + null)) `when`(repository.getDeviceSetting(cachedDevice, DeviceSettingId.DEVICE_SETTING_ID_ANC)) .thenReturn( flowOf( @@ -192,15 +248,9 @@ class DeviceDetailsFragmentFormatterTest { toggles = listOf( ToggleModel( - "", DeviceSettingIcon.BitmapIcon( - Bitmap.createBitmap( - 1, - 1, - Bitmap.Config.ARGB_8888 - ) - ) - ) - ), + "", + DeviceSettingIcon.BitmapIcon( + Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)))), isActive = true, state = DeviceSettingStateModel.MultiTogglePreferenceState(0), isAllowedChangingState = true, diff --git a/tests/robotests/src/com/android/settings/bluetooth/ui/viewmodel/BluetoothDeviceDetailsViewModelTest.kt b/tests/robotests/src/com/android/settings/bluetooth/ui/viewmodel/BluetoothDeviceDetailsViewModelTest.kt index 378f363f0dd..9cbe6e38736 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/ui/viewmodel/BluetoothDeviceDetailsViewModelTest.kt +++ b/tests/robotests/src/com/android/settings/bluetooth/ui/viewmodel/BluetoothDeviceDetailsViewModelTest.kt @@ -78,7 +78,11 @@ class BluetoothDeviceDetailsViewModelTest { underTest = BluetoothDeviceDetailsViewModel( - application, repository, spatialAudioInteractor, cachedDevice) + application, + repository, + spatialAudioInteractor, + cachedDevice, + testScope.testScheduler) } @Test @@ -87,7 +91,7 @@ class BluetoothDeviceDetailsViewModelTest { `when`(repository.getDeviceSettingsConfig(cachedDevice)) .thenReturn( DeviceSettingConfigModel( - listOf(BUILTIN_SETTING_ITEM_1, BUILDIN_SETTING_ITEM_2), listOf())) + listOf(BUILTIN_SETTING_ITEM_1, BUILDIN_SETTING_ITEM_2), listOf(), null)) val keys = underTest.getItems(FragmentTypeModel.DeviceDetailsMainFragment) @@ -95,6 +99,38 @@ class BluetoothDeviceDetailsViewModelTest { } } + @Test + fun getHelpItems_mainPage_returnNull() { + testScope.runTest { + `when`(repository.getDeviceSettingsConfig(cachedDevice)) + .thenReturn( + DeviceSettingConfigModel( + listOf(BUILTIN_SETTING_ITEM_1, BUILDIN_SETTING_ITEM_2), + listOf(), + SETTING_ITEM_HELP)) + + val item = underTest.getHelpItem(FragmentTypeModel.DeviceDetailsMainFragment) + + assertThat(item).isNull() + } + } + + @Test + fun getHelpItems_moreSettings_returnConfigHelpItem() { + testScope.runTest { + `when`(repository.getDeviceSettingsConfig(cachedDevice)) + .thenReturn( + DeviceSettingConfigModel( + listOf(BUILTIN_SETTING_ITEM_1, BUILDIN_SETTING_ITEM_2), + listOf(), + SETTING_ITEM_HELP)) + + val item = underTest.getHelpItem(FragmentTypeModel.DeviceDetailsMoreSettingsFragment) + + assertThat(item).isSameInstanceAs(SETTING_ITEM_HELP) + } + } + @Test fun getDeviceSetting_returnRepositoryResponse() { testScope.runTest { @@ -107,7 +143,8 @@ class BluetoothDeviceDetailsViewModelTest { BUILTIN_SETTING_ITEM_1, buildRemoteSettingItem(remoteSettingId1), ), - listOf())) + listOf(), + null)) `when`(repository.getDeviceSetting(cachedDevice, remoteSettingId1)) .thenReturn(flowOf(pref)) @@ -137,7 +174,8 @@ class BluetoothDeviceDetailsViewModelTest { buildRemoteSettingItem( DeviceSettingId.DEVICE_SETTING_ID_SPATIAL_AUDIO_MULTI_TOGGLE), ), - listOf())) + listOf(), + null)) `when`(spatialAudioInteractor.getDeviceSetting(cachedDevice)).thenReturn(flowOf(pref)) var deviceSettingPreference: DeviceSettingPreferenceModel? = null @@ -159,7 +197,7 @@ class BluetoothDeviceDetailsViewModelTest { `when`(repository.getDeviceSettingsConfig(cachedDevice)) .thenReturn( DeviceSettingConfigModel( - listOf(BUILTIN_SETTING_ITEM_1, BUILDIN_SETTING_ITEM_2), listOf())) + listOf(BUILTIN_SETTING_ITEM_1, BUILDIN_SETTING_ITEM_2), listOf(), null)) val layout = underTest.getLayout(FragmentTypeModel.DeviceDetailsMainFragment)!! @@ -186,7 +224,8 @@ class BluetoothDeviceDetailsViewModelTest { buildRemoteSettingItem(remoteSettingId2), buildRemoteSettingItem(remoteSettingId3), ), - listOf())) + listOf(), + null)) `when`(repository.getDeviceSetting(cachedDevice, remoteSettingId1)) .thenReturn(flowOf(buildMultiTogglePreference(remoteSettingId1))) `when`(repository.getDeviceSetting(cachedDevice, remoteSettingId2)) @@ -248,5 +287,6 @@ class BluetoothDeviceDetailsViewModelTest { val BUILDIN_SETTING_ITEM_2 = DeviceSettingConfigItemModel.BuiltinItem( DeviceSettingId.DEVICE_SETTING_ID_ACTION_BUTTONS, "action_buttons") + val SETTING_ITEM_HELP = DeviceSettingConfigItemModel.AppProvidedItem(12345) } }