Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fcc3c273 authored by Haijie Hong's avatar Haijie Hong Committed by Android (Google) Code Review
Browse files

Merge "Make bluetooth profile toggles configurable" into main

parents 40bdf7db ced629eb
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
/*
 * 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.settingslib.bluetooth.devicesettings

/** The contract between the device settings provider services and Settings. */
object DeviceSettingContract {
    const val INVISIBLE_PROFILES = "INVISIBLE_PROFILES"
}
+15 −2
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.text.TextUtils
import com.android.settingslib.bluetooth.CachedBluetoothDevice
import com.android.settingslib.bluetooth.devicesettings.ActionSwitchPreference
import com.android.settingslib.bluetooth.devicesettings.DeviceSetting
import com.android.settingslib.bluetooth.devicesettings.DeviceSettingContract
import com.android.settingslib.bluetooth.devicesettings.DeviceSettingId
import com.android.settingslib.bluetooth.devicesettings.DeviceSettingItem
import com.android.settingslib.bluetooth.devicesettings.DeviceSettingsConfig
@@ -30,6 +31,9 @@ import com.android.settingslib.bluetooth.devicesettings.DeviceSettingHelpPrefere
import com.android.settingslib.bluetooth.devicesettings.MultiTogglePreference
import com.android.settingslib.bluetooth.devicesettings.ToggleInfo
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigItemModel
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigItemModel.AppProvidedItem
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigItemModel.BuiltinItem.BluetoothProfilesItem
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigItemModel.BuiltinItem.CommonBuiltinItem
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigModel
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingIcon
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingModel
@@ -103,9 +107,18 @@ class DeviceSettingRepositoryImpl(

    private fun DeviceSettingItem.toModel(): DeviceSettingConfigItemModel {
        return if (!TextUtils.isEmpty(preferenceKey)) {
            DeviceSettingConfigItemModel.BuiltinItem(settingId, preferenceKey!!)
            if (settingId == DeviceSettingId.DEVICE_SETTING_ID_BLUETOOTH_PROFILES) {
                BluetoothProfilesItem(
                    settingId,
                    preferenceKey!!,
                    extras.getStringArrayList(DeviceSettingContract.INVISIBLE_PROFILES)
                        ?: emptyList()
                )
            } else {
                CommonBuiltinItem(settingId, preferenceKey!!)
            }
        } else {
            DeviceSettingConfigItemModel.AppProvidedItem(settingId)
            AppProvidedItem(settingId)
        }
    }

+8 −1
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.content.Intent
import android.content.ServiceConnection
import android.os.IBinder
import android.os.IInterface
import android.text.TextUtils
import android.util.Log
import com.android.settingslib.bluetooth.BluetoothUtils
import com.android.settingslib.bluetooth.CachedBluetoothDevice
@@ -84,6 +85,10 @@ class DeviceSettingServiceConnection(
                }
                setAction(intentAction)
            }

        fun isValid(): Boolean {
            return !TextUtils.isEmpty(packageName) && !TextUtils.isEmpty(intentAction)
        }
    }

    private var isServiceEnabled =
@@ -96,7 +101,8 @@ class DeviceSettingServiceConnection(
                    } else if (allStatus.all { it is ServiceConnectionStatus.Connected }) {
                        allStatus
                            .filterIsInstance<
                                ServiceConnectionStatus.Connected<IDeviceSettingsProviderService>
                                ServiceConnectionStatus.Connected<
                                        IDeviceSettingsProviderService>
                            >()
                            .all { it.service.serviceStatus?.enabled == true }
                    } else {
@@ -215,6 +221,7 @@ class DeviceSettingServiceConnection(
                    )
                }
            }
            ?.filter { it.isValid() }
            ?.distinct()
            ?.associateBy(
                { it },
+17 −4
Original line number Diff line number Diff line
@@ -36,10 +36,23 @@ sealed interface DeviceSettingConfigItemModel {
    @DeviceSettingId val settingId: Int

    /** A built-in item in Settings. */
    data class BuiltinItem(
    sealed interface BuiltinItem : DeviceSettingConfigItemModel {
        @DeviceSettingId override val settingId: Int
        val preferenceKey: String

        /** A general built-in item in Settings. */
        data class CommonBuiltinItem(
            @DeviceSettingId override val settingId: Int,
            override val preferenceKey: String,
        ) : BuiltinItem

        /** A bluetooth profiles in Settings. */
        data class BluetoothProfilesItem(
            @DeviceSettingId override val settingId: Int,
        val preferenceKey: String?
    ) : DeviceSettingConfigItemModel
            override val preferenceKey: String,
            val invisibleProfiles: List<String>,
        ) : BuiltinItem
    }

    /** A remote item provided by other apps. */
    data class AppProvidedItem(@DeviceSettingId override val settingId: Int) :
+105 −74
Original line number Diff line number Diff line
@@ -91,7 +91,9 @@ class DeviceSettingRepositoryTest {
        `when`(cachedDevice.address).thenReturn(BLUETOOTH_ADDRESS)
        `when`(
                bluetoothDevice.getMetadata(
                    DeviceSettingServiceConnection.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
                    DeviceSettingServiceConnection.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS
                )
            )
            .thenReturn(BLUETOOTH_DEVICE_METADATA.toByteArray())

        `when`(configService.queryLocalInterface(anyString())).thenReturn(configService)
@@ -114,7 +116,8 @@ class DeviceSettingRepositoryTest {
                    connection.onServiceConnected(
                        ComponentName(
                            SETTING_PROVIDER_SERVICE_PACKAGE_NAME_1,
                            SETTING_PROVIDER_SERVICE_CLASS_NAME_1),
                            SETTING_PROVIDER_SERVICE_CLASS_NAME_1,
                        ),
                        settingProviderService1,
                    )
                SETTING_PROVIDER_SERVICE_INTENT_ACTION_2 ->
@@ -146,16 +149,24 @@ class DeviceSettingRepositoryTest {
    fun getDeviceSettingsConfig_withMetadata_success() {
        testScope.runTest {
            `when`(configService.getDeviceSettingsConfig(any())).thenReturn(DEVICE_SETTING_CONFIG)
            `when`(settingProviderService1.serviceStatus).thenReturn(
                DeviceSettingsProviderServiceStatus(true)
            )
            `when`(settingProviderService2.serviceStatus).thenReturn(
                DeviceSettingsProviderServiceStatus(true)
            )
            `when`(settingProviderService1.serviceStatus)
                .thenReturn(DeviceSettingsProviderServiceStatus(true))
            `when`(settingProviderService2.serviceStatus)
                .thenReturn(DeviceSettingsProviderServiceStatus(true))

            val config = underTest.getDeviceSettingsConfig(cachedDevice)

            assertConfig(config!!, DEVICE_SETTING_CONFIG)
            assertThat(config.mainItems[0])
                .isInstanceOf(DeviceSettingConfigItemModel.AppProvidedItem::class.java)
            assertThat(config.mainItems[1])
                .isInstanceOf(
                    DeviceSettingConfigItemModel.BuiltinItem.CommonBuiltinItem::class.java
                )
            assertThat(config.mainItems[2])
                .isInstanceOf(
                    DeviceSettingConfigItemModel.BuiltinItem.BluetoothProfilesItem::class.java
                )
        }
    }

@@ -164,15 +175,15 @@ class DeviceSettingRepositoryTest {
        testScope.runTest {
            `when`(
                    bluetoothDevice.getMetadata(
                    DeviceSettingServiceConnection.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
                .thenReturn("".toByteArray())
            `when`(configService.getDeviceSettingsConfig(any())).thenReturn(DEVICE_SETTING_CONFIG)
            `when`(settingProviderService1.serviceStatus).thenReturn(
                DeviceSettingsProviderServiceStatus(true)
                        DeviceSettingServiceConnection.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS
                    )
            `when`(settingProviderService2.serviceStatus).thenReturn(
                DeviceSettingsProviderServiceStatus(true)
                )
                .thenReturn("".toByteArray())
            `when`(configService.getDeviceSettingsConfig(any())).thenReturn(DEVICE_SETTING_CONFIG)
            `when`(settingProviderService1.serviceStatus)
                .thenReturn(DeviceSettingsProviderServiceStatus(true))
            `when`(settingProviderService2.serviceStatus)
                .thenReturn(DeviceSettingsProviderServiceStatus(true))

            val config = underTest.getDeviceSettingsConfig(cachedDevice)

@@ -184,12 +195,10 @@ class DeviceSettingRepositoryTest {
    fun getDeviceSettingsConfig_providerServiceNotEnabled_returnNull() {
        testScope.runTest {
            `when`(configService.getDeviceSettingsConfig(any())).thenReturn(DEVICE_SETTING_CONFIG)
            `when`(settingProviderService1.serviceStatus).thenReturn(
                DeviceSettingsProviderServiceStatus(false)
            )
            `when`(settingProviderService2.serviceStatus).thenReturn(
                DeviceSettingsProviderServiceStatus(true)
            )
            `when`(settingProviderService1.serviceStatus)
                .thenReturn(DeviceSettingsProviderServiceStatus(false))
            `when`(settingProviderService2.serviceStatus)
                .thenReturn(DeviceSettingsProviderServiceStatus(true))

            val config = underTest.getDeviceSettingsConfig(cachedDevice)

@@ -219,12 +228,10 @@ class DeviceSettingRepositoryTest {
                    .getArgument<IDeviceSettingsListener>(1)
                    .onDeviceSettingsChanged(listOf(DEVICE_SETTING_1))
            }
            `when`(settingProviderService1.serviceStatus).thenReturn(
                DeviceSettingsProviderServiceStatus(true)
            )
            `when`(settingProviderService2.serviceStatus).thenReturn(
                DeviceSettingsProviderServiceStatus(true)
            )
            `when`(settingProviderService1.serviceStatus)
                .thenReturn(DeviceSettingsProviderServiceStatus(true))
            `when`(settingProviderService2.serviceStatus)
                .thenReturn(DeviceSettingsProviderServiceStatus(true))
            var setting: DeviceSettingModel? = null

            underTest
@@ -247,12 +254,10 @@ class DeviceSettingRepositoryTest {
                    .getArgument<IDeviceSettingsListener>(1)
                    .onDeviceSettingsChanged(listOf(DEVICE_SETTING_2))
            }
            `when`(settingProviderService1.serviceStatus).thenReturn(
                DeviceSettingsProviderServiceStatus(true)
            )
            `when`(settingProviderService2.serviceStatus).thenReturn(
                DeviceSettingsProviderServiceStatus(true)
            )
            `when`(settingProviderService1.serviceStatus)
                .thenReturn(DeviceSettingsProviderServiceStatus(true))
            `when`(settingProviderService2.serviceStatus)
                .thenReturn(DeviceSettingsProviderServiceStatus(true))
            var setting: DeviceSettingModel? = null

            underTest
@@ -275,12 +280,10 @@ class DeviceSettingRepositoryTest {
                    .getArgument<IDeviceSettingsListener>(1)
                    .onDeviceSettingsChanged(listOf(DEVICE_SETTING_HELP))
            }
            `when`(settingProviderService1.serviceStatus).thenReturn(
                DeviceSettingsProviderServiceStatus(true)
            )
            `when`(settingProviderService2.serviceStatus).thenReturn(
                DeviceSettingsProviderServiceStatus(true)
            )
            `when`(settingProviderService1.serviceStatus)
                .thenReturn(DeviceSettingsProviderServiceStatus(true))
            `when`(settingProviderService2.serviceStatus)
                .thenReturn(DeviceSettingsProviderServiceStatus(true))
            var setting: DeviceSettingModel? = null

            underTest
@@ -324,12 +327,10 @@ class DeviceSettingRepositoryTest {
                    .getArgument<IDeviceSettingsListener>(1)
                    .onDeviceSettingsChanged(listOf(DEVICE_SETTING_1))
            }
            `when`(settingProviderService1.serviceStatus).thenReturn(
                DeviceSettingsProviderServiceStatus(true)
            )
            `when`(settingProviderService2.serviceStatus).thenReturn(
                DeviceSettingsProviderServiceStatus(true)
            )
            `when`(settingProviderService1.serviceStatus)
                .thenReturn(DeviceSettingsProviderServiceStatus(true))
            `when`(settingProviderService2.serviceStatus)
                .thenReturn(DeviceSettingsProviderServiceStatus(true))
            var setting: DeviceSettingModel? = null

            underTest
@@ -347,8 +348,10 @@ class DeviceSettingRepositoryTest {
                    DeviceSettingState.Builder()
                        .setSettingId(DeviceSettingId.DEVICE_SETTING_ID_HEADER)
                        .setPreferenceState(
                            ActionSwitchPreferenceState.Builder().setChecked(false).build())
                        .build())
                            ActionSwitchPreferenceState.Builder().setChecked(false).build()
                        )
                        .build(),
                )
        }
    }

@@ -362,12 +365,10 @@ class DeviceSettingRepositoryTest {
                    .getArgument<IDeviceSettingsListener>(1)
                    .onDeviceSettingsChanged(listOf(DEVICE_SETTING_2))
            }
            `when`(settingProviderService1.serviceStatus).thenReturn(
                DeviceSettingsProviderServiceStatus(true)
            )
            `when`(settingProviderService2.serviceStatus).thenReturn(
                DeviceSettingsProviderServiceStatus(true)
            )
            `when`(settingProviderService1.serviceStatus)
                .thenReturn(DeviceSettingsProviderServiceStatus(true))
            `when`(settingProviderService2.serviceStatus)
                .thenReturn(DeviceSettingsProviderServiceStatus(true))
            var setting: DeviceSettingModel? = null

            underTest
@@ -385,8 +386,10 @@ class DeviceSettingRepositoryTest {
                    DeviceSettingState.Builder()
                        .setSettingId(DeviceSettingId.DEVICE_SETTING_ID_ANC)
                        .setPreferenceState(
                            MultiTogglePreferenceState.Builder().setState(2).build())
                        .build())
                            MultiTogglePreferenceState.Builder().setState(2).build()
                        )
                        .build(),
                )
        }
    }

@@ -437,7 +440,7 @@ class DeviceSettingRepositoryTest {

    private fun assertConfig(
        actual: DeviceSettingConfigModel,
        serviceResponse: DeviceSettingsConfig
        serviceResponse: DeviceSettingsConfig,
    ) {
        assertThat(actual.mainItems.size).isEqualTo(serviceResponse.mainContentItems.size)
        for (i in 0..<actual.mainItems.size) {
@@ -451,7 +454,7 @@ class DeviceSettingRepositoryTest {

    private fun assertConfigItem(
        actual: DeviceSettingConfigItemModel,
        serviceResponse: DeviceSettingItem
        serviceResponse: DeviceSettingItem,
    ) {
        assertThat(actual.settingId).isEqualTo(serviceResponse.settingId)
    }
@@ -485,24 +488,43 @@ class DeviceSettingRepositoryTest {
                "</DEVICE_SETTINGS_CONFIG_ACTION>"
        val DEVICE_INFO = DeviceInfo.Builder().setBluetoothAddress(BLUETOOTH_ADDRESS).build()
        const val DEVICE_SETTING_ID_HELP = 12345
        val DEVICE_SETTING_ITEM_1 =
        val DEVICE_SETTING_APP_PROVIDED_ITEM_1 =
            DeviceSettingItem(
                DeviceSettingId.DEVICE_SETTING_ID_HEADER,
                SETTING_PROVIDER_SERVICE_PACKAGE_NAME_1,
                SETTING_PROVIDER_SERVICE_CLASS_NAME_1,
                SETTING_PROVIDER_SERVICE_INTENT_ACTION_1)
        val DEVICE_SETTING_ITEM_2 =
                SETTING_PROVIDER_SERVICE_INTENT_ACTION_1,
            )
        val DEVICE_SETTING_APP_PROVIDED_ITEM_2 =
            DeviceSettingItem(
                DeviceSettingId.DEVICE_SETTING_ID_ANC,
                SETTING_PROVIDER_SERVICE_PACKAGE_NAME_2,
                SETTING_PROVIDER_SERVICE_CLASS_NAME_2,
                SETTING_PROVIDER_SERVICE_INTENT_ACTION_2)
                SETTING_PROVIDER_SERVICE_INTENT_ACTION_2,
            )
        val DEVICE_SETTING_BUILT_IN_ITEM =
            DeviceSettingItem(
                DeviceSettingId.DEVICE_SETTING_ID_BLUETOOTH_AUDIO_DEVICE_TYPE_GROUP,
                "",
                "",
                "",
                "device_type",
            )
        val DEVICE_SETTING_BUILT_IN_BT_PROFILES_ITEM =
            DeviceSettingItem(
                DeviceSettingId.DEVICE_SETTING_ID_BLUETOOTH_PROFILES,
                "",
                "",
                "",
                "bluetooth_profiles",
            )
        val DEVICE_SETTING_HELP_ITEM =
            DeviceSettingItem(
                DEVICE_SETTING_ID_HELP,
                SETTING_PROVIDER_SERVICE_PACKAGE_NAME_2,
                SETTING_PROVIDER_SERVICE_CLASS_NAME_2,
                SETTING_PROVIDER_SERVICE_INTENT_ACTION_2)
                SETTING_PROVIDER_SERVICE_INTENT_ACTION_2,
            )
        val DEVICE_SETTING_1 =
            DeviceSetting.Builder()
                .setSettingId(DeviceSettingId.DEVICE_SETTING_ID_HEADER)
@@ -511,7 +533,8 @@ class DeviceSettingRepositoryTest {
                        .setTitle("title1")
                        .setHasSwitch(true)
                        .setAllowedChangingState(true)
                        .build())
                        .build()
                )
                .build()
        val DEVICE_SETTING_2 =
            DeviceSetting.Builder()
@@ -524,22 +547,30 @@ class DeviceSettingRepositoryTest {
                            ToggleInfo.Builder()
                                .setLabel("label1")
                                .setIcon(Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888))
                                .build())
                                .build()
                        )
                        .addToggleInfo(
                            ToggleInfo.Builder()
                                .setLabel("label2")
                                .setIcon(Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888))
                                .build())
                        .build())
                                .build()
        val DEVICE_SETTING_HELP = DeviceSetting.Builder()
                        )
                        .build()
                )
                .build()
        val DEVICE_SETTING_HELP =
            DeviceSetting.Builder()
                .setSettingId(DEVICE_SETTING_ID_HELP)
                .setPreference(DeviceSettingHelpPreference.Builder().setIntent(Intent()).build())
                .build()
        val DEVICE_SETTING_CONFIG =
            DeviceSettingsConfig(
                listOf(DEVICE_SETTING_ITEM_1),
                listOf(DEVICE_SETTING_ITEM_2),
                listOf(
                    DEVICE_SETTING_APP_PROVIDED_ITEM_1,
                    DEVICE_SETTING_BUILT_IN_ITEM,
                    DEVICE_SETTING_BUILT_IN_BT_PROFILES_ITEM,
                ),
                listOf(DEVICE_SETTING_APP_PROVIDED_ITEM_2),
                DEVICE_SETTING_HELP_ITEM,
            )
    }