From aaa040e08561f3765cdc9f325ac6510ed7d89855 Mon Sep 17 00:00:00 2001 From: Haijie Hong Date: Fri, 8 Nov 2024 21:53:49 +0800 Subject: [PATCH] Revert ANC and Spatial audio UI change BUG: 378016708 Test: atest DeviceDetailsFragmentFormatterTest Flag: com.android.settings.flags.enable_bluetooth_device_details_polish Change-Id: I390ff06ab11b16134d0656c9576670b319c46c74 --- .../bluetooth/BluetoothFeatureProvider.java | 9 - .../bluetooth/BluetoothFeatureProviderImpl.kt | 21 -- .../interactor/SpatialAudioInteractor.kt | 180 ----------- .../ui/composable/MultiTogglePreference.kt | 124 ++++++++ .../composable/MultiTogglePreferenceGroup.kt | 280 ------------------ .../ui/view/DeviceDetailsFragmentFormatter.kt | 20 +- .../BluetoothDeviceDetailsViewModel.kt | 44 +-- .../interactor/SpatialAudioInteractorTest.kt | 275 ----------------- .../DeviceDetailsFragmentFormatterTest.kt | 10 - .../BluetoothDeviceDetailsViewModelTest.kt | 43 +-- 10 files changed, 138 insertions(+), 868 deletions(-) delete mode 100644 src/com/android/settings/bluetooth/domain/interactor/SpatialAudioInteractor.kt create mode 100644 src/com/android/settings/bluetooth/ui/composable/MultiTogglePreference.kt delete mode 100644 src/com/android/settings/bluetooth/ui/composable/MultiTogglePreferenceGroup.kt delete mode 100644 tests/robotests/src/com/android/settings/bluetooth/domain/interactor/SpatialAudioInteractorTest.kt diff --git a/src/com/android/settings/bluetooth/BluetoothFeatureProvider.java b/src/com/android/settings/bluetooth/BluetoothFeatureProvider.java index 1bad5e56fa4..d87e6096e92 100644 --- a/src/com/android/settings/bluetooth/BluetoothFeatureProvider.java +++ b/src/com/android/settings/bluetooth/BluetoothFeatureProvider.java @@ -20,7 +20,6 @@ import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.ComponentName; import android.content.Context; -import android.media.AudioManager; import android.media.Spatializer; import android.net.Uri; @@ -28,7 +27,6 @@ import androidx.annotation.NonNull; import androidx.preference.Preference; import com.android.settings.SettingsPreferenceFragment; -import com.android.settings.bluetooth.domain.interactor.SpatialAudioInteractor; import com.android.settings.bluetooth.ui.view.DeviceDetailsFragmentFormatter; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.devicesettings.data.repository.DeviceSettingRepository; @@ -98,13 +96,6 @@ public interface BluetoothFeatureProvider { @NonNull BluetoothAdapter bluetoothAdapter, @NonNull CoroutineScope scope); - /** Gets spatial audio interactor. */ - @NonNull - SpatialAudioInteractor getSpatialAudioInteractor( - @NonNull Context context, - @NonNull AudioManager audioManager, - @NonNull CoroutineScope scope); - /** Gets device details fragment layout formatter. */ @NonNull DeviceDetailsFragmentFormatter getDeviceDetailsFragmentFormatter( diff --git a/src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.kt b/src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.kt index 6f967a2da6d..082c6932c91 100644 --- a/src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.kt +++ b/src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.kt @@ -22,20 +22,14 @@ import android.content.Context import android.media.AudioManager import android.media.Spatializer import android.net.Uri -import android.util.Log -import androidx.lifecycle.LifecycleCoroutineScope import androidx.preference.Preference import com.android.settings.SettingsPreferenceFragment -import com.android.settings.bluetooth.domain.interactor.SpatialAudioInteractor -import com.android.settings.bluetooth.domain.interactor.SpatialAudioInteractorImpl import com.android.settings.bluetooth.ui.view.DeviceDetailsFragmentFormatter import com.android.settings.bluetooth.ui.view.DeviceDetailsFragmentFormatterImpl 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.media.data.repository.SpatializerRepositoryImpl -import com.android.settingslib.media.domain.interactor.SpatializerInteractor import com.google.common.collect.ImmutableList import com.google.common.collect.ImmutableSet import kotlinx.coroutines.CoroutineScope @@ -82,21 +76,6 @@ open class BluetoothFeatureProviderImpl : BluetoothFeatureProvider { ): DeviceSettingRepository = DeviceSettingRepositoryImpl(context, bluetoothAdapter, scope, Dispatchers.IO) - override fun getSpatialAudioInteractor( - context: Context, - audioManager: AudioManager, - scope: CoroutineScope, - ): SpatialAudioInteractor { - return SpatialAudioInteractorImpl( - context, audioManager, - SpatializerInteractor( - SpatializerRepositoryImpl( - getSpatializer(context), - Dispatchers.IO - ) - ), scope, Dispatchers.IO) - } - override fun getDeviceDetailsFragmentFormatter( context: Context, fragment: SettingsPreferenceFragment, diff --git a/src/com/android/settings/bluetooth/domain/interactor/SpatialAudioInteractor.kt b/src/com/android/settings/bluetooth/domain/interactor/SpatialAudioInteractor.kt deleted file mode 100644 index cade566be6d..00000000000 --- a/src/com/android/settings/bluetooth/domain/interactor/SpatialAudioInteractor.kt +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings.bluetooth.domain.interactor - -import android.content.Context -import android.media.AudioManager -import android.util.Log -import com.android.settings.R -import com.android.settingslib.bluetooth.BluetoothUtils -import com.android.settingslib.bluetooth.CachedBluetoothDevice -import com.android.settingslib.bluetooth.devicesettings.DeviceSettingId -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 com.android.settingslib.bluetooth.devicesettings.shared.model.ToggleModel -import com.android.settingslib.media.domain.interactor.SpatializerInteractor -import kotlin.coroutines.CoroutineContext -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.channels.awaitClose -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.callbackFlow -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.flowOn -import kotlinx.coroutines.flow.onStart -import kotlinx.coroutines.flow.stateIn -import kotlinx.coroutines.launch - -/** Provides device setting for spatial audio. */ -interface SpatialAudioInteractor { - /** Gets device setting for spatial audio */ - fun getDeviceSetting(cachedDevice: CachedBluetoothDevice): Flow -} - -class SpatialAudioInteractorImpl( - private val context: Context, - private val audioManager: AudioManager, - private val spatializerInteractor: SpatializerInteractor, - private val coroutineScope: CoroutineScope, - private val backgroundCoroutineContext: CoroutineContext, -) : SpatialAudioInteractor { - private val spatialAudioOffToggle = - ToggleModel( - context.getString(R.string.spatial_audio_multi_toggle_off), - DeviceSettingIcon.ResourceIcon(R.drawable.ic_spatial_audio_off), - ) - private val spatialAudioOnToggle = - ToggleModel( - context.getString(R.string.spatial_audio_multi_toggle_on), - DeviceSettingIcon.ResourceIcon(R.drawable.ic_spatial_audio), - ) - private val headTrackingOnToggle = - ToggleModel( - context.getString(R.string.spatial_audio_multi_toggle_head_tracking_on), - DeviceSettingIcon.ResourceIcon(R.drawable.ic_head_tracking), - ) - private val changes = MutableSharedFlow() - - override fun getDeviceSetting(cachedDevice: CachedBluetoothDevice): Flow = - changes - .onStart { emit(Unit) } - .combine( - isDeviceConnected(cachedDevice), - ) { _, connected -> - if (connected) { - getSpatialAudioDeviceSettingModel(cachedDevice) - } else { - null - } - } - .flowOn(backgroundCoroutineContext) - .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), initialValue = null) - - private fun isDeviceConnected(cachedDevice: CachedBluetoothDevice): Flow = - callbackFlow { - val listener = - CachedBluetoothDevice.Callback { launch { send(cachedDevice.isConnected) } } - cachedDevice.registerCallback(context.mainExecutor, listener) - awaitClose { cachedDevice.unregisterCallback(listener) } - } - .onStart { emit(cachedDevice.isConnected) } - .flowOn(backgroundCoroutineContext) - - private suspend fun getSpatialAudioDeviceSettingModel( - cachedDevice: CachedBluetoothDevice - ): DeviceSettingModel? { - // TODO(b/343317785): use audio repository instead of calling AudioManager directly. - Log.i(TAG, "CachedDevice: $cachedDevice profiles: ${cachedDevice.profiles}") - val attributes = - BluetoothUtils.getAudioDeviceAttributesForSpatialAudio( - cachedDevice, - audioManager.getBluetoothAudioDeviceCategory(cachedDevice.address), - ) - ?: run { - Log.i(TAG, "No audio profiles in cachedDevice: ${cachedDevice.address}.") - return null - } - - Log.i(TAG, "Audio device attributes for ${cachedDevice.address}: $attributes.") - val spatialAudioAvailable = spatializerInteractor.isSpatialAudioAvailable(attributes) - if (!spatialAudioAvailable) { - Log.i(TAG, "Spatial audio is not available for ${cachedDevice.address}") - return null - } - val headTrackingAvailable = - spatialAudioAvailable && spatializerInteractor.isHeadTrackingAvailable(attributes) - val toggles = - if (headTrackingAvailable) { - listOf(spatialAudioOffToggle, spatialAudioOnToggle, headTrackingOnToggle) - } else { - listOf(spatialAudioOffToggle, spatialAudioOnToggle) - } - val spatialAudioEnabled = spatializerInteractor.isSpatialAudioEnabled(attributes) - val headTrackingEnabled = - spatialAudioEnabled && spatializerInteractor.isHeadTrackingEnabled(attributes) - - val activeIndex = - when { - headTrackingEnabled -> INDEX_HEAD_TRACKING_ENABLED - spatialAudioEnabled -> INDEX_SPATIAL_AUDIO_ON - else -> INDEX_SPATIAL_AUDIO_OFF - } - Log.i( - TAG, - "Head tracking available: $headTrackingAvailable, " + - "spatial audio enabled: $spatialAudioEnabled, " + - "head tracking enabled: $headTrackingEnabled", - ) - return DeviceSettingModel.MultiTogglePreference( - cachedDevice = cachedDevice, - id = DeviceSettingId.DEVICE_SETTING_ID_SPATIAL_AUDIO_MULTI_TOGGLE, - title = context.getString(R.string.spatial_audio_multi_toggle_title), - toggles = toggles, - isActive = spatialAudioEnabled, - state = DeviceSettingStateModel.MultiTogglePreferenceState(activeIndex), - isAllowedChangingState = true, - updateState = { newState -> - coroutineScope.launch(backgroundCoroutineContext) { - Log.i(TAG, "Update spatial audio state: $newState") - when (newState.selectedIndex) { - INDEX_SPATIAL_AUDIO_OFF -> { - spatializerInteractor.setSpatialAudioEnabled(attributes, false) - } - INDEX_SPATIAL_AUDIO_ON -> { - spatializerInteractor.setSpatialAudioEnabled(attributes, true) - spatializerInteractor.setHeadTrackingEnabled(attributes, false) - } - INDEX_HEAD_TRACKING_ENABLED -> { - spatializerInteractor.setSpatialAudioEnabled(attributes, true) - spatializerInteractor.setHeadTrackingEnabled(attributes, true) - } - } - changes.emit(Unit) - } - }, - ) - } - - companion object { - private const val TAG = "SpatialAudioInteractor" - private const val INDEX_SPATIAL_AUDIO_OFF = 0 - private const val INDEX_SPATIAL_AUDIO_ON = 1 - private const val INDEX_HEAD_TRACKING_ENABLED = 2 - } -} diff --git a/src/com/android/settings/bluetooth/ui/composable/MultiTogglePreference.kt b/src/com/android/settings/bluetooth/ui/composable/MultiTogglePreference.kt new file mode 100644 index 00000000000..b524c21e3c2 --- /dev/null +++ b/src/com/android/settings/bluetooth/ui/composable/MultiTogglePreference.kt @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.bluetooth.ui.composable + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.defaultMinSize +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.android.settings.bluetooth.ui.composable.Icon as DeviceSettingComposeIcon +import com.android.settings.bluetooth.ui.model.DeviceSettingPreferenceModel + +@Composable +fun MultiTogglePreference(pref: DeviceSettingPreferenceModel.MultiTogglePreference) { + Column(modifier = Modifier.padding(24.dp)) { + Row( + modifier = Modifier.fillMaxWidth().height(56.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceEvenly, + ) { + Box { + Row { + for ((idx, toggle) in pref.toggles.withIndex()) { + val selected = idx == pref.selectedIndex + Column( + modifier = Modifier.weight(1f) + .padding(start = if (idx == 0) 0.dp else 1.dp) + .height(56.dp) + .background( + Color.Transparent, + shape = RoundedCornerShape(12.dp), + ), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + val startCornerRadius = if (idx == 0) 12.dp else 0.dp + val endCornerRadius = if (idx == pref.toggles.size - 1) 12.dp else 0.dp + Button( + onClick = { pref.onSelectedChange(idx) }, + modifier = Modifier.fillMaxSize(), + enabled = pref.isAllowedChangingState, + colors = getButtonColors(selected), + shape = RoundedCornerShape( + startCornerRadius, + endCornerRadius, + endCornerRadius, + startCornerRadius, + ) + ) { + DeviceSettingComposeIcon( + toggle.icon, + modifier = Modifier.size(24.dp), + ) + } + } + } + } + } + } + Spacer(modifier = Modifier.height(12.dp)) + Row( + modifier = Modifier.fillMaxWidth().defaultMinSize(32.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceEvenly, + ) { + for (toggle in pref.toggles) { + Text( + text = toggle.label, + fontSize = 12.sp, + textAlign = TextAlign.Center, + overflow = TextOverflow.Visible, + modifier = Modifier.weight(1f).padding(horizontal = 8.dp), + ) + } + } + } +} + +@Composable +private fun getButtonColors(isActive: Boolean) = if (isActive) { + ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.primary, + contentColor = MaterialTheme.colorScheme.onPrimary, + ) +} else { + ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.surfaceVariant, + contentColor = MaterialTheme.colorScheme.onPrimaryContainer, + ) +} diff --git a/src/com/android/settings/bluetooth/ui/composable/MultiTogglePreferenceGroup.kt b/src/com/android/settings/bluetooth/ui/composable/MultiTogglePreferenceGroup.kt deleted file mode 100644 index 9743737f515..00000000000 --- a/src/com/android/settings/bluetooth/ui/composable/MultiTogglePreferenceGroup.kt +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings.bluetooth.ui.composable - -import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.defaultMinSize -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.offset -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.BasicAlertDialog -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.Card -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.LocalContentColor -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.geometry.Rect -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.layout.boundsInParent -import androidx.compose.ui.layout.onGloballyPositioned -import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.semantics.Role -import androidx.compose.ui.semantics.contentDescription -import androidx.compose.ui.semantics.role -import androidx.compose.ui.semantics.semantics -import androidx.compose.ui.semantics.toggleableState -import androidx.compose.ui.state.ToggleableState -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.compose.ui.window.DialogProperties -import com.android.settings.R -import com.android.settings.bluetooth.ui.model.DeviceSettingPreferenceModel -import com.android.settings.bluetooth.ui.composable.Icon as DeviceSettingComposeIcon -import com.android.settingslib.spa.framework.theme.SettingsDimension -import com.android.settingslib.spa.widget.dialog.getDialogWidth - -@Composable -fun MultiTogglePreferenceGroup( - preferenceModels: List, -) { - var settingIdForPopUp by remember { mutableStateOf(null) } - - settingIdForPopUp?.let { id -> - preferenceModels.find { it.id == id && it.isAllowedChangingState }?.let { - dialog(it) { settingIdForPopUp = null } - } ?: run { - settingIdForPopUp = null - } - } - - Row( - modifier = Modifier.padding(SettingsDimension.itemPadding), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(24.dp), - ) { - preferenceModels.forEach { preferenceModel -> - Column( - modifier = Modifier.weight(1f), - verticalArrangement = Arrangement.Top, - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Row { - Surface( - modifier = Modifier.height(64.dp), - shape = RoundedCornerShape(28.dp), - color = MaterialTheme.colorScheme.surface) { - Button( - modifier = - Modifier.fillMaxSize().padding(8.dp).semantics { - role = Role.Switch - toggleableState = - if (!preferenceModel.isAllowedChangingState) { - ToggleableState.Indeterminate - } else if (preferenceModel.isActive) { - ToggleableState.On - } else { - ToggleableState.Off - } - contentDescription = preferenceModel.title - }, - onClick = { settingIdForPopUp = preferenceModel.id }, - enabled = preferenceModel.isAllowedChangingState, - shape = RoundedCornerShape(20.dp), - colors = getButtonColors(preferenceModel.isActive), - contentPadding = PaddingValues(0.dp)) { - DeviceSettingComposeIcon( - preferenceModel.toggles[preferenceModel.selectedIndex] - .icon, - modifier = Modifier.size(24.dp)) - } - } - } - Row { Text(text = preferenceModel.title, fontSize = 12.sp) } - } - } - } -} - -@Composable -private fun getButtonColors(isActive: Boolean) = - if (isActive) { - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.tertiaryContainer, - contentColor = MaterialTheme.colorScheme.onTertiaryContainer, - ) - } else { - ButtonDefaults.buttonColors( - containerColor = Color.Transparent, - contentColor = MaterialTheme.colorScheme.onSurfaceVariant, - ) - } - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -private fun dialog( - multiTogglePreference: DeviceSettingPreferenceModel.MultiTogglePreference, - onDismiss: () -> Unit -) { - BasicAlertDialog( - onDismissRequest = { onDismiss() }, - modifier = Modifier.width(getDialogWidth()), - properties = DialogProperties(usePlatformDefaultWidth = false), - content = { - Card( - shape = RoundedCornerShape(28.dp), - modifier = Modifier.fillMaxWidth().height(192.dp), - content = { - Box { - Button( - onClick = { onDismiss() }, - modifier = Modifier.padding(8.dp).align(Alignment.TopEnd).size(48.dp), - contentPadding = PaddingValues(12.dp), - colors = - ButtonDefaults.buttonColors(containerColor = Color.Transparent), - ) { - Icon( - painterResource(id = R.drawable.ic_close), - null, - tint = MaterialTheme.colorScheme.inverseSurface) - } - Box(modifier = Modifier.padding(horizontal = 8.dp, vertical = 20.dp)) { - dialogContent(multiTogglePreference) - } - } - }, - ) - }) -} - -@Composable -private fun dialogContent(multiTogglePreference: DeviceSettingPreferenceModel.MultiTogglePreference) { - Column { - Row( - modifier = Modifier.fillMaxWidth().height(24.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceEvenly, - ) { - Text(text = multiTogglePreference.title, fontSize = 16.sp) - } - Spacer(modifier = Modifier.height(20.dp)) - var selectedRect by remember { mutableStateOf(null) } - val offset = - selectedRect?.let { rect -> - animateFloatAsState(targetValue = rect.left, finishedListener = {}).value - } - - Row( - modifier = - Modifier.fillMaxWidth() - .height(64.dp) - .background( - MaterialTheme.colorScheme.surface, shape = RoundedCornerShape(28.dp)), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceEvenly, - ) { - Box { - offset?.let { offset -> - with(LocalDensity.current) { - Box( - modifier = - Modifier.offset(offset.toDp(), 0.dp) - .height(selectedRect!!.height.toDp()) - .width(selectedRect!!.width.toDp()) - .background( - MaterialTheme.colorScheme.tertiaryContainer, - shape = RoundedCornerShape(20.dp))) - } - } - Row { - for ((idx, toggle) in multiTogglePreference.toggles.withIndex()) { - val selected = idx == multiTogglePreference.selectedIndex - Column( - modifier = - Modifier.weight(1f) - .padding(horizontal = 8.dp) - .height(48.dp) - .background( - Color.Transparent, shape = RoundedCornerShape(28.dp)) - .onGloballyPositioned { layoutCoordinates -> - if (selected) { - selectedRect = layoutCoordinates.boundsInParent() - } - }, - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Button( - onClick = { - multiTogglePreference.onSelectedChange(idx) - }, - modifier = Modifier.fillMaxSize(), - colors = - ButtonDefaults.buttonColors( - containerColor = Color.Transparent, - contentColor = LocalContentColor.current), - ) { - DeviceSettingComposeIcon( - toggle.icon, modifier = Modifier.size(24.dp)) - } - } - } - } - } - } - Spacer(modifier = Modifier.height(12.dp)) - Row( - modifier = Modifier.fillMaxWidth().defaultMinSize(32.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceEvenly, - ) { - for (toggle in multiTogglePreference.toggles) { - Text( - text = toggle.label, - fontSize = 12.sp, - textAlign = TextAlign.Center, - overflow = TextOverflow.Visible, - modifier = Modifier.weight(1f).padding(horizontal = 8.dp)) - } - } - } -} diff --git a/src/com/android/settings/bluetooth/ui/view/DeviceDetailsFragmentFormatter.kt b/src/com/android/settings/bluetooth/ui/view/DeviceDetailsFragmentFormatter.kt index e3ed7f597b5..23878da421b 100644 --- a/src/com/android/settings/bluetooth/ui/view/DeviceDetailsFragmentFormatter.kt +++ b/src/com/android/settings/bluetooth/ui/view/DeviceDetailsFragmentFormatter.kt @@ -43,7 +43,7 @@ import androidx.preference.Preference import com.android.settings.R import com.android.settings.SettingsPreferenceFragment import com.android.settings.bluetooth.ui.composable.Icon -import com.android.settings.bluetooth.ui.composable.MultiTogglePreferenceGroup +import com.android.settings.bluetooth.ui.composable.MultiTogglePreference import com.android.settings.bluetooth.ui.layout.DeviceSettingLayout import com.android.settings.bluetooth.ui.model.DeviceSettingPreferenceModel import com.android.settings.bluetooth.ui.model.FragmentTypeModel @@ -56,11 +56,14 @@ import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSetti import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigItemModel import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingIcon import com.android.settingslib.spa.framework.theme.SettingsDimension +import com.android.settingslib.spa.widget.button.ActionButton +import com.android.settingslib.spa.widget.button.ActionButtons 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.SwitchPreference import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel import com.android.settingslib.spa.widget.preference.TwoTargetSwitchPreference +import com.android.settingslib.spa.widget.scaffold.RegularScaffold import com.android.settingslib.spa.widget.ui.Footer import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -241,7 +244,7 @@ class DeviceDetailsFragmentFormatterImpl( buildSwitchPreference(setting) } is DeviceSettingPreferenceModel.MultiTogglePreference -> { - buildMultiTogglePreference(listOf(setting)) + buildMultiTogglePreference(setting) } is DeviceSettingPreferenceModel.FooterPreference -> { buildFooterPreference(setting) @@ -253,22 +256,15 @@ class DeviceDetailsFragmentFormatterImpl( null -> {} } } - else -> { - if (!settings.all { it is DeviceSettingPreferenceModel.MultiTogglePreference }) { - return - } - buildMultiTogglePreference( - settings.filterIsInstance() - ) - } + else -> {} } } @Composable private fun buildMultiTogglePreference( - prefs: List + pref: DeviceSettingPreferenceModel.MultiTogglePreference ) { - MultiTogglePreferenceGroup(prefs) + MultiTogglePreference(pref) } @Composable diff --git a/src/com/android/settings/bluetooth/ui/viewmodel/BluetoothDeviceDetailsViewModel.kt b/src/com/android/settings/bluetooth/ui/viewmodel/BluetoothDeviceDetailsViewModel.kt index 1ea2da3d2a3..8d3b8539b98 100644 --- a/src/com/android/settings/bluetooth/ui/viewmodel/BluetoothDeviceDetailsViewModel.kt +++ b/src/com/android/settings/bluetooth/ui/viewmodel/BluetoothDeviceDetailsViewModel.kt @@ -18,8 +18,6 @@ package com.android.settings.bluetooth.ui.viewmodel import android.app.Application import android.bluetooth.BluetoothAdapter -import android.media.AudioManager -import android.util.Log import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider @@ -60,20 +58,12 @@ class BluetoothDeviceDetailsViewModel( bluetoothAdapter, viewModelScope, ) - private val spatialAudioInteractor = - featureFactory.bluetoothFeatureProvider.getSpatialAudioInteractor( - application, - application.getSystemService(AudioManager::class.java), - viewModelScope, - ) private val items = viewModelScope.async(backgroundCoroutineContext, start = CoroutineStart.LAZY) { deviceSettingRepository.getDeviceSettingsConfig(cachedDevice) } - private val spatialAudioModel by lazy { spatialAudioInteractor.getDeviceSetting(cachedDevice) } - suspend fun getItems(fragment: FragmentTypeModel): List? = when (fragment) { is FragmentTypeModel.DeviceDetailsMainFragment -> items.await()?.mainItems @@ -95,11 +85,8 @@ class BluetoothDeviceDetailsViewModel( if (settingId == DeviceSettingId.DEVICE_SETTING_ID_MORE_SETTINGS) { return flowOf(DeviceSettingPreferenceModel.MoreSettingsPreference(settingId)) } - return when (settingId) { - DeviceSettingId.DEVICE_SETTING_ID_SPATIAL_AUDIO_MULTI_TOGGLE -> - spatialAudioModel - else -> deviceSettingRepository.getDeviceSetting(cachedDevice, settingId) - }.map { it?.toPreferenceModel() } + return deviceSettingRepository.getDeviceSetting(cachedDevice, settingId) + .map { it?.toPreferenceModel() } } private fun DeviceSettingModel.toPreferenceModel(): DeviceSettingPreferenceModel? { @@ -166,7 +153,6 @@ class BluetoothDeviceDetailsViewModel( val positionToSettingIds = combine(configDeviceSetting) { settings -> val positionMapping = mutableMapOf>() - var multiToggleSettingIds: MutableList? = null for (i in settings.indices) { val configItem = configItems[i] val setting = settings[i] @@ -174,35 +160,13 @@ class BluetoothDeviceDetailsViewModel( if (!isXmlPreference && setting == null) { continue } - if (setting !is DeviceSettingPreferenceModel.MultiTogglePreference) { - multiToggleSettingIds = null - positionMapping[i] = - listOf( - DeviceSettingLayoutColumn( - configItem.settingId, - configItem.highlighted, - ) - ) - continue - } - - if (multiToggleSettingIds != null) { - multiToggleSettingIds.add( + positionMapping[i] = + listOf( DeviceSettingLayoutColumn( configItem.settingId, configItem.highlighted, ) ) - } else { - multiToggleSettingIds = - mutableListOf( - DeviceSettingLayoutColumn( - configItem.settingId, - configItem.highlighted, - ) - ) - positionMapping[i] = multiToggleSettingIds - } } positionMapping } diff --git a/tests/robotests/src/com/android/settings/bluetooth/domain/interactor/SpatialAudioInteractorTest.kt b/tests/robotests/src/com/android/settings/bluetooth/domain/interactor/SpatialAudioInteractorTest.kt deleted file mode 100644 index 28e05810467..00000000000 --- a/tests/robotests/src/com/android/settings/bluetooth/domain/interactor/SpatialAudioInteractorTest.kt +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings.bluetooth.domain.interactor - -import android.bluetooth.BluetoothDevice -import android.bluetooth.BluetoothProfile -import android.content.Context -import android.media.AudioDeviceAttributes -import android.media.AudioDeviceInfo -import android.media.AudioManager -import androidx.test.core.app.ApplicationProvider -import com.android.settingslib.bluetooth.CachedBluetoothDevice -import com.android.settingslib.bluetooth.LeAudioProfile -import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingModel -import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingStateModel -import com.android.settingslib.media.data.repository.SpatializerRepository -import com.android.settingslib.media.domain.interactor.SpatializerInteractor -import com.google.common.truth.Truth.assertThat -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.Flow -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 -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.Mock -import org.mockito.Mockito.spy -import org.mockito.Mockito.times -import org.mockito.Mockito.verify -import org.mockito.Mockito.verifyNoInteractions -import org.mockito.Mockito.`when` -import org.mockito.junit.MockitoJUnit -import org.mockito.junit.MockitoRule -import org.robolectric.RobolectricTestRunner - -@OptIn(ExperimentalCoroutinesApi::class) -@RunWith(RobolectricTestRunner::class) -class SpatialAudioInteractorTest { - @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule() - - @Mock private lateinit var audioManager: AudioManager - @Mock private lateinit var cachedDevice: CachedBluetoothDevice - @Mock private lateinit var bluetoothDevice: BluetoothDevice - @Mock private lateinit var spatializerRepository: SpatializerRepository - @Mock private lateinit var leAudioProfile: LeAudioProfile - - private lateinit var underTest: SpatialAudioInteractor - private val testScope = TestScope() - - @Before - fun setUp() { - val context = spy(ApplicationProvider.getApplicationContext()) - `when`(cachedDevice.device).thenReturn(bluetoothDevice) - `when`(cachedDevice.address).thenReturn(BLUETOOTH_ADDRESS) - `when`(leAudioProfile.profileId).thenReturn(BluetoothProfile.LE_AUDIO) - underTest = - SpatialAudioInteractorImpl( - context, - audioManager, - SpatializerInteractor(spatializerRepository), - testScope.backgroundScope, - testScope.testScheduler) - } - - @Test - fun getDeviceSetting_noAudioProfile_returnNull() { - testScope.runTest { - `when`(cachedDevice.isConnected).thenReturn(true) - val setting = getLatestValue(underTest.getDeviceSetting(cachedDevice)) - - assertThat(setting).isNull() - verifyNoInteractions(spatializerRepository) - } - } - - @Test - fun getDeviceSetting_audioProfileNotEnabled_returnNull() { - testScope.runTest { - `when`(cachedDevice.isConnected).thenReturn(true) - `when`(cachedDevice.profiles).thenReturn(listOf(leAudioProfile)) - `when`(leAudioProfile.isEnabled(bluetoothDevice)).thenReturn(false) - - val setting = getLatestValue(underTest.getDeviceSetting(cachedDevice)) - - assertThat(setting).isNull() - verifyNoInteractions(spatializerRepository) - } - } - - @Test - fun getDeviceSetting_deviceNotConnected_returnNull() { - testScope.runTest { - `when`(cachedDevice.isConnected).thenReturn(false) - `when`(cachedDevice.profiles).thenReturn(listOf(leAudioProfile)) - `when`(leAudioProfile.isEnabled(bluetoothDevice)).thenReturn(true) - - val setting = getLatestValue(underTest.getDeviceSetting(cachedDevice)) - - assertThat(setting).isNull() - verifyNoInteractions(spatializerRepository) - } - } - - @Test - fun getDeviceSetting_spatialAudioNotSupported_returnNull() { - testScope.runTest { - `when`(cachedDevice.isConnected).thenReturn(true) - `when`(cachedDevice.profiles).thenReturn(listOf(leAudioProfile)) - `when`(leAudioProfile.isEnabled(bluetoothDevice)).thenReturn(true) - `when`( - spatializerRepository.isSpatialAudioAvailableForDevice( - BLE_AUDIO_DEVICE_ATTRIBUTES)) - .thenReturn(false) - - val setting = getLatestValue(underTest.getDeviceSetting(cachedDevice)) - - assertThat(setting).isNull() - } - } - - @Test - fun getDeviceSetting_spatialAudioSupported_returnTwoToggles() { - testScope.runTest { - `when`(cachedDevice.isConnected).thenReturn(true) - `when`(cachedDevice.profiles).thenReturn(listOf(leAudioProfile)) - `when`(leAudioProfile.isEnabled(bluetoothDevice)).thenReturn(true) - `when`( - spatializerRepository.isSpatialAudioAvailableForDevice( - BLE_AUDIO_DEVICE_ATTRIBUTES)) - .thenReturn(true) - `when`( - spatializerRepository.isHeadTrackingAvailableForDevice( - BLE_AUDIO_DEVICE_ATTRIBUTES)) - .thenReturn(false) - `when`(spatializerRepository.getSpatialAudioCompatibleDevices()) - .thenReturn(listOf(BLE_AUDIO_DEVICE_ATTRIBUTES)) - `when`(spatializerRepository.isHeadTrackingEnabled(BLE_AUDIO_DEVICE_ATTRIBUTES)) - .thenReturn(false) - - val setting = - getLatestValue(underTest.getDeviceSetting(cachedDevice)) - as DeviceSettingModel.MultiTogglePreference - - assertThat(setting).isNotNull() - assertThat(setting.toggles.size).isEqualTo(2) - assertThat(setting.state.selectedIndex).isEqualTo(1) - } - } - - @Test - fun getDeviceSetting_headTrackingSupported_returnThreeToggles() { - testScope.runTest { - `when`(cachedDevice.isConnected).thenReturn(true) - `when`(cachedDevice.profiles).thenReturn(listOf(leAudioProfile)) - `when`(leAudioProfile.isEnabled(bluetoothDevice)).thenReturn(true) - `when`( - spatializerRepository.isSpatialAudioAvailableForDevice( - BLE_AUDIO_DEVICE_ATTRIBUTES)) - .thenReturn(true) - `when`( - spatializerRepository.isHeadTrackingAvailableForDevice( - BLE_AUDIO_DEVICE_ATTRIBUTES)) - .thenReturn(true) - `when`(spatializerRepository.getSpatialAudioCompatibleDevices()) - .thenReturn(listOf(BLE_AUDIO_DEVICE_ATTRIBUTES)) - `when`(spatializerRepository.isHeadTrackingEnabled(BLE_AUDIO_DEVICE_ATTRIBUTES)) - .thenReturn(true) - - val setting = - getLatestValue(underTest.getDeviceSetting(cachedDevice)) - as DeviceSettingModel.MultiTogglePreference - - assertThat(setting).isNotNull() - assertThat(setting.toggles.size).isEqualTo(3) - assertThat(setting.state.selectedIndex).isEqualTo(2) - } - } - - @Test - fun getDeviceSetting_updateState_enableSpatialAudio() { - testScope.runTest { - `when`(cachedDevice.isConnected).thenReturn(true) - `when`(cachedDevice.profiles).thenReturn(listOf(leAudioProfile)) - `when`(leAudioProfile.isEnabled(bluetoothDevice)).thenReturn(true) - `when`( - spatializerRepository.isSpatialAudioAvailableForDevice( - BLE_AUDIO_DEVICE_ATTRIBUTES)) - .thenReturn(true) - `when`( - spatializerRepository.isHeadTrackingAvailableForDevice( - BLE_AUDIO_DEVICE_ATTRIBUTES)) - .thenReturn(true) - `when`(spatializerRepository.getSpatialAudioCompatibleDevices()).thenReturn(listOf()) - `when`(spatializerRepository.isHeadTrackingEnabled(BLE_AUDIO_DEVICE_ATTRIBUTES)) - .thenReturn(false) - - val setting = - getLatestValue(underTest.getDeviceSetting(cachedDevice)) - as DeviceSettingModel.MultiTogglePreference - setting.updateState(DeviceSettingStateModel.MultiTogglePreferenceState(2)) - runCurrent() - - assertThat(setting).isNotNull() - verify(spatializerRepository, times(1)) - .addSpatialAudioCompatibleDevice(BLE_AUDIO_DEVICE_ATTRIBUTES) - } - } - - @Test - fun getDeviceSetting_updateState_enableHeadTracking() { - testScope.runTest { - `when`(cachedDevice.isConnected).thenReturn(true) - `when`(cachedDevice.profiles).thenReturn(listOf(leAudioProfile)) - `when`(leAudioProfile.isEnabled(bluetoothDevice)).thenReturn(true) - `when`( - spatializerRepository.isSpatialAudioAvailableForDevice( - BLE_AUDIO_DEVICE_ATTRIBUTES)) - .thenReturn(true) - `when`( - spatializerRepository.isHeadTrackingAvailableForDevice( - BLE_AUDIO_DEVICE_ATTRIBUTES)) - .thenReturn(true) - `when`(spatializerRepository.getSpatialAudioCompatibleDevices()).thenReturn(listOf()) - `when`(spatializerRepository.isHeadTrackingEnabled(BLE_AUDIO_DEVICE_ATTRIBUTES)) - .thenReturn(false) - - val setting = - getLatestValue(underTest.getDeviceSetting(cachedDevice)) - as DeviceSettingModel.MultiTogglePreference - setting.updateState(DeviceSettingStateModel.MultiTogglePreferenceState(2)) - runCurrent() - - assertThat(setting).isNotNull() - verify(spatializerRepository, times(1)) - .addSpatialAudioCompatibleDevice(BLE_AUDIO_DEVICE_ATTRIBUTES) - verify(spatializerRepository, times(1)) - .setHeadTrackingEnabled(BLE_AUDIO_DEVICE_ATTRIBUTES, true) - } - } - - private fun getLatestValue(deviceSettingFlow: Flow): DeviceSettingModel? { - var latestValue: DeviceSettingModel? = null - deviceSettingFlow.onEach { latestValue = it }.launchIn(testScope.backgroundScope) - testScope.runCurrent() - return latestValue - } - - private companion object { - const val BLUETOOTH_ADDRESS = "12:34:56:78:12:34" - val BLE_AUDIO_DEVICE_ATTRIBUTES = - AudioDeviceAttributes( - AudioDeviceAttributes.ROLE_OUTPUT, - AudioDeviceInfo.TYPE_BLE_HEADSET, - BLUETOOTH_ADDRESS, - ) - } -} 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 1ea804449c8..bd56021e38d 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 @@ -20,14 +20,11 @@ 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 @@ -56,13 +53,11 @@ 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 @@ -74,7 +69,6 @@ class DeviceDetailsFragmentFormatterTest { @Mock private lateinit var cachedDevice: CachedBluetoothDevice @Mock private lateinit var bluetoothAdapter: BluetoothAdapter @Mock private lateinit var repository: DeviceSettingRepository - @Mock private lateinit var spatialAudioInteractor: SpatialAudioInteractor private lateinit var fragment: TestFragment private lateinit var underTest: DeviceDetailsFragmentFormatter @@ -90,10 +84,6 @@ class DeviceDetailsFragmentFormatterTest { featureFactory.bluetoothFeatureProvider.getDeviceSettingRepository( eq(context), eq(bluetoothAdapter), any())) .thenReturn(repository) - `when`( - featureFactory.bluetoothFeatureProvider.getSpatialAudioInteractor( - eq(context), any(AudioManager::class.java), any())) - .thenReturn(spatialAudioInteractor) fragmentActivity = Robolectric.setupActivity(FragmentActivity::class.java) assertThat(fragmentActivity.applicationContext).isNotNull() fragment = TestFragment(context) 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 6813d943499..caeea942f62 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 @@ -19,9 +19,7 @@ package com.android.settings.bluetooth.ui.viewmodel import android.app.Application import android.bluetooth.BluetoothAdapter import android.graphics.Bitmap -import android.media.AudioManager import androidx.test.core.app.ApplicationProvider -import com.android.settings.bluetooth.domain.interactor.SpatialAudioInteractor import com.android.settings.bluetooth.ui.layout.DeviceSettingLayout import com.android.settings.bluetooth.ui.model.DeviceSettingPreferenceModel import com.android.settings.bluetooth.ui.model.FragmentTypeModel @@ -68,8 +66,6 @@ class BluetoothDeviceDetailsViewModelTest { @Mock private lateinit var repository: DeviceSettingRepository - @Mock private lateinit var spatialAudioInteractor: SpatialAudioInteractor - private lateinit var underTest: BluetoothDeviceDetailsViewModel private lateinit var featureFactory: FakeFeatureFactory private val testScope = TestScope() @@ -84,11 +80,6 @@ class BluetoothDeviceDetailsViewModelTest { eq(application), eq(bluetoothAdapter), any() )) .thenReturn(repository) - `when`( - featureFactory.bluetoothFeatureProvider.getSpatialAudioInteractor( - eq(application), any(AudioManager::class.java), any() - )) - .thenReturn(spatialAudioInteractor) underTest = BluetoothDeviceDetailsViewModel( @@ -173,37 +164,6 @@ class BluetoothDeviceDetailsViewModelTest { } } - @Test - fun getDeviceSetting_spatialAudio_returnSpatialAudioInteractorResponse() { - testScope.runTest { - val pref = - buildMultiTogglePreference( - DeviceSettingId.DEVICE_SETTING_ID_SPATIAL_AUDIO_MULTI_TOGGLE) - `when`(repository.getDeviceSettingsConfig(cachedDevice)) - .thenReturn( - DeviceSettingConfigModel( - listOf( - BUILTIN_SETTING_ITEM_1, - buildRemoteSettingItem( - DeviceSettingId.DEVICE_SETTING_ID_SPATIAL_AUDIO_MULTI_TOGGLE), - ), - listOf(), - null)) - `when`(spatialAudioInteractor.getDeviceSetting(cachedDevice)).thenReturn(flowOf(pref)) - - var deviceSettingPreference: DeviceSettingPreferenceModel? = null - underTest - .getDeviceSetting( - cachedDevice, DeviceSettingId.DEVICE_SETTING_ID_SPATIAL_AUDIO_MULTI_TOGGLE) - .onEach { deviceSettingPreference = it } - .launchIn(testScope.backgroundScope) - runCurrent() - - assertThat(deviceSettingPreference?.id).isEqualTo(pref.id) - verify(spatialAudioInteractor, times(1)).getDeviceSetting(cachedDevice) - } - } - @Test fun getLayout_builtinDeviceSettings() { testScope.runTest { @@ -252,7 +212,8 @@ class BluetoothDeviceDetailsViewModelTest { .isEqualTo( listOf( listOf(DeviceSettingId.DEVICE_SETTING_ID_HEADER), - listOf(remoteSettingId1, remoteSettingId2), + listOf(remoteSettingId1), + listOf(remoteSettingId2), listOf(remoteSettingId3), )) }