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.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
@@ -109,28 +108,34 @@ public class BluetoothDetailsProfilesController extends BluetoothDetailsControll
|
||||
PreferenceFragmentCompat fragment,
|
||||
LocalBluetoothManager manager,
|
||||
CachedBluetoothDevice device,
|
||||
Lifecycle lifecycle,
|
||||
@Nullable List<String> invisibleProfiles,
|
||||
boolean hasExtraSpace) {
|
||||
Lifecycle lifecycle) {
|
||||
super(context, fragment, device, lifecycle);
|
||||
mManager = manager;
|
||||
mProfileManager = mManager.getProfileManager();
|
||||
mCachedDevice = device;
|
||||
mCachedDeviceGroup = Utils.findAllCachedBluetoothDevicesByGroupId(mManager, mCachedDevice);
|
||||
}
|
||||
|
||||
/** Sets the profiles to be hidden. */
|
||||
public void setInvisibleProfiles(List<String> invisibleProfiles) {
|
||||
if (invisibleProfiles != null) {
|
||||
mInvisibleProfiles = Set.copyOf(invisibleProfiles);
|
||||
}
|
||||
mHasExtraSpace = hasExtraSpace;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init(PreferenceScreen screen) {
|
||||
mProfilesContainer = (PreferenceCategory)screen.findPreference(getPreferenceKey());
|
||||
if (mHasExtraSpace) {
|
||||
/** 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
|
||||
protected void init(PreferenceScreen screen) {
|
||||
mProfilesContainer = (PreferenceCategory) screen.findPreference(getPreferenceKey());
|
||||
mProfilesContainer.setLayoutResource(R.layout.preference_bluetooth_profile_category);
|
||||
// Call refresh here even though it will get called later in onResume, to avoid the
|
||||
// list of switches appearing to "pop" into the page.
|
||||
refresh();
|
||||
|
@@ -61,7 +61,6 @@ import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -289,9 +288,12 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
|
||||
getController(
|
||||
SlicePreferenceController.class,
|
||||
controller -> {
|
||||
controller.setSliceUri(finalControlUri);
|
||||
controller.onStart();
|
||||
controller.displayPreference(getPreferenceScreen());
|
||||
if (getPreferenceScreen().findPreference(controller.getPreferenceKey())
|
||||
!= null) {
|
||||
controller.setSliceUri(finalControlUri);
|
||||
controller.onStart();
|
||||
controller.displayPreference(getPreferenceScreen());
|
||||
}
|
||||
});
|
||||
|
||||
// Temporarily fix the issue that the page will be automatically scrolled to a wrong
|
||||
@@ -352,9 +354,23 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(@NonNull Bundle savedInstanceState, @NonNull String rootKey) {
|
||||
super.onCreatePreferences(savedInstanceState, rootKey);
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -409,38 +425,8 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
|
||||
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
|
||||
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<>();
|
||||
|
||||
if (mCachedDevice != null) {
|
||||
@@ -459,7 +445,7 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
|
||||
controllers.add(new BluetoothDetailsSpatialAudioController(context, this, mCachedDevice,
|
||||
lifecycle));
|
||||
controllers.add(new BluetoothDetailsProfilesController(context, this, mManager,
|
||||
mCachedDevice, lifecycle, invisibleProfiles, invisibleProfiles == null));
|
||||
mCachedDevice, lifecycle));
|
||||
controllers.add(new BluetoothDetailsMacAddressController(context, this, mCachedDevice,
|
||||
lifecycle));
|
||||
controllers.add(new StylusDevicesController(context, mInputDevice, mCachedDevice,
|
||||
|
@@ -26,10 +26,11 @@ import android.net.Uri;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
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.devicesettings.data.repository.DeviceSettingRepository;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope;
|
||||
|
||||
@@ -100,7 +101,8 @@ public interface BluetoothFeatureProvider {
|
||||
@NonNull
|
||||
DeviceDetailsFragmentFormatter getDeviceDetailsFragmentFormatter(
|
||||
@NonNull Context context,
|
||||
@NonNull SettingsPreferenceFragment fragment,
|
||||
@NonNull DashboardFragment fragment,
|
||||
@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.net.Uri
|
||||
import androidx.preference.Preference
|
||||
import com.android.settings.SettingsPreferenceFragment
|
||||
import com.android.settings.bluetooth.ui.view.DeviceDetailsFragmentFormatter
|
||||
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.CachedBluetoothDevice
|
||||
import com.android.settingslib.bluetooth.devicesettings.data.repository.DeviceSettingRepository
|
||||
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.ImmutableSet
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -78,13 +79,15 @@ open class BluetoothFeatureProviderImpl : BluetoothFeatureProvider {
|
||||
|
||||
override fun getDeviceDetailsFragmentFormatter(
|
||||
context: Context,
|
||||
fragment: SettingsPreferenceFragment,
|
||||
fragment: DashboardFragment,
|
||||
bluetoothAdapter: BluetoothAdapter,
|
||||
cachedDevice: CachedBluetoothDevice
|
||||
cachedDevice: CachedBluetoothDevice,
|
||||
controllers: List<AbstractPreferenceController>,
|
||||
): DeviceDetailsFragmentFormatter {
|
||||
return DeviceDetailsFragmentFormatterImpl(
|
||||
context,
|
||||
fragment,
|
||||
controllers,
|
||||
bluetoothAdapter,
|
||||
cachedDevice,
|
||||
Dispatchers.IO
|
||||
|
@@ -45,7 +45,8 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.preference.Preference
|
||||
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.MultiTogglePreference
|
||||
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.viewmodel.BluetoothDeviceDetailsViewModel
|
||||
import com.android.settings.core.SubSettingLauncher
|
||||
import com.android.settings.dashboard.DashboardFragment
|
||||
import com.android.settings.overlay.FeatureFactory
|
||||
import com.android.settings.spa.preference.ComposePreference
|
||||
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.DeviceSettingConfigItemModel
|
||||
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.widget.preference.Preference as SpaPreference
|
||||
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.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/** Handles device details fragment layout according to config. */
|
||||
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. */
|
||||
fun updateLayout(fragmentType: FragmentTypeModel)
|
||||
|
||||
@@ -104,7 +105,8 @@ interface DeviceDetailsFragmentFormatter {
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class DeviceDetailsFragmentFormatterImpl(
|
||||
private val context: Context,
|
||||
private val fragment: SettingsPreferenceFragment,
|
||||
private val fragment: DashboardFragment,
|
||||
controllers: List<AbstractPreferenceController>,
|
||||
private val bluetoothAdapter: BluetoothAdapter,
|
||||
private val cachedDevice: CachedBluetoothDevice,
|
||||
private val backgroundCoroutineContext: CoroutineContext,
|
||||
@@ -112,40 +114,32 @@ class DeviceDetailsFragmentFormatterImpl(
|
||||
private val metricsFeatureProvider = FeatureFactory.featureFactory.metricsFeatureProvider
|
||||
private val prefVisibility = mutableMapOf<String, MutableStateFlow<Boolean>>()
|
||||
private val prefVisibilityJobs = mutableListOf<Job>()
|
||||
private var isLoading = false
|
||||
private var prefKeyToController: Map<String, AbstractPreferenceController> =
|
||||
controllers.associateBy { it.preferenceKey }
|
||||
|
||||
private val viewModel: BluetoothDeviceDetailsViewModel =
|
||||
ViewModelProvider(
|
||||
fragment,
|
||||
BluetoothDeviceDetailsViewModel.Factory(
|
||||
fragment.requireActivity().application,
|
||||
bluetoothAdapter,
|
||||
cachedDevice,
|
||||
backgroundCoroutineContext,
|
||||
),
|
||||
)
|
||||
fragment,
|
||||
BluetoothDeviceDetailsViewModel.Factory(
|
||||
fragment.requireActivity().application,
|
||||
bluetoothAdapter,
|
||||
cachedDevice,
|
||||
backgroundCoroutineContext,
|
||||
),
|
||||
)
|
||||
.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. */
|
||||
override fun updateLayout(fragmentType: FragmentTypeModel) = runBlocking {
|
||||
val items = viewModel.getItems(fragmentType) ?: return@runBlocking
|
||||
val layout = viewModel.getLayout(fragmentType) ?: return@runBlocking
|
||||
override fun updateLayout(fragmentType: FragmentTypeModel) {
|
||||
fragment.setLoading(true, false)
|
||||
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 =
|
||||
items
|
||||
@@ -156,21 +150,21 @@ class DeviceDetailsFragmentFormatterImpl(
|
||||
for (i in 0 until fragment.preferenceScreen.preferenceCount) {
|
||||
val pref = fragment.preferenceScreen.getPreference(i)
|
||||
prefKeyToSettingId[pref.key]?.let { id -> settingIdToXmlPreferences[id] = pref }
|
||||
if (pref.key !in prefKeyToSettingId) {
|
||||
getController(pref.key)?.let { disableController(it) }
|
||||
}
|
||||
}
|
||||
fragment.preferenceScreen.removeAll()
|
||||
for (job in prefVisibilityJobs) {
|
||||
job.cancel()
|
||||
}
|
||||
prefVisibilityJobs.clear()
|
||||
|
||||
for (row in items.indices) {
|
||||
val settingId = items[row].settingId
|
||||
val settingItem = items[row]
|
||||
val settingId = settingItem.settingId
|
||||
if (settingIdToXmlPreferences.containsKey(settingId)) {
|
||||
fragment.preferenceScreen.addPreference(
|
||||
settingIdToXmlPreferences[settingId]!!
|
||||
.apply { order = row }
|
||||
.also { logItemShown(it.key, it.isVisible) }
|
||||
)
|
||||
val pref = settingIdToXmlPreferences[settingId]!!.apply { order = row }
|
||||
fragment.preferenceScreen.addPreference(pref)
|
||||
} else {
|
||||
val prefKey = getPreferenceKey(settingId)
|
||||
prefVisibilityJobs.add(
|
||||
@@ -195,6 +189,29 @@ class DeviceDetailsFragmentFormatterImpl(
|
||||
isSelectable = false
|
||||
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(
|
||||
@@ -232,14 +249,14 @@ class DeviceDetailsFragmentFormatterImpl(
|
||||
@Composable
|
||||
private fun buildPreference(layout: DeviceSettingLayout, row: Int, prefKey: String) {
|
||||
val contents by
|
||||
remember(row) { getDevicesSettingForRow(layout, row) }
|
||||
.collectAsStateWithLifecycle(initialValue = listOf())
|
||||
remember(row) { getDevicesSettingForRow(layout, row) }
|
||||
.collectAsStateWithLifecycle(initialValue = listOf())
|
||||
|
||||
val highlighted by
|
||||
remember(row) {
|
||||
layout.rows[row].columns.map { columns -> columns.any { it.highlighted } }
|
||||
}
|
||||
.collectAsStateWithLifecycle(initialValue = false)
|
||||
remember(row) {
|
||||
layout.rows[row].columns.map { columns -> columns.any { it.highlighted } }
|
||||
}
|
||||
.collectAsStateWithLifecycle(initialValue = false)
|
||||
|
||||
val settings = contents
|
||||
AnimatedVisibility(visible = settings.isNotEmpty(), enter = fadeIn(), exit = fadeOut()) {
|
||||
@@ -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 companion object {
|
||||
|
@@ -25,6 +25,7 @@ import android.graphics.PorterDuff
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.android.settings.R
|
||||
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.FragmentTypeModel
|
||||
import com.android.settings.dashboard.DashboardFragment
|
||||
import com.android.settings.flags.Flags
|
||||
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
|
||||
@@ -88,17 +89,29 @@ class DeviceDetailsMoreSettingsFragment : DashboardFragment() {
|
||||
return R.xml.bluetooth_device_more_settings_fragment
|
||||
}
|
||||
|
||||
override fun addPreferenceController(controller: AbstractPreferenceController) {
|
||||
val keys: List<String>? =
|
||||
formatter.getVisiblePreferenceKeys(FragmentTypeModel.DeviceDetailsMoreSettingsFragment)
|
||||
val lifecycle = settingsLifecycle
|
||||
if (keys == null || keys.contains(controller.preferenceKey)) {
|
||||
super.addPreferenceController(controller)
|
||||
} else if (controller is LifecycleObserver) {
|
||||
lifecycle.removeObserver((controller as LifecycleObserver))
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
if (!this::formatter.isInitialized) {
|
||||
val controllers = preferenceControllers.stream()
|
||||
.flatMap { obj: List<AbstractPreferenceController?> -> obj.stream() }
|
||||
.toList()
|
||||
val bluetoothManager = requireContext().getSystemService(BluetoothManager::class.java)
|
||||
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? {
|
||||
val bluetoothAddress = arguments?.getString(KEY_DEVICE_ADDRESS) ?: return null
|
||||
localBluetoothManager = Utils.getLocalBtManager(context) ?: return null
|
||||
@@ -107,32 +120,13 @@ class DeviceDetailsMoreSettingsFragment : DashboardFragment() {
|
||||
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> {
|
||||
val bluetoothManager = context.getSystemService(BluetoothManager::class.java)
|
||||
cachedDevice =
|
||||
getCachedDevice()
|
||||
?: run {
|
||||
finish()
|
||||
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(
|
||||
BluetoothDetailsProfilesController(
|
||||
context,
|
||||
@@ -140,10 +134,6 @@ class DeviceDetailsMoreSettingsFragment : DashboardFragment() {
|
||||
localBluetoothManager,
|
||||
cachedDevice,
|
||||
settingsLifecycle,
|
||||
formatter.getInvisibleBluetoothProfiles(
|
||||
FragmentTypeModel.DeviceDetailsMoreSettingsFragment
|
||||
),
|
||||
false,
|
||||
),
|
||||
BluetoothDetailsAudioDeviceTypeController(
|
||||
context,
|
||||
|
Reference in New Issue
Block a user