Reimplement device details UI without ComposePreference
Replace ComposePreference with androidx.preference.Preference. ANC toggle will still use Compose until SegmentedButtonPreference is ready. BUG: 402036473 Test: local tested Flag: com.android.settings.flags.enable_bluetooth_device_details_polish Change-Id: I5114af8f2d679d695b3c5ef4d7be2874245c435e
This commit is contained in:
@@ -16,7 +16,7 @@
|
||||
|
||||
package com.android.settings.bluetooth.ui.view
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.app.settings.SettingsEnums
|
||||
import android.bluetooth.BluetoothAdapter
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
@@ -25,6 +25,7 @@ import androidx.fragment.app.FragmentActivity
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.preference.PreferenceScreen
|
||||
import androidx.preference.SwitchPreferenceCompat
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import com.android.settings.bluetooth.ui.model.DeviceSettingPreferenceModel
|
||||
import com.android.settings.bluetooth.ui.model.FragmentTypeModel
|
||||
@@ -33,6 +34,7 @@ import com.android.settings.testutils.FakeFeatureFactory
|
||||
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.DeviceSettingActionModel
|
||||
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.DeviceSettingIcon
|
||||
@@ -58,14 +60,15 @@ import org.mockito.Mock
|
||||
import org.mockito.Mockito.any
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.Mockito.`when`
|
||||
import org.mockito.Spy
|
||||
import org.mockito.junit.MockitoJUnit
|
||||
import org.mockito.junit.MockitoRule
|
||||
import org.mockito.kotlin.doNothing
|
||||
import org.robolectric.Robolectric
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.shadows.ShadowLooper
|
||||
import org.robolectric.shadows.ShadowLooper.shadowMainLooper
|
||||
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
class DeviceDetailsFragmentFormatterTest {
|
||||
@@ -78,7 +81,7 @@ class DeviceDetailsFragmentFormatterTest {
|
||||
@Mock private lateinit var headerController: AbstractPreferenceController
|
||||
@Mock private lateinit var buttonController: AbstractPreferenceController
|
||||
|
||||
private lateinit var context: Context
|
||||
@Spy private val context: Context = ApplicationProvider.getApplicationContext()
|
||||
private lateinit var fragment: TestFragment
|
||||
private lateinit var underTest: DeviceDetailsFragmentFormatter
|
||||
private lateinit var featureFactory: FakeFeatureFactory
|
||||
@@ -87,11 +90,15 @@ class DeviceDetailsFragmentFormatterTest {
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
context = ApplicationProvider.getApplicationContext()
|
||||
featureFactory = FakeFeatureFactory.setupForTest()
|
||||
doNothing().`when`(context).startActivity(any(Intent::class.java))
|
||||
`when`(
|
||||
featureFactory.bluetoothFeatureProvider.getDeviceSettingRepository(
|
||||
eq(context), eq(bluetoothAdapter), any()))
|
||||
any(),
|
||||
eq(bluetoothAdapter),
|
||||
any(),
|
||||
)
|
||||
)
|
||||
.thenReturn(repository)
|
||||
fragmentActivity = Robolectric.setupActivity(FragmentActivity::class.java)
|
||||
assertThat(fragmentActivity.applicationContext).isNotNull()
|
||||
@@ -115,7 +122,8 @@ class DeviceDetailsFragmentFormatterTest {
|
||||
listOf(profileController, headerController, buttonController),
|
||||
bluetoothAdapter,
|
||||
cachedDevice,
|
||||
testScope.testScheduler)
|
||||
testScope.testScheduler,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -124,11 +132,16 @@ class DeviceDetailsFragmentFormatterTest {
|
||||
`when`(repository.getDeviceSettingsConfig(cachedDevice))
|
||||
.thenReturn(
|
||||
DeviceSettingConfigModel(
|
||||
listOf(), listOf(), DeviceSettingConfigItemModel.AppProvidedItem(12345, false)))
|
||||
val intent = Intent().apply {
|
||||
setAction(Intent.ACTION_VIEW)
|
||||
setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
listOf(),
|
||||
listOf(),
|
||||
DeviceSettingConfigItemModel.AppProvidedItem(12345, false),
|
||||
)
|
||||
)
|
||||
val intent =
|
||||
Intent().apply {
|
||||
setAction(Intent.ACTION_VIEW)
|
||||
setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
`when`(repository.getDeviceSetting(cachedDevice, 12345))
|
||||
.thenReturn(
|
||||
flowOf(
|
||||
@@ -136,12 +149,15 @@ class DeviceDetailsFragmentFormatterTest {
|
||||
cachedDevice = cachedDevice,
|
||||
id = 12345,
|
||||
intent = intent,
|
||||
)))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
var helpPreference: DeviceSettingPreferenceModel.HelpPreference? = null
|
||||
underTest.getMenuItem(FragmentTypeModel.DeviceDetailsMoreSettingsFragment).onEach {
|
||||
helpPreference = it
|
||||
}.launchIn(testScope.backgroundScope)
|
||||
underTest
|
||||
.getMenuItem(FragmentTypeModel.DeviceDetailsMoreSettingsFragment)
|
||||
.onEach { helpPreference = it }
|
||||
.launchIn(testScope.backgroundScope)
|
||||
delay(100)
|
||||
runCurrent()
|
||||
ShadowLooper.idleMainLooper()
|
||||
@@ -171,13 +187,19 @@ class DeviceDetailsFragmentFormatterTest {
|
||||
listOf(
|
||||
DeviceSettingConfigItemModel.BuiltinItem.CommonBuiltinItem(
|
||||
DeviceSettingId.DEVICE_SETTING_ID_HEADER,
|
||||
highlighted = false, preferenceKey = "bluetooth_device_header"),
|
||||
highlighted = false,
|
||||
preferenceKey = "bluetooth_device_header",
|
||||
),
|
||||
DeviceSettingConfigItemModel.BuiltinItem.CommonBuiltinItem(
|
||||
DeviceSettingId.DEVICE_SETTING_ID_BLUETOOTH_PROFILES,
|
||||
highlighted = false, preferenceKey = "bluetooth_profiles"),
|
||||
highlighted = false,
|
||||
preferenceKey = "bluetooth_profiles",
|
||||
),
|
||||
),
|
||||
listOf(),
|
||||
null))
|
||||
null,
|
||||
)
|
||||
)
|
||||
|
||||
underTest.updateLayout(FragmentTypeModel.DeviceDetailsMainFragment)
|
||||
runCurrent()
|
||||
@@ -189,13 +211,17 @@ class DeviceDetailsFragmentFormatterTest {
|
||||
SettingsEnums.PAGE_UNKNOWN,
|
||||
SettingsEnums.ACTION_BLUETOOTH_DEVICE_DETAILS_ITEM_SHOWN,
|
||||
0,
|
||||
"bluetooth_device_header", 1)
|
||||
"bluetooth_device_header",
|
||||
1,
|
||||
)
|
||||
verify(featureFactory.metricsFeatureProvider)
|
||||
.action(
|
||||
SettingsEnums.PAGE_UNKNOWN,
|
||||
SettingsEnums.ACTION_BLUETOOTH_DEVICE_DETAILS_ITEM_SHOWN,
|
||||
0,
|
||||
"bluetooth_profiles", 1)
|
||||
"bluetooth_profiles",
|
||||
1,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,16 +235,22 @@ class DeviceDetailsFragmentFormatterTest {
|
||||
DeviceSettingConfigItemModel.BuiltinItem.CommonBuiltinItem(
|
||||
DeviceSettingId.DEVICE_SETTING_ID_HEADER,
|
||||
highlighted = false,
|
||||
preferenceKey = "bluetooth_device_header"),
|
||||
preferenceKey = "bluetooth_device_header",
|
||||
),
|
||||
DeviceSettingConfigItemModel.AppProvidedItem(
|
||||
DeviceSettingId.DEVICE_SETTING_ID_ANC, highlighted = false),
|
||||
DeviceSettingId.DEVICE_SETTING_ID_ANC,
|
||||
highlighted = false,
|
||||
),
|
||||
DeviceSettingConfigItemModel.BuiltinItem.CommonBuiltinItem(
|
||||
DeviceSettingId.DEVICE_SETTING_ID_BLUETOOTH_PROFILES,
|
||||
highlighted = false,
|
||||
preferenceKey = "bluetooth_profiles"),
|
||||
preferenceKey = "bluetooth_profiles",
|
||||
),
|
||||
),
|
||||
listOf(),
|
||||
null))
|
||||
null,
|
||||
)
|
||||
)
|
||||
`when`(repository.getDeviceSetting(cachedDevice, DeviceSettingId.DEVICE_SETTING_ID_ANC))
|
||||
.thenReturn(
|
||||
flowOf(
|
||||
@@ -231,11 +263,17 @@ class DeviceDetailsFragmentFormatterTest {
|
||||
ToggleModel(
|
||||
"",
|
||||
DeviceSettingIcon.BitmapIcon(
|
||||
Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)))),
|
||||
Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)
|
||||
),
|
||||
)
|
||||
),
|
||||
isActive = true,
|
||||
state = DeviceSettingStateModel.MultiTogglePreferenceState(0),
|
||||
isAllowedChangingState = true,
|
||||
updateState = {})))
|
||||
updateState = {},
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
underTest.updateLayout(FragmentTypeModel.DeviceDetailsMainFragment)
|
||||
runCurrent()
|
||||
@@ -244,13 +282,119 @@ class DeviceDetailsFragmentFormatterTest {
|
||||
.containsExactly(
|
||||
"bluetooth_device_header",
|
||||
"DEVICE_SETTING_${DeviceSettingId.DEVICE_SETTING_ID_ANC}",
|
||||
"bluetooth_profiles")
|
||||
"bluetooth_profiles",
|
||||
)
|
||||
verify(featureFactory.metricsFeatureProvider)
|
||||
.action(
|
||||
SettingsEnums.PAGE_UNKNOWN,
|
||||
SettingsEnums.ACTION_BLUETOOTH_DEVICE_DETAILS_ITEM_SHOWN,
|
||||
0,
|
||||
"DEVICE_SETTING_${DeviceSettingId.DEVICE_SETTING_ID_ANC}", 1
|
||||
"DEVICE_SETTING_${DeviceSettingId.DEVICE_SETTING_ID_ANC}",
|
||||
1,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updateLayout_plainPreferenceClicked() {
|
||||
testScope.runTest {
|
||||
val settingId = 12345
|
||||
val intent = Intent("test_intent")
|
||||
`when`(repository.getDeviceSettingsConfig(cachedDevice))
|
||||
.thenReturn(
|
||||
DeviceSettingConfigModel(
|
||||
listOf(
|
||||
DeviceSettingConfigItemModel.AppProvidedItem(
|
||||
settingId,
|
||||
highlighted = false,
|
||||
)
|
||||
),
|
||||
listOf(),
|
||||
null,
|
||||
)
|
||||
)
|
||||
|
||||
`when`(repository.getDeviceSetting(cachedDevice, settingId))
|
||||
.thenReturn(
|
||||
flowOf(
|
||||
DeviceSettingModel.ActionSwitchPreference(
|
||||
cachedDevice = cachedDevice,
|
||||
id = settingId,
|
||||
title = "title",
|
||||
summary = "summary",
|
||||
icon = null,
|
||||
action = DeviceSettingActionModel.IntentAction(intent),
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
underTest.updateLayout(FragmentTypeModel.DeviceDetailsMainFragment)
|
||||
runCurrent()
|
||||
val displayedPrefs = getDisplayedPreferences()
|
||||
displayedPrefs[0].performClick()
|
||||
|
||||
assertThat(displayedPrefs).hasSize(1)
|
||||
verify(context).startActivity(intent)
|
||||
verify(featureFactory.metricsFeatureProvider)
|
||||
.action(
|
||||
SettingsEnums.PAGE_UNKNOWN,
|
||||
SettingsEnums.ACTION_BLUETOOTH_DEVICE_DETAILS_ITEM_CLICKED,
|
||||
0,
|
||||
"DEVICE_SETTING_$settingId",
|
||||
2,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updateLayout_switchPreferenceClicked() {
|
||||
val settingId = 12345
|
||||
testScope.runTest {
|
||||
`when`(repository.getDeviceSettingsConfig(cachedDevice))
|
||||
.thenReturn(
|
||||
DeviceSettingConfigModel(
|
||||
listOf(
|
||||
DeviceSettingConfigItemModel.AppProvidedItem(
|
||||
settingId,
|
||||
highlighted = false,
|
||||
)
|
||||
),
|
||||
listOf(),
|
||||
null,
|
||||
)
|
||||
)
|
||||
|
||||
`when`(repository.getDeviceSetting(cachedDevice, settingId))
|
||||
.thenReturn(
|
||||
flowOf(
|
||||
DeviceSettingModel.ActionSwitchPreference(
|
||||
cachedDevice = cachedDevice,
|
||||
id = settingId,
|
||||
title = "title",
|
||||
summary = "summary",
|
||||
icon = null,
|
||||
action = null,
|
||||
switchState = DeviceSettingStateModel.ActionSwitchPreferenceState(true),
|
||||
isAllowedChangingState = true,
|
||||
updateState = {},
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
underTest.updateLayout(FragmentTypeModel.DeviceDetailsMainFragment)
|
||||
runCurrent()
|
||||
val displayedPrefs = getDisplayedPreferences()
|
||||
displayedPrefs[0].performClick()
|
||||
|
||||
assertThat(displayedPrefs).hasSize(1)
|
||||
assertThat(displayedPrefs[0]).isInstanceOf(SwitchPreferenceCompat::class.java)
|
||||
verify(featureFactory.metricsFeatureProvider)
|
||||
.action(
|
||||
SettingsEnums.PAGE_UNKNOWN,
|
||||
SettingsEnums.ACTION_BLUETOOTH_DEVICE_DETAILS_ITEM_CLICKED,
|
||||
0,
|
||||
"DEVICE_SETTING_$settingId",
|
||||
0,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -20,7 +20,6 @@ import android.app.Application
|
||||
import android.bluetooth.BluetoothAdapter
|
||||
import android.graphics.Bitmap
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import com.android.settings.bluetooth.ui.layout.DeviceSettingLayout
|
||||
import com.android.settings.bluetooth.ui.model.DeviceSettingPreferenceModel
|
||||
import com.android.settings.bluetooth.ui.model.FragmentTypeModel
|
||||
import com.android.settings.testutils.FakeFeatureFactory
|
||||
@@ -164,74 +163,6 @@ class BluetoothDeviceDetailsViewModelTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getLayout_builtinDeviceSettings() {
|
||||
testScope.runTest {
|
||||
`when`(repository.getDeviceSettingsConfig(cachedDevice))
|
||||
.thenReturn(
|
||||
DeviceSettingConfigModel(
|
||||
listOf(BUILTIN_SETTING_ITEM_1, BUILDIN_SETTING_ITEM_2), listOf(), null))
|
||||
|
||||
val layout = underTest.getLayout(FragmentTypeModel.DeviceDetailsMainFragment)!!
|
||||
|
||||
assertThat(getLatestLayout(layout))
|
||||
.isEqualTo(
|
||||
listOf(
|
||||
listOf(DeviceSettingId.DEVICE_SETTING_ID_HEADER),
|
||||
listOf(DeviceSettingId.DEVICE_SETTING_ID_ACTION_BUTTONS)))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getLayout_remoteDeviceSettings() {
|
||||
val remoteSettingId1 = 10001
|
||||
val remoteSettingId2 = 10002
|
||||
val remoteSettingId3 = 10003
|
||||
testScope.runTest {
|
||||
`when`(repository.getDeviceSettingsConfig(cachedDevice))
|
||||
.thenReturn(
|
||||
DeviceSettingConfigModel(
|
||||
listOf(
|
||||
BUILTIN_SETTING_ITEM_1,
|
||||
buildRemoteSettingItem(remoteSettingId1),
|
||||
buildRemoteSettingItem(remoteSettingId2),
|
||||
buildRemoteSettingItem(remoteSettingId3),
|
||||
),
|
||||
listOf(),
|
||||
null))
|
||||
`when`(repository.getDeviceSetting(cachedDevice, remoteSettingId1))
|
||||
.thenReturn(flowOf(buildMultiTogglePreference(remoteSettingId1)))
|
||||
`when`(repository.getDeviceSetting(cachedDevice, remoteSettingId2))
|
||||
.thenReturn(flowOf(buildMultiTogglePreference(remoteSettingId2)))
|
||||
`when`(repository.getDeviceSetting(cachedDevice, remoteSettingId3))
|
||||
.thenReturn(flowOf(buildActionSwitchPreference(remoteSettingId3)))
|
||||
|
||||
val layout = underTest.getLayout(FragmentTypeModel.DeviceDetailsMainFragment)!!
|
||||
|
||||
assertThat(getLatestLayout(layout))
|
||||
.isEqualTo(
|
||||
listOf(
|
||||
listOf(DeviceSettingId.DEVICE_SETTING_ID_HEADER),
|
||||
listOf(remoteSettingId1),
|
||||
listOf(remoteSettingId2),
|
||||
listOf(remoteSettingId3),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
private fun getLatestLayout(layout: DeviceSettingLayout): List<List<Int>> {
|
||||
val latestLayout = MutableList(layout.rows.size) { emptyList<Int>() }
|
||||
for (i in layout.rows.indices) {
|
||||
layout.rows[i]
|
||||
.columns
|
||||
.onEach { latestLayout[i] = it.map { c -> c.settingId } }
|
||||
.launchIn(testScope.backgroundScope)
|
||||
}
|
||||
|
||||
testScope.runCurrent()
|
||||
return latestLayout.filter { !it.isEmpty() }.toList()
|
||||
}
|
||||
|
||||
private fun buildMultiTogglePreference(settingId: Int) =
|
||||
DeviceSettingModel.MultiTogglePreference(
|
||||
cachedDevice,
|
||||
|
Reference in New Issue
Block a user