Add loading screen for Device details fragment to avoid ANR
BUG: 343317785 Test: local tested Flag: com.android.settings.flags.enable_bluetooth_device_details_polish Change-Id: Iad57fc2fe4cb0a3f90e8d01310b9c7ad20d02233
This commit is contained in:
@@ -27,7 +27,6 @@ import android.sysprop.BluetoothProperties;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
import androidx.preference.PreferenceCategory;
|
import androidx.preference.PreferenceCategory;
|
||||||
@@ -109,28 +108,34 @@ public class BluetoothDetailsProfilesController extends BluetoothDetailsControll
|
|||||||
PreferenceFragmentCompat fragment,
|
PreferenceFragmentCompat fragment,
|
||||||
LocalBluetoothManager manager,
|
LocalBluetoothManager manager,
|
||||||
CachedBluetoothDevice device,
|
CachedBluetoothDevice device,
|
||||||
Lifecycle lifecycle,
|
Lifecycle lifecycle) {
|
||||||
@Nullable List<String> invisibleProfiles,
|
|
||||||
boolean hasExtraSpace) {
|
|
||||||
super(context, fragment, device, lifecycle);
|
super(context, fragment, device, lifecycle);
|
||||||
mManager = manager;
|
mManager = manager;
|
||||||
mProfileManager = mManager.getProfileManager();
|
mProfileManager = mManager.getProfileManager();
|
||||||
mCachedDevice = device;
|
mCachedDevice = device;
|
||||||
mCachedDeviceGroup = Utils.findAllCachedBluetoothDevicesByGroupId(mManager, mCachedDevice);
|
mCachedDeviceGroup = Utils.findAllCachedBluetoothDevicesByGroupId(mManager, mCachedDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sets the profiles to be hidden. */
|
||||||
|
public void setInvisibleProfiles(List<String> invisibleProfiles) {
|
||||||
if (invisibleProfiles != null) {
|
if (invisibleProfiles != null) {
|
||||||
mInvisibleProfiles = Set.copyOf(invisibleProfiles);
|
mInvisibleProfiles = Set.copyOf(invisibleProfiles);
|
||||||
}
|
}
|
||||||
mHasExtraSpace = hasExtraSpace;
|
}
|
||||||
|
|
||||||
|
/** Sets whether it should show an extra padding on top of the preference. */
|
||||||
|
public void setHasExtraSpace(boolean hasExtraSpace) {
|
||||||
|
if (hasExtraSpace) {
|
||||||
|
mProfilesContainer.setLayoutResource(R.layout.preference_bluetooth_profile_category);
|
||||||
|
} else {
|
||||||
|
mProfilesContainer.setLayoutResource(R.layout.preference_category_bluetooth_no_padding);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void init(PreferenceScreen screen) {
|
protected void init(PreferenceScreen screen) {
|
||||||
mProfilesContainer = (PreferenceCategory) screen.findPreference(getPreferenceKey());
|
mProfilesContainer = (PreferenceCategory) screen.findPreference(getPreferenceKey());
|
||||||
if (mHasExtraSpace) {
|
|
||||||
mProfilesContainer.setLayoutResource(R.layout.preference_bluetooth_profile_category);
|
mProfilesContainer.setLayoutResource(R.layout.preference_bluetooth_profile_category);
|
||||||
} else {
|
|
||||||
mProfilesContainer.setLayoutResource(R.layout.preference_category_bluetooth_no_padding);
|
|
||||||
}
|
|
||||||
// Call refresh here even though it will get called later in onResume, to avoid the
|
// Call refresh here even though it will get called later in onResume, to avoid the
|
||||||
// list of switches appearing to "pop" into the page.
|
// list of switches appearing to "pop" into the page.
|
||||||
refresh();
|
refresh();
|
||||||
|
@@ -61,7 +61,6 @@ import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
|||||||
import com.android.settingslib.core.AbstractPreferenceController;
|
import com.android.settingslib.core.AbstractPreferenceController;
|
||||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -289,9 +288,12 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
|
|||||||
getController(
|
getController(
|
||||||
SlicePreferenceController.class,
|
SlicePreferenceController.class,
|
||||||
controller -> {
|
controller -> {
|
||||||
|
if (getPreferenceScreen().findPreference(controller.getPreferenceKey())
|
||||||
|
!= null) {
|
||||||
controller.setSliceUri(finalControlUri);
|
controller.setSliceUri(finalControlUri);
|
||||||
controller.onStart();
|
controller.onStart();
|
||||||
controller.displayPreference(getPreferenceScreen());
|
controller.displayPreference(getPreferenceScreen());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Temporarily fix the issue that the page will be automatically scrolled to a wrong
|
// Temporarily fix the issue that the page will be automatically scrolled to a wrong
|
||||||
@@ -352,9 +354,23 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreatePreferences(@NonNull Bundle savedInstanceState, @NonNull String rootKey) {
|
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||||
super.onCreatePreferences(savedInstanceState, rootKey);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
if (Flags.enableBluetoothDeviceDetailsPolish()) {
|
if (Flags.enableBluetoothDeviceDetailsPolish()) {
|
||||||
|
if (mFormatter == null) {
|
||||||
|
List<AbstractPreferenceController> controllers = getPreferenceControllers().stream()
|
||||||
|
.flatMap(List::stream)
|
||||||
|
.toList();
|
||||||
|
mFormatter =
|
||||||
|
FeatureFactory.getFeatureFactory()
|
||||||
|
.getBluetoothFeatureProvider()
|
||||||
|
.getDeviceDetailsFragmentFormatter(
|
||||||
|
requireContext(),
|
||||||
|
this,
|
||||||
|
mBluetoothAdapter,
|
||||||
|
mCachedDevice,
|
||||||
|
controllers);
|
||||||
|
}
|
||||||
mFormatter.updateLayout(FragmentTypeModel.DeviceDetailsMainFragment.INSTANCE);
|
mFormatter.updateLayout(FragmentTypeModel.DeviceDetailsMainFragment.INSTANCE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -409,38 +425,8 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
|
|||||||
return super.onOptionsItemSelected(menuItem);
|
return super.onOptionsItemSelected(menuItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void addPreferenceController(AbstractPreferenceController controller) {
|
|
||||||
if (Flags.enableBluetoothDeviceDetailsPolish()) {
|
|
||||||
List<String> keys =
|
|
||||||
mFormatter.getVisiblePreferenceKeys(
|
|
||||||
FragmentTypeModel.DeviceDetailsMainFragment.INSTANCE);
|
|
||||||
Lifecycle lifecycle = getSettingsLifecycle();
|
|
||||||
if (keys == null || keys.contains(controller.getPreferenceKey())) {
|
|
||||||
super.addPreferenceController(controller);
|
|
||||||
} else if (controller instanceof LifecycleObserver) {
|
|
||||||
lifecycle.removeObserver((LifecycleObserver) controller);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
super.addPreferenceController(controller);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
|
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
|
||||||
List<String> invisibleProfiles = List.of();
|
|
||||||
if (Flags.enableBluetoothDeviceDetailsPolish()) {
|
|
||||||
if (mFormatter == null) {
|
|
||||||
mFormatter =
|
|
||||||
FeatureFactory.getFeatureFactory()
|
|
||||||
.getBluetoothFeatureProvider()
|
|
||||||
.getDeviceDetailsFragmentFormatter(
|
|
||||||
requireContext(), this, mBluetoothAdapter, mCachedDevice);
|
|
||||||
}
|
|
||||||
invisibleProfiles =
|
|
||||||
mFormatter.getInvisibleBluetoothProfiles(
|
|
||||||
FragmentTypeModel.DeviceDetailsMainFragment.INSTANCE);
|
|
||||||
}
|
|
||||||
ArrayList<AbstractPreferenceController> controllers = new ArrayList<>();
|
ArrayList<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||||
|
|
||||||
if (mCachedDevice != null) {
|
if (mCachedDevice != null) {
|
||||||
@@ -459,7 +445,7 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
|
|||||||
controllers.add(new BluetoothDetailsSpatialAudioController(context, this, mCachedDevice,
|
controllers.add(new BluetoothDetailsSpatialAudioController(context, this, mCachedDevice,
|
||||||
lifecycle));
|
lifecycle));
|
||||||
controllers.add(new BluetoothDetailsProfilesController(context, this, mManager,
|
controllers.add(new BluetoothDetailsProfilesController(context, this, mManager,
|
||||||
mCachedDevice, lifecycle, invisibleProfiles, invisibleProfiles == null));
|
mCachedDevice, lifecycle));
|
||||||
controllers.add(new BluetoothDetailsMacAddressController(context, this, mCachedDevice,
|
controllers.add(new BluetoothDetailsMacAddressController(context, this, mCachedDevice,
|
||||||
lifecycle));
|
lifecycle));
|
||||||
controllers.add(new StylusDevicesController(context, mInputDevice, mCachedDevice,
|
controllers.add(new StylusDevicesController(context, mInputDevice, mCachedDevice,
|
||||||
|
@@ -26,10 +26,11 @@ import android.net.Uri;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
|
|
||||||
import com.android.settings.SettingsPreferenceFragment;
|
|
||||||
import com.android.settings.bluetooth.ui.view.DeviceDetailsFragmentFormatter;
|
import com.android.settings.bluetooth.ui.view.DeviceDetailsFragmentFormatter;
|
||||||
|
import com.android.settings.dashboard.DashboardFragment;
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
import com.android.settingslib.bluetooth.devicesettings.data.repository.DeviceSettingRepository;
|
import com.android.settingslib.bluetooth.devicesettings.data.repository.DeviceSettingRepository;
|
||||||
|
import com.android.settingslib.core.AbstractPreferenceController;
|
||||||
|
|
||||||
import kotlinx.coroutines.CoroutineScope;
|
import kotlinx.coroutines.CoroutineScope;
|
||||||
|
|
||||||
@@ -100,7 +101,8 @@ public interface BluetoothFeatureProvider {
|
|||||||
@NonNull
|
@NonNull
|
||||||
DeviceDetailsFragmentFormatter getDeviceDetailsFragmentFormatter(
|
DeviceDetailsFragmentFormatter getDeviceDetailsFragmentFormatter(
|
||||||
@NonNull Context context,
|
@NonNull Context context,
|
||||||
@NonNull SettingsPreferenceFragment fragment,
|
@NonNull DashboardFragment fragment,
|
||||||
@NonNull BluetoothAdapter bluetoothAdapter,
|
@NonNull BluetoothAdapter bluetoothAdapter,
|
||||||
@NonNull CachedBluetoothDevice cachedDevice);
|
@NonNull CachedBluetoothDevice cachedDevice,
|
||||||
|
@NonNull List<AbstractPreferenceController> controllers);
|
||||||
}
|
}
|
||||||
|
@@ -23,13 +23,14 @@ import android.media.AudioManager
|
|||||||
import android.media.Spatializer
|
import android.media.Spatializer
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import com.android.settings.SettingsPreferenceFragment
|
|
||||||
import com.android.settings.bluetooth.ui.view.DeviceDetailsFragmentFormatter
|
import com.android.settings.bluetooth.ui.view.DeviceDetailsFragmentFormatter
|
||||||
import com.android.settings.bluetooth.ui.view.DeviceDetailsFragmentFormatterImpl
|
import com.android.settings.bluetooth.ui.view.DeviceDetailsFragmentFormatterImpl
|
||||||
|
import com.android.settings.dashboard.DashboardFragment
|
||||||
import com.android.settingslib.bluetooth.BluetoothUtils
|
import com.android.settingslib.bluetooth.BluetoothUtils
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice
|
||||||
import com.android.settingslib.bluetooth.devicesettings.data.repository.DeviceSettingRepository
|
import com.android.settingslib.bluetooth.devicesettings.data.repository.DeviceSettingRepository
|
||||||
import com.android.settingslib.bluetooth.devicesettings.data.repository.DeviceSettingRepositoryImpl
|
import com.android.settingslib.bluetooth.devicesettings.data.repository.DeviceSettingRepositoryImpl
|
||||||
|
import com.android.settingslib.core.AbstractPreferenceController
|
||||||
import com.google.common.collect.ImmutableList
|
import com.google.common.collect.ImmutableList
|
||||||
import com.google.common.collect.ImmutableSet
|
import com.google.common.collect.ImmutableSet
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
@@ -78,13 +79,15 @@ open class BluetoothFeatureProviderImpl : BluetoothFeatureProvider {
|
|||||||
|
|
||||||
override fun getDeviceDetailsFragmentFormatter(
|
override fun getDeviceDetailsFragmentFormatter(
|
||||||
context: Context,
|
context: Context,
|
||||||
fragment: SettingsPreferenceFragment,
|
fragment: DashboardFragment,
|
||||||
bluetoothAdapter: BluetoothAdapter,
|
bluetoothAdapter: BluetoothAdapter,
|
||||||
cachedDevice: CachedBluetoothDevice
|
cachedDevice: CachedBluetoothDevice,
|
||||||
|
controllers: List<AbstractPreferenceController>,
|
||||||
): DeviceDetailsFragmentFormatter {
|
): DeviceDetailsFragmentFormatter {
|
||||||
return DeviceDetailsFragmentFormatterImpl(
|
return DeviceDetailsFragmentFormatterImpl(
|
||||||
context,
|
context,
|
||||||
fragment,
|
fragment,
|
||||||
|
controllers,
|
||||||
bluetoothAdapter,
|
bluetoothAdapter,
|
||||||
cachedDevice,
|
cachedDevice,
|
||||||
Dispatchers.IO
|
Dispatchers.IO
|
||||||
|
@@ -45,7 +45,8 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
import com.android.settings.SettingsPreferenceFragment
|
import com.android.settings.bluetooth.BlockingPrefWithSliceController
|
||||||
|
import com.android.settings.bluetooth.BluetoothDetailsProfilesController
|
||||||
import com.android.settings.bluetooth.ui.composable.Icon
|
import com.android.settings.bluetooth.ui.composable.Icon
|
||||||
import com.android.settings.bluetooth.ui.composable.MultiTogglePreference
|
import com.android.settings.bluetooth.ui.composable.MultiTogglePreference
|
||||||
import com.android.settings.bluetooth.ui.layout.DeviceSettingLayout
|
import com.android.settings.bluetooth.ui.layout.DeviceSettingLayout
|
||||||
@@ -54,12 +55,18 @@ import com.android.settings.bluetooth.ui.model.FragmentTypeModel
|
|||||||
import com.android.settings.bluetooth.ui.view.DeviceDetailsMoreSettingsFragment.Companion.KEY_DEVICE_ADDRESS
|
import com.android.settings.bluetooth.ui.view.DeviceDetailsMoreSettingsFragment.Companion.KEY_DEVICE_ADDRESS
|
||||||
import com.android.settings.bluetooth.ui.viewmodel.BluetoothDeviceDetailsViewModel
|
import com.android.settings.bluetooth.ui.viewmodel.BluetoothDeviceDetailsViewModel
|
||||||
import com.android.settings.core.SubSettingLauncher
|
import com.android.settings.core.SubSettingLauncher
|
||||||
|
import com.android.settings.dashboard.DashboardFragment
|
||||||
import com.android.settings.overlay.FeatureFactory
|
import com.android.settings.overlay.FeatureFactory
|
||||||
import com.android.settings.spa.preference.ComposePreference
|
import com.android.settings.spa.preference.ComposePreference
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice
|
||||||
|
import com.android.settingslib.bluetooth.devicesettings.DeviceSettingId
|
||||||
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingActionModel
|
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.DeviceSettingConfigItemModel
|
||||||
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingIcon
|
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingIcon
|
||||||
|
import com.android.settingslib.core.AbstractPreferenceController
|
||||||
|
import com.android.settingslib.core.lifecycle.LifecycleObserver
|
||||||
|
import com.android.settingslib.core.lifecycle.events.OnPause
|
||||||
|
import com.android.settingslib.core.lifecycle.events.OnStop
|
||||||
import com.android.settingslib.spa.framework.theme.SettingsDimension
|
import com.android.settingslib.spa.framework.theme.SettingsDimension
|
||||||
import com.android.settingslib.spa.widget.preference.Preference as SpaPreference
|
import com.android.settingslib.spa.widget.preference.Preference as SpaPreference
|
||||||
import com.android.settingslib.spa.widget.preference.PreferenceModel
|
import com.android.settingslib.spa.widget.preference.PreferenceModel
|
||||||
@@ -81,16 +88,10 @@ import kotlinx.coroutines.flow.flowOf
|
|||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
/** Handles device details fragment layout according to config. */
|
/** Handles device details fragment layout according to config. */
|
||||||
interface DeviceDetailsFragmentFormatter {
|
interface DeviceDetailsFragmentFormatter {
|
||||||
/** Gets keys of visible preferences in built-in preference in xml. */
|
|
||||||
fun getVisiblePreferenceKeys(fragmentType: FragmentTypeModel): List<String>?
|
|
||||||
|
|
||||||
/** Updates device details fragment layout. */
|
|
||||||
fun getInvisibleBluetoothProfiles(fragmentType: FragmentTypeModel): List<String>?
|
|
||||||
|
|
||||||
/** Updates device details fragment layout. */
|
/** Updates device details fragment layout. */
|
||||||
fun updateLayout(fragmentType: FragmentTypeModel)
|
fun updateLayout(fragmentType: FragmentTypeModel)
|
||||||
|
|
||||||
@@ -104,7 +105,8 @@ interface DeviceDetailsFragmentFormatter {
|
|||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
class DeviceDetailsFragmentFormatterImpl(
|
class DeviceDetailsFragmentFormatterImpl(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val fragment: SettingsPreferenceFragment,
|
private val fragment: DashboardFragment,
|
||||||
|
controllers: List<AbstractPreferenceController>,
|
||||||
private val bluetoothAdapter: BluetoothAdapter,
|
private val bluetoothAdapter: BluetoothAdapter,
|
||||||
private val cachedDevice: CachedBluetoothDevice,
|
private val cachedDevice: CachedBluetoothDevice,
|
||||||
private val backgroundCoroutineContext: CoroutineContext,
|
private val backgroundCoroutineContext: CoroutineContext,
|
||||||
@@ -112,6 +114,9 @@ class DeviceDetailsFragmentFormatterImpl(
|
|||||||
private val metricsFeatureProvider = FeatureFactory.featureFactory.metricsFeatureProvider
|
private val metricsFeatureProvider = FeatureFactory.featureFactory.metricsFeatureProvider
|
||||||
private val prefVisibility = mutableMapOf<String, MutableStateFlow<Boolean>>()
|
private val prefVisibility = mutableMapOf<String, MutableStateFlow<Boolean>>()
|
||||||
private val prefVisibilityJobs = mutableListOf<Job>()
|
private val prefVisibilityJobs = mutableListOf<Job>()
|
||||||
|
private var isLoading = false
|
||||||
|
private var prefKeyToController: Map<String, AbstractPreferenceController> =
|
||||||
|
controllers.associateBy { it.preferenceKey }
|
||||||
|
|
||||||
private val viewModel: BluetoothDeviceDetailsViewModel =
|
private val viewModel: BluetoothDeviceDetailsViewModel =
|
||||||
ViewModelProvider(
|
ViewModelProvider(
|
||||||
@@ -125,27 +130,16 @@ class DeviceDetailsFragmentFormatterImpl(
|
|||||||
)
|
)
|
||||||
.get(BluetoothDeviceDetailsViewModel::class.java)
|
.get(BluetoothDeviceDetailsViewModel::class.java)
|
||||||
|
|
||||||
override fun getVisiblePreferenceKeys(fragmentType: FragmentTypeModel): List<String>? =
|
|
||||||
runBlocking {
|
|
||||||
viewModel
|
|
||||||
.getItems(fragmentType)
|
|
||||||
?.filterIsInstance<DeviceSettingConfigItemModel.BuiltinItem>()
|
|
||||||
?.map { it.preferenceKey }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getInvisibleBluetoothProfiles(fragmentType: FragmentTypeModel): List<String>? =
|
|
||||||
runBlocking {
|
|
||||||
viewModel
|
|
||||||
.getItems(fragmentType)
|
|
||||||
?.filterIsInstance<DeviceSettingConfigItemModel.BuiltinItem.BluetoothProfilesItem>()
|
|
||||||
?.firstOrNull()
|
|
||||||
?.invisibleProfiles
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Updates bluetooth device details fragment layout. */
|
/** Updates bluetooth device details fragment layout. */
|
||||||
override fun updateLayout(fragmentType: FragmentTypeModel) = runBlocking {
|
override fun updateLayout(fragmentType: FragmentTypeModel) {
|
||||||
val items = viewModel.getItems(fragmentType) ?: return@runBlocking
|
fragment.setLoading(true, false)
|
||||||
val layout = viewModel.getLayout(fragmentType) ?: return@runBlocking
|
isLoading = true
|
||||||
|
fragment.lifecycleScope.launch { updateLayoutInternal(fragmentType) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun updateLayoutInternal(fragmentType: FragmentTypeModel) {
|
||||||
|
val items = viewModel.getItems(fragmentType) ?: return
|
||||||
|
val layout = viewModel.getLayout(fragmentType) ?: return
|
||||||
|
|
||||||
val prefKeyToSettingId =
|
val prefKeyToSettingId =
|
||||||
items
|
items
|
||||||
@@ -156,21 +150,21 @@ class DeviceDetailsFragmentFormatterImpl(
|
|||||||
for (i in 0 until fragment.preferenceScreen.preferenceCount) {
|
for (i in 0 until fragment.preferenceScreen.preferenceCount) {
|
||||||
val pref = fragment.preferenceScreen.getPreference(i)
|
val pref = fragment.preferenceScreen.getPreference(i)
|
||||||
prefKeyToSettingId[pref.key]?.let { id -> settingIdToXmlPreferences[id] = pref }
|
prefKeyToSettingId[pref.key]?.let { id -> settingIdToXmlPreferences[id] = pref }
|
||||||
|
if (pref.key !in prefKeyToSettingId) {
|
||||||
|
getController(pref.key)?.let { disableController(it) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fragment.preferenceScreen.removeAll()
|
fragment.preferenceScreen.removeAll()
|
||||||
for (job in prefVisibilityJobs) {
|
for (job in prefVisibilityJobs) {
|
||||||
job.cancel()
|
job.cancel()
|
||||||
}
|
}
|
||||||
prefVisibilityJobs.clear()
|
prefVisibilityJobs.clear()
|
||||||
|
|
||||||
for (row in items.indices) {
|
for (row in items.indices) {
|
||||||
val settingId = items[row].settingId
|
val settingItem = items[row]
|
||||||
|
val settingId = settingItem.settingId
|
||||||
if (settingIdToXmlPreferences.containsKey(settingId)) {
|
if (settingIdToXmlPreferences.containsKey(settingId)) {
|
||||||
fragment.preferenceScreen.addPreference(
|
val pref = settingIdToXmlPreferences[settingId]!!.apply { order = row }
|
||||||
settingIdToXmlPreferences[settingId]!!
|
fragment.preferenceScreen.addPreference(pref)
|
||||||
.apply { order = row }
|
|
||||||
.also { logItemShown(it.key, it.isVisible) }
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
val prefKey = getPreferenceKey(settingId)
|
val prefKey = getPreferenceKey(settingId)
|
||||||
prefVisibilityJobs.add(
|
prefVisibilityJobs.add(
|
||||||
@@ -195,6 +189,29 @@ class DeviceDetailsFragmentFormatterImpl(
|
|||||||
isSelectable = false
|
isSelectable = false
|
||||||
setContent { Spacer(modifier = Modifier.height(1.dp)) }
|
setContent { Spacer(modifier = Modifier.height(1.dp)) }
|
||||||
})
|
})
|
||||||
|
|
||||||
|
for (row in items.indices) {
|
||||||
|
val settingItem = items[row]
|
||||||
|
val settingId = settingItem.settingId
|
||||||
|
if (settingIdToXmlPreferences.containsKey(settingId)) {
|
||||||
|
val pref = fragment.preferenceScreen.getPreference(row)
|
||||||
|
if (settingId == DeviceSettingId.DEVICE_SETTING_ID_BLUETOOTH_PROFILES) {
|
||||||
|
(getController(pref.key) as? BluetoothDetailsProfilesController)?.run {
|
||||||
|
if (settingItem is DeviceSettingConfigItemModel.BuiltinItem.BluetoothProfilesItem) {
|
||||||
|
setInvisibleProfiles(settingItem.invisibleProfiles)
|
||||||
|
setHasExtraSpace(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getController(pref.key)?.displayPreference(fragment.preferenceScreen)
|
||||||
|
logItemShown(pref.key, pref.isVisible)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
fragment.setLoading(false, false)
|
||||||
|
isLoading = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getMenuItem(
|
override fun getMenuItem(
|
||||||
@@ -454,6 +471,29 @@ class DeviceDetailsFragmentFormatterImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getController(key: String): AbstractPreferenceController? {
|
||||||
|
return prefKeyToController[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun disableController(controller: AbstractPreferenceController) {
|
||||||
|
if (controller is LifecycleObserver) {
|
||||||
|
fragment.settingsLifecycle.removeObserver(controller as LifecycleObserver)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (controller is BlockingPrefWithSliceController) {
|
||||||
|
// Make UiBlockListener finished, otherwise UI will flicker.
|
||||||
|
controller.onChanged(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (controller is OnPause) {
|
||||||
|
(controller as OnPause).onPause()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (controller is OnStop) {
|
||||||
|
(controller as OnStop).onStop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun getPreferenceKey(settingId: Int) = "DEVICE_SETTING_${settingId}"
|
private fun getPreferenceKey(settingId: Int) = "DEVICE_SETTING_${settingId}"
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
|
@@ -25,6 +25,7 @@ import android.graphics.PorterDuff
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
import com.android.settings.bluetooth.BluetoothDetailsAudioDeviceTypeController
|
import com.android.settings.bluetooth.BluetoothDetailsAudioDeviceTypeController
|
||||||
@@ -33,12 +34,12 @@ import com.android.settings.bluetooth.Utils
|
|||||||
import com.android.settings.bluetooth.ui.model.DeviceSettingPreferenceModel
|
import com.android.settings.bluetooth.ui.model.DeviceSettingPreferenceModel
|
||||||
import com.android.settings.bluetooth.ui.model.FragmentTypeModel
|
import com.android.settings.bluetooth.ui.model.FragmentTypeModel
|
||||||
import com.android.settings.dashboard.DashboardFragment
|
import com.android.settings.dashboard.DashboardFragment
|
||||||
|
import com.android.settings.flags.Flags
|
||||||
import com.android.settings.overlay.FeatureFactory.Companion.featureFactory
|
import com.android.settings.overlay.FeatureFactory.Companion.featureFactory
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice
|
||||||
import com.android.settingslib.bluetooth.LocalBluetoothManager
|
import com.android.settingslib.bluetooth.LocalBluetoothManager
|
||||||
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingIcon
|
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingIcon
|
||||||
import com.android.settingslib.core.AbstractPreferenceController
|
import com.android.settingslib.core.AbstractPreferenceController
|
||||||
import com.android.settingslib.core.lifecycle.LifecycleObserver
|
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.filterNotNull
|
import kotlinx.coroutines.flow.filterNotNull
|
||||||
@@ -88,17 +89,29 @@ class DeviceDetailsMoreSettingsFragment : DashboardFragment() {
|
|||||||
return R.xml.bluetooth_device_more_settings_fragment
|
return R.xml.bluetooth_device_more_settings_fragment
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addPreferenceController(controller: AbstractPreferenceController) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
val keys: List<String>? =
|
super.onViewCreated(view, savedInstanceState)
|
||||||
formatter.getVisiblePreferenceKeys(FragmentTypeModel.DeviceDetailsMoreSettingsFragment)
|
if (!this::formatter.isInitialized) {
|
||||||
val lifecycle = settingsLifecycle
|
val controllers = preferenceControllers.stream()
|
||||||
if (keys == null || keys.contains(controller.preferenceKey)) {
|
.flatMap { obj: List<AbstractPreferenceController?> -> obj.stream() }
|
||||||
super.addPreferenceController(controller)
|
.toList()
|
||||||
} else if (controller is LifecycleObserver) {
|
val bluetoothManager = requireContext().getSystemService(BluetoothManager::class.java)
|
||||||
lifecycle.removeObserver((controller as LifecycleObserver))
|
formatter =
|
||||||
|
featureFactory
|
||||||
|
.bluetoothFeatureProvider
|
||||||
|
.getDeviceDetailsFragmentFormatter(
|
||||||
|
requireContext(), this, bluetoothManager.adapter, cachedDevice, controllers
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
formatter.updateLayout(FragmentTypeModel.DeviceDetailsMoreSettingsFragment)
|
||||||
|
helpItem =
|
||||||
|
formatter
|
||||||
|
.getMenuItem(FragmentTypeModel.DeviceDetailsMoreSettingsFragment)
|
||||||
|
.stateIn(lifecycleScope, SharingStarted.WhileSubscribed(), initialValue = null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private fun getCachedDevice(): CachedBluetoothDevice? {
|
private fun getCachedDevice(): CachedBluetoothDevice? {
|
||||||
val bluetoothAddress = arguments?.getString(KEY_DEVICE_ADDRESS) ?: return null
|
val bluetoothAddress = arguments?.getString(KEY_DEVICE_ADDRESS) ?: return null
|
||||||
localBluetoothManager = Utils.getLocalBtManager(context) ?: return null
|
localBluetoothManager = Utils.getLocalBtManager(context) ?: return null
|
||||||
@@ -107,32 +120,13 @@ class DeviceDetailsMoreSettingsFragment : DashboardFragment() {
|
|||||||
return Utils.getLocalBtManager(context).cachedDeviceManager.findDevice(remoteDevice)
|
return Utils.getLocalBtManager(context).cachedDeviceManager.findDevice(remoteDevice)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
|
||||||
super.onCreatePreferences(savedInstanceState, rootKey)
|
|
||||||
formatter.updateLayout(FragmentTypeModel.DeviceDetailsMoreSettingsFragment)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createPreferenceControllers(context: Context): List<AbstractPreferenceController> {
|
override fun createPreferenceControllers(context: Context): List<AbstractPreferenceController> {
|
||||||
val bluetoothManager = context.getSystemService(BluetoothManager::class.java)
|
|
||||||
cachedDevice =
|
cachedDevice =
|
||||||
getCachedDevice()
|
getCachedDevice()
|
||||||
?: run {
|
?: run {
|
||||||
finish()
|
finish()
|
||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
if (!this::formatter.isInitialized) {
|
|
||||||
formatter =
|
|
||||||
featureFactory.bluetoothFeatureProvider.getDeviceDetailsFragmentFormatter(
|
|
||||||
requireContext(),
|
|
||||||
this,
|
|
||||||
bluetoothManager.adapter,
|
|
||||||
cachedDevice,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
helpItem =
|
|
||||||
formatter
|
|
||||||
.getMenuItem(FragmentTypeModel.DeviceDetailsMoreSettingsFragment)
|
|
||||||
.stateIn(lifecycleScope, SharingStarted.WhileSubscribed(), initialValue = null)
|
|
||||||
return listOf(
|
return listOf(
|
||||||
BluetoothDetailsProfilesController(
|
BluetoothDetailsProfilesController(
|
||||||
context,
|
context,
|
||||||
@@ -140,10 +134,6 @@ class DeviceDetailsMoreSettingsFragment : DashboardFragment() {
|
|||||||
localBluetoothManager,
|
localBluetoothManager,
|
||||||
cachedDevice,
|
cachedDevice,
|
||||||
settingsLifecycle,
|
settingsLifecycle,
|
||||||
formatter.getInvisibleBluetoothProfiles(
|
|
||||||
FragmentTypeModel.DeviceDetailsMoreSettingsFragment
|
|
||||||
),
|
|
||||||
false,
|
|
||||||
),
|
),
|
||||||
BluetoothDetailsAudioDeviceTypeController(
|
BluetoothDetailsAudioDeviceTypeController(
|
||||||
context,
|
context,
|
||||||
|
@@ -120,7 +120,12 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont
|
|||||||
.thenAnswer(invocation -> ImmutableList.of(mConnectableProfiles));
|
.thenAnswer(invocation -> ImmutableList.of(mConnectableProfiles));
|
||||||
|
|
||||||
setupDevice(mDeviceConfig);
|
setupDevice(mDeviceConfig);
|
||||||
initController(List.of());
|
mController = new BluetoothDetailsProfilesController(mContext, mFragment, mLocalManager,
|
||||||
|
mCachedDevice, mLifecycle);
|
||||||
|
mProfiles.setKey(mController.getPreferenceKey());
|
||||||
|
mController.mProfilesContainer = mProfiles;
|
||||||
|
mScreen.removeAll();
|
||||||
|
mScreen.addPreference(mProfiles);
|
||||||
BluetoothProperties.le_audio_allow_list(Lists.newArrayList(LE_DEVICE_MODEL));
|
BluetoothProperties.le_audio_allow_list(Lists.newArrayList(LE_DEVICE_MODEL));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -550,7 +555,8 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void prefKeyInBlockingList_hideToggle() {
|
public void prefKeyInBlockingList_hideToggle() {
|
||||||
initController(List.of("A2DP"));
|
mController.setInvisibleProfiles(List.of("A2DP"));
|
||||||
|
mController.setHasExtraSpace(true);
|
||||||
setupDevice(makeDefaultDeviceConfig());
|
setupDevice(makeDefaultDeviceConfig());
|
||||||
|
|
||||||
addA2dpProfileToDevice(true, true, true);
|
addA2dpProfileToDevice(true, true, true);
|
||||||
@@ -565,7 +571,6 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void prefKeyNotInBlockingList_showToggle() {
|
public void prefKeyNotInBlockingList_showToggle() {
|
||||||
initController(List.of());
|
|
||||||
setupDevice(makeDefaultDeviceConfig());
|
setupDevice(makeDefaultDeviceConfig());
|
||||||
|
|
||||||
addA2dpProfileToDevice(true, true, true);
|
addA2dpProfileToDevice(true, true, true);
|
||||||
@@ -653,13 +658,4 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont
|
|||||||
assertThat(switches.getFirst().getTitle()).isEqualTo(
|
assertThat(switches.getFirst().getTitle()).isEqualTo(
|
||||||
mContext.getString(mLeAudioProfile.getNameResource(mDevice)));
|
mContext.getString(mLeAudioProfile.getNameResource(mDevice)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initController(List<String> invisibleProfiles) {
|
|
||||||
mController = new BluetoothDetailsProfilesController(mContext, mFragment, mLocalManager,
|
|
||||||
mCachedDevice, mLifecycle, invisibleProfiles, true);
|
|
||||||
mProfiles.setKey(mController.getPreferenceKey());
|
|
||||||
mController.mProfilesContainer = mProfiles;
|
|
||||||
mScreen.removeAll();
|
|
||||||
mScreen.addPreference(mProfiles);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -52,7 +52,6 @@ import androidx.fragment.app.FragmentTransaction;
|
|||||||
import androidx.preference.PreferenceScreen;
|
import androidx.preference.PreferenceScreen;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.bluetooth.ui.model.FragmentTypeModel;
|
|
||||||
import com.android.settings.bluetooth.ui.view.DeviceDetailsFragmentFormatter;
|
import com.android.settings.bluetooth.ui.view.DeviceDetailsFragmentFormatter;
|
||||||
import com.android.settings.flags.Flags;
|
import com.android.settings.flags.Flags;
|
||||||
import com.android.settings.testutils.FakeFeatureFactory;
|
import com.android.settings.testutils.FakeFeatureFactory;
|
||||||
@@ -122,10 +121,7 @@ public class BluetoothDeviceDetailsFragmentTest {
|
|||||||
removeInputDeviceWithMatchingBluetoothAddress();
|
removeInputDeviceWithMatchingBluetoothAddress();
|
||||||
FakeFeatureFactory fakeFeatureFactory = FakeFeatureFactory.setupForTest();
|
FakeFeatureFactory fakeFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||||
when(fakeFeatureFactory.mBluetoothFeatureProvider.getDeviceDetailsFragmentFormatter(any(),
|
when(fakeFeatureFactory.mBluetoothFeatureProvider.getDeviceDetailsFragmentFormatter(any(),
|
||||||
any(), any(), eq(mCachedDevice))).thenReturn(mFormatter);
|
any(), any(), eq(mCachedDevice), any())).thenReturn(mFormatter);
|
||||||
when(mFormatter.getVisiblePreferenceKeys(
|
|
||||||
FragmentTypeModel.DeviceDetailsMainFragment.INSTANCE))
|
|
||||||
.thenReturn(null);
|
|
||||||
|
|
||||||
mFragment = setupFragment();
|
mFragment = setupFragment();
|
||||||
mFragment.onAttach(mContext);
|
mFragment.onAttach(mContext);
|
||||||
|
@@ -39,6 +39,7 @@ import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSetti
|
|||||||
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingModel
|
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.DeviceSettingStateModel
|
||||||
import com.android.settingslib.bluetooth.devicesettings.shared.model.ToggleModel
|
import com.android.settingslib.bluetooth.devicesettings.shared.model.ToggleModel
|
||||||
|
import com.android.settingslib.core.AbstractPreferenceController
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
@@ -73,6 +74,9 @@ class DeviceDetailsFragmentFormatterTest {
|
|||||||
@Mock private lateinit var cachedDevice: CachedBluetoothDevice
|
@Mock private lateinit var cachedDevice: CachedBluetoothDevice
|
||||||
@Mock private lateinit var bluetoothAdapter: BluetoothAdapter
|
@Mock private lateinit var bluetoothAdapter: BluetoothAdapter
|
||||||
@Mock private lateinit var repository: DeviceSettingRepository
|
@Mock private lateinit var repository: DeviceSettingRepository
|
||||||
|
@Mock private lateinit var profileController: AbstractPreferenceController
|
||||||
|
@Mock private lateinit var headerController: AbstractPreferenceController
|
||||||
|
@Mock private lateinit var buttonController: AbstractPreferenceController
|
||||||
|
|
||||||
private lateinit var context: Context
|
private lateinit var context: Context
|
||||||
private lateinit var fragment: TestFragment
|
private lateinit var fragment: TestFragment
|
||||||
@@ -98,55 +102,22 @@ class DeviceDetailsFragmentFormatterTest {
|
|||||||
fragment.preferenceScreen.run {
|
fragment.preferenceScreen.run {
|
||||||
addPreference(Preference(context).apply { key = "bluetooth_device_header" })
|
addPreference(Preference(context).apply { key = "bluetooth_device_header" })
|
||||||
addPreference(Preference(context).apply { key = "action_buttons" })
|
addPreference(Preference(context).apply { key = "action_buttons" })
|
||||||
addPreference(Preference(context).apply { key = "keyboard_settings" })
|
addPreference(Preference(context).apply { key = "bluetooth_profiles" })
|
||||||
}
|
}
|
||||||
|
`when`(profileController.preferenceKey).thenReturn("bluetooth_profiles")
|
||||||
|
`when`(headerController.preferenceKey).thenReturn("bluetooth_device_header")
|
||||||
|
`when`(buttonController.preferenceKey).thenReturn("action_buttons")
|
||||||
|
|
||||||
underTest =
|
underTest =
|
||||||
DeviceDetailsFragmentFormatterImpl(
|
DeviceDetailsFragmentFormatterImpl(
|
||||||
context,
|
context,
|
||||||
fragment,
|
fragment,
|
||||||
|
listOf(profileController, headerController, buttonController),
|
||||||
bluetoothAdapter,
|
bluetoothAdapter,
|
||||||
cachedDevice,
|
cachedDevice,
|
||||||
testScope.testScheduler)
|
testScope.testScheduler)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun getVisiblePreferenceKeysForMainPage_hasConfig_returnList() {
|
|
||||||
testScope.runTest {
|
|
||||||
`when`(repository.getDeviceSettingsConfig(cachedDevice))
|
|
||||||
.thenReturn(
|
|
||||||
DeviceSettingConfigModel(
|
|
||||||
listOf(
|
|
||||||
DeviceSettingConfigItemModel.BuiltinItem.CommonBuiltinItem(
|
|
||||||
DeviceSettingId.DEVICE_SETTING_ID_HEADER,
|
|
||||||
highlighted = false,
|
|
||||||
preferenceKey = "bluetooth_device_header"
|
|
||||||
),
|
|
||||||
DeviceSettingConfigItemModel.BuiltinItem.CommonBuiltinItem(
|
|
||||||
DeviceSettingId.DEVICE_SETTING_ID_ACTION_BUTTONS, highlighted = false, preferenceKey = "action_buttons"),
|
|
||||||
),
|
|
||||||
listOf(),
|
|
||||||
null))
|
|
||||||
|
|
||||||
val keys =
|
|
||||||
underTest.getVisiblePreferenceKeys(FragmentTypeModel.DeviceDetailsMainFragment)
|
|
||||||
|
|
||||||
assertThat(keys).containsExactly("bluetooth_device_header", "action_buttons")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun getVisiblePreferenceKeysForMainPage_noConfig_returnNull() {
|
|
||||||
testScope.runTest {
|
|
||||||
`when`(repository.getDeviceSettingsConfig(cachedDevice)).thenReturn(null)
|
|
||||||
|
|
||||||
val keys =
|
|
||||||
underTest.getVisiblePreferenceKeys(FragmentTypeModel.DeviceDetailsMainFragment)
|
|
||||||
|
|
||||||
assertThat(keys).isNull()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun getMenuItem_returnItem() {
|
fun getMenuItem_returnItem() {
|
||||||
testScope.runTest {
|
testScope.runTest {
|
||||||
@@ -187,7 +158,7 @@ class DeviceDetailsFragmentFormatterTest {
|
|||||||
underTest.updateLayout(FragmentTypeModel.DeviceDetailsMainFragment)
|
underTest.updateLayout(FragmentTypeModel.DeviceDetailsMainFragment)
|
||||||
|
|
||||||
assertThat(getDisplayedPreferences().mapNotNull { it.key })
|
assertThat(getDisplayedPreferences().mapNotNull { it.key })
|
||||||
.containsExactly("bluetooth_device_header", "action_buttons", "keyboard_settings")
|
.containsExactly("bluetooth_device_header", "action_buttons", "bluetooth_profiles")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,8 +173,8 @@ class DeviceDetailsFragmentFormatterTest {
|
|||||||
DeviceSettingId.DEVICE_SETTING_ID_HEADER,
|
DeviceSettingId.DEVICE_SETTING_ID_HEADER,
|
||||||
highlighted = false, preferenceKey = "bluetooth_device_header"),
|
highlighted = false, preferenceKey = "bluetooth_device_header"),
|
||||||
DeviceSettingConfigItemModel.BuiltinItem.CommonBuiltinItem(
|
DeviceSettingConfigItemModel.BuiltinItem.CommonBuiltinItem(
|
||||||
DeviceSettingId.DEVICE_SETTING_ID_KEYBOARD_SETTINGS,
|
DeviceSettingId.DEVICE_SETTING_ID_BLUETOOTH_PROFILES,
|
||||||
highlighted = false, preferenceKey = "keyboard_settings"),
|
highlighted = false, preferenceKey = "bluetooth_profiles"),
|
||||||
),
|
),
|
||||||
listOf(),
|
listOf(),
|
||||||
null))
|
null))
|
||||||
@@ -212,7 +183,7 @@ class DeviceDetailsFragmentFormatterTest {
|
|||||||
runCurrent()
|
runCurrent()
|
||||||
|
|
||||||
assertThat(getDisplayedPreferences().mapNotNull { it.key })
|
assertThat(getDisplayedPreferences().mapNotNull { it.key })
|
||||||
.containsExactly("bluetooth_device_header", "keyboard_settings")
|
.containsExactly("bluetooth_device_header", "bluetooth_profiles")
|
||||||
verify(featureFactory.metricsFeatureProvider)
|
verify(featureFactory.metricsFeatureProvider)
|
||||||
.action(
|
.action(
|
||||||
SettingsEnums.PAGE_UNKNOWN,
|
SettingsEnums.PAGE_UNKNOWN,
|
||||||
@@ -224,7 +195,7 @@ class DeviceDetailsFragmentFormatterTest {
|
|||||||
SettingsEnums.PAGE_UNKNOWN,
|
SettingsEnums.PAGE_UNKNOWN,
|
||||||
SettingsEnums.ACTION_BLUETOOTH_DEVICE_DETAILS_ITEM_SHOWN,
|
SettingsEnums.ACTION_BLUETOOTH_DEVICE_DETAILS_ITEM_SHOWN,
|
||||||
0,
|
0,
|
||||||
"keyboard_settings", 1)
|
"bluetooth_profiles", 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,9 +213,9 @@ class DeviceDetailsFragmentFormatterTest {
|
|||||||
DeviceSettingConfigItemModel.AppProvidedItem(
|
DeviceSettingConfigItemModel.AppProvidedItem(
|
||||||
DeviceSettingId.DEVICE_SETTING_ID_ANC, highlighted = false),
|
DeviceSettingId.DEVICE_SETTING_ID_ANC, highlighted = false),
|
||||||
DeviceSettingConfigItemModel.BuiltinItem.CommonBuiltinItem(
|
DeviceSettingConfigItemModel.BuiltinItem.CommonBuiltinItem(
|
||||||
DeviceSettingId.DEVICE_SETTING_ID_KEYBOARD_SETTINGS,
|
DeviceSettingId.DEVICE_SETTING_ID_BLUETOOTH_PROFILES,
|
||||||
highlighted = false,
|
highlighted = false,
|
||||||
preferenceKey = "keyboard_settings"),
|
preferenceKey = "bluetooth_profiles"),
|
||||||
),
|
),
|
||||||
listOf(),
|
listOf(),
|
||||||
null))
|
null))
|
||||||
@@ -273,7 +244,7 @@ class DeviceDetailsFragmentFormatterTest {
|
|||||||
.containsExactly(
|
.containsExactly(
|
||||||
"bluetooth_device_header",
|
"bluetooth_device_header",
|
||||||
"DEVICE_SETTING_${DeviceSettingId.DEVICE_SETTING_ID_ANC}",
|
"DEVICE_SETTING_${DeviceSettingId.DEVICE_SETTING_ID_ANC}",
|
||||||
"keyboard_settings")
|
"bluetooth_profiles")
|
||||||
verify(featureFactory.metricsFeatureProvider)
|
verify(featureFactory.metricsFeatureProvider)
|
||||||
.action(
|
.action(
|
||||||
SettingsEnums.PAGE_UNKNOWN,
|
SettingsEnums.PAGE_UNKNOWN,
|
||||||
|
Reference in New Issue
Block a user