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

Commit fe306f36 authored by David Duarte's avatar David Duarte
Browse files

Config: Replace mask by profileId

Bug: 305741984
Test: m com.android.btservices
Flag: EXEMPT, no-op
Change-Id: Icc2cb317a4d2bee4c7a2649989bc0bcbe467eeaf
parent 02e7e546
Loading
Loading
Loading
Loading
+14 −12
Original line number Diff line number Diff line
@@ -159,6 +159,7 @@ import java.time.Duration;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -1026,28 +1027,29 @@ public class AdapterService extends Service {
    }

    void updateLeAudioProfileServiceState() {
        HashSet<Class> nonSupportedProfiles = new HashSet<>();
        Map<Integer, Class> nonSupportedProfiles = new HashMap<>();

        if (!isLeConnectedIsochronousStreamCentralSupported()) {
            nonSupportedProfiles.addAll(Config.getLeAudioUnicastProfiles());
            nonSupportedProfiles.putAll(Config.getLeAudioUnicastProfiles());
        }

        if (!isLeAudioBroadcastAssistantSupported()) {
            nonSupportedProfiles.add(BassClientService.class);
            nonSupportedProfiles.put(
                    BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT, BassClientService.class);
        }

        if (!isLeAudioBroadcastSourceSupported()) {
            Config.updateSupportedProfileMask(
                    false, LeAudioService.class, BluetoothProfile.LE_AUDIO_BROADCAST);
            Config.setProfileEnabled(BluetoothProfile.LE_AUDIO_BROADCAST, false);
        }

        // Disable the non-supported profiles service
        for (Class profileService : nonSupportedProfiles) {
            Config.setProfileEnabled(profileService, false);
        nonSupportedProfiles.forEach(
                (profileId, profileService) -> {
                    Config.setProfileEnabled(profileId, false);
                    if (isStartedProfile(profileService.getSimpleName())) {
                        setProfileServiceState(profileService, BluetoothAdapter.STATE_OFF);
                    }
        }
                });
    }

    void updateAdapterState(int prevState, int newState) {
@@ -4284,7 +4286,7 @@ public class AdapterService extends Service {

            HashSet<Class> supportedProfileServices =
                    new HashSet<Class>(Arrays.asList(Config.getSupportedProfiles()));
            HashSet<Class> leAudioUnicastProfiles = Config.getLeAudioUnicastProfiles();
            Collection<Class> leAudioUnicastProfiles = Config.getLeAudioUnicastProfiles().values();

            if (supportedProfileServices.containsAll(leAudioUnicastProfiles)) {
                return BluetoothStatusCodes.FEATURE_SUPPORTED;
+93 −101
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@ import com.android.bluetooth.vc.VolumeControlService;
import com.android.internal.annotations.VisibleForTesting;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;

public class Config {
    private static final String TAG = "AdapterServiceConfig";
@@ -66,95 +66,98 @@ public class Config {
    private static class ProfileConfig {
        Class mClass;
        boolean mSupported;
        long mMask;
        int mProfileId;

        ProfileConfig(Class theClass, boolean supported, long mask) {
        ProfileConfig(Class theClass, boolean supported, int profileId) {
            mClass = theClass;
            mSupported = supported;
            mMask = mask;
            mProfileId = profileId;
        }
    }

    /** List of profile services related to LE audio */
    private static final HashSet<Class> LE_AUDIO_UNICAST_PROFILES =
            new HashSet<Class>(
                    Arrays.asList(
                            LeAudioService.class,
                            VolumeControlService.class,
                            McpService.class,
                            CsipSetCoordinatorService.class,
                            TbsService.class));

    /**
     * List of profile services with the profile-supported resource flag and bit mask.
     */
    private static final Map<Integer, Class> LE_AUDIO_UNICAST_PROFILES =
            Map.of(
                    BluetoothProfile.LE_AUDIO, LeAudioService.class,
                    BluetoothProfile.VOLUME_CONTROL, VolumeControlService.class,
                    BluetoothProfile.CSIP_SET_COORDINATOR, CsipSetCoordinatorService.class,
                    BluetoothProfile.MCP_SERVER, McpService.class,
                    BluetoothProfile.LE_CALL_CONTROL, TbsService.class);

    /** List of profile services with the profile-supported resource flag and bit mask. */
    private static final ProfileConfig[] PROFILE_SERVICES_AND_FLAGS = {
            new ProfileConfig(A2dpService.class, A2dpService.isEnabled(),
                    (1 << BluetoothProfile.A2DP)),
            new ProfileConfig(A2dpSinkService.class, A2dpSinkService.isEnabled(),
                    (1 << BluetoothProfile.A2DP_SINK)),
            new ProfileConfig(AvrcpTargetService.class, AvrcpTargetService.isEnabled(),
                    (1 << BluetoothProfile.AVRCP)),
            new ProfileConfig(AvrcpControllerService.class, AvrcpControllerService.isEnabled(),
                    (1 << BluetoothProfile.AVRCP_CONTROLLER)),
            new ProfileConfig(BassClientService.class, BassClientService.isEnabled(),
                    (1 << BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT)),
            new ProfileConfig(BatteryService.class, BatteryService.isEnabled(),
                    (1 << BluetoothProfile.BATTERY)),
            new ProfileConfig(CsipSetCoordinatorService.class,
        new ProfileConfig(A2dpService.class, A2dpService.isEnabled(), BluetoothProfile.A2DP),
        new ProfileConfig(
                A2dpSinkService.class, A2dpSinkService.isEnabled(), BluetoothProfile.A2DP_SINK),
        new ProfileConfig(
                AvrcpTargetService.class, AvrcpTargetService.isEnabled(), BluetoothProfile.AVRCP),
        new ProfileConfig(
                AvrcpControllerService.class,
                AvrcpControllerService.isEnabled(),
                BluetoothProfile.AVRCP_CONTROLLER),
        new ProfileConfig(
                BassClientService.class,
                BassClientService.isEnabled(),
                BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT),
        new ProfileConfig(
                BatteryService.class, BatteryService.isEnabled(), BluetoothProfile.BATTERY),
        new ProfileConfig(
                CsipSetCoordinatorService.class,
                CsipSetCoordinatorService.isEnabled(),
                    (1 << BluetoothProfile.CSIP_SET_COORDINATOR)),
            new ProfileConfig(HapClientService.class, HapClientService.isEnabled(),
                    (1 << BluetoothProfile.HAP_CLIENT)),
            new ProfileConfig(HeadsetService.class, HeadsetService.isEnabled(),
                    (1 << BluetoothProfile.HEADSET)),
            new ProfileConfig(HeadsetClientService.class, HeadsetClientService.isEnabled(),
                    (1 << BluetoothProfile.HEADSET_CLIENT)),
            new ProfileConfig(HearingAidService.class, HearingAidService.isEnabled(),
                    (1 << BluetoothProfile.HEARING_AID)),
            new ProfileConfig(HidDeviceService.class, HidDeviceService.isEnabled(),
                    (1 << BluetoothProfile.HID_DEVICE)),
            new ProfileConfig(HidHostService.class, HidHostService.isEnabled(),
                    (1 << BluetoothProfile.HID_HOST)),
            new ProfileConfig(GattService.class, GattService.isEnabled(),
                    (1 << BluetoothProfile.GATT)),
            new ProfileConfig(LeAudioService.class, LeAudioService.isEnabled(),
                    (1 << BluetoothProfile.LE_AUDIO)),
            new ProfileConfig(null, LeAudioService.isBroadcastEnabled(),
                    (1 << BluetoothProfile.LE_AUDIO_BROADCAST)),
            new ProfileConfig(TbsService.class, TbsService.isEnabled(),
                    (1 << BluetoothProfile.LE_CALL_CONTROL)),
            new ProfileConfig(BluetoothMapService.class, BluetoothMapService.isEnabled(),
                    (1 << BluetoothProfile.MAP)),
            new ProfileConfig(MapClientService.class, MapClientService.isEnabled(),
                    (1 << BluetoothProfile.MAP_CLIENT)),
            new ProfileConfig(McpService.class, McpService.isEnabled(),
                    (1 << BluetoothProfile.MCP_SERVER)),
            new ProfileConfig(BluetoothOppService.class, BluetoothOppService.isEnabled(),
                    (1 << BluetoothProfile.OPP)),
            new ProfileConfig(PanService.class, PanService.isEnabled(),
                    (1 << BluetoothProfile.PAN)),
            new ProfileConfig(BluetoothPbapService.class, BluetoothPbapService.isEnabled(),
                    (1 << BluetoothProfile.PBAP)),
            new ProfileConfig(PbapClientService.class, PbapClientService.isEnabled(),
                    (1 << BluetoothProfile.PBAP_CLIENT)),
            new ProfileConfig(SapService.class, SapService.isEnabled(),
                    (1 << BluetoothProfile.SAP)),
            new ProfileConfig(VolumeControlService.class, VolumeControlService.isEnabled(),
                    (1 << BluetoothProfile.VOLUME_CONTROL)),
                BluetoothProfile.CSIP_SET_COORDINATOR),
        new ProfileConfig(
                HapClientService.class, HapClientService.isEnabled(), BluetoothProfile.HAP_CLIENT),
        new ProfileConfig(
                HeadsetService.class, HeadsetService.isEnabled(), BluetoothProfile.HEADSET),
        new ProfileConfig(
                HeadsetClientService.class,
                HeadsetClientService.isEnabled(),
                BluetoothProfile.HEADSET_CLIENT),
        new ProfileConfig(
                HearingAidService.class,
                HearingAidService.isEnabled(),
                BluetoothProfile.HEARING_AID),
        new ProfileConfig(
                HidDeviceService.class, HidDeviceService.isEnabled(), BluetoothProfile.HID_DEVICE),
        new ProfileConfig(
                HidHostService.class, HidHostService.isEnabled(), BluetoothProfile.HID_HOST),
        new ProfileConfig(GattService.class, GattService.isEnabled(), BluetoothProfile.GATT),
        new ProfileConfig(
                LeAudioService.class, LeAudioService.isEnabled(), BluetoothProfile.LE_AUDIO),
        new ProfileConfig(
                null, LeAudioService.isBroadcastEnabled(), BluetoothProfile.LE_AUDIO_BROADCAST),
        new ProfileConfig(
                TbsService.class, TbsService.isEnabled(), BluetoothProfile.LE_CALL_CONTROL),
        new ProfileConfig(
                BluetoothMapService.class, BluetoothMapService.isEnabled(), BluetoothProfile.MAP),
        new ProfileConfig(
                MapClientService.class, MapClientService.isEnabled(), BluetoothProfile.MAP_CLIENT),
        new ProfileConfig(McpService.class, McpService.isEnabled(), BluetoothProfile.MCP_SERVER),
        new ProfileConfig(
                BluetoothOppService.class, BluetoothOppService.isEnabled(), BluetoothProfile.OPP),
        new ProfileConfig(PanService.class, PanService.isEnabled(), BluetoothProfile.PAN),
        new ProfileConfig(
                BluetoothPbapService.class,
                BluetoothPbapService.isEnabled(),
                BluetoothProfile.PBAP),
        new ProfileConfig(
                PbapClientService.class,
                PbapClientService.isEnabled(),
                BluetoothProfile.PBAP_CLIENT),
        new ProfileConfig(SapService.class, SapService.isEnabled(), BluetoothProfile.SAP),
        new ProfileConfig(
                VolumeControlService.class,
                VolumeControlService.isEnabled(),
                BluetoothProfile.VOLUME_CONTROL),
    };

    /**
     * A test function to allow for dynamic enabled
     */
    /** A test function to allow for dynamic enabled */
    @VisibleForTesting
    public static void setProfileEnabled(Class profileClass, boolean enabled) {
        if (profileClass == null) {
            return;
        }
    public static void setProfileEnabled(int profileId, boolean enabled) {
        for (ProfileConfig profile : PROFILE_SERVICES_AND_FLAGS) {
            if (profileClass.equals(profile.mClass)) {
            if (profileId == profile.mProfileId) {
                profile.mSupported = enabled;
                break;
            }
        }
    }
@@ -178,54 +181,43 @@ public class Config {
        // platforms can choose to enable ASHA themselves
        if (BluetoothProperties.isProfileAshaCentralEnabled().isEmpty()) {
            if (Utils.isAutomotive(ctx) || Utils.isTv(ctx) || Utils.isWatch(ctx)) {
                setProfileEnabled(HearingAidService.class, false);
                setProfileEnabled(BluetoothProfile.HEARING_AID, false);
            }
        }

        // Disable ASHA if BLE is not supported on this platform even if the platform enabled ASHA
        // accidentally
        if (!Utils.isBleSupported(ctx)) {
            setProfileEnabled(HearingAidService.class, false);
            setProfileEnabled(BluetoothProfile.HEARING_AID, false);
        }

        for (ProfileConfig config : PROFILE_SERVICES_AND_FLAGS) {
            if (config.mClass == null) continue;
            Log.i(
                    TAG,
                    String.format(
                            "init: profile=%s, enabled=%s",
                            config.mClass.getSimpleName(), config.mSupported));
                            BluetoothProfile.getProfileName(config.mProfileId), config.mSupported));
        }
    }

    static void setLeAudioProfileStatus(Boolean enable) {
        setProfileEnabled(CsipSetCoordinatorService.class, enable);
        setProfileEnabled(HapClientService.class, enable);
        setProfileEnabled(LeAudioService.class, enable);
        setProfileEnabled(TbsService.class, enable);
        setProfileEnabled(McpService.class, enable);
        setProfileEnabled(VolumeControlService.class, enable);
        setProfileEnabled(BluetoothProfile.CSIP_SET_COORDINATOR, enable);
        setProfileEnabled(BluetoothProfile.HAP_CLIENT, enable);
        setProfileEnabled(BluetoothProfile.LE_AUDIO, enable);
        setProfileEnabled(BluetoothProfile.LE_CALL_CONTROL, enable);
        setProfileEnabled(BluetoothProfile.MCP_SERVER, enable);
        setProfileEnabled(BluetoothProfile.VOLUME_CONTROL, enable);

        final boolean broadcastDynamicSwitchSupported =
                SystemProperties.getBoolean(LE_AUDIO_BROADCAST_DYNAMIC_SWITCH_PROPERTY, false);

        if (broadcastDynamicSwitchSupported) {
            setProfileEnabled(BassClientService.class, enable);
            updateSupportedProfileMask(
                    enable, LeAudioService.class, BluetoothProfile.LE_AUDIO_BROADCAST);
        }
    }

    static void updateSupportedProfileMask(Boolean enable, Class profile, int supportedProfile) {
        for (ProfileConfig config : PROFILE_SERVICES_AND_FLAGS) {
            if (config.mMask == (1 << supportedProfile)) {
                config.mSupported = enable;
                return;
            }
            setProfileEnabled(BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT, enable);
            setProfileEnabled(BluetoothProfile.LE_AUDIO_BROADCAST, enable);
        }
    }

    static HashSet<Class> getLeAudioUnicastProfiles() {
    static Map<Integer, Class> getLeAudioUnicastProfiles() {
        return LE_AUDIO_UNICAST_PROFILES;
    }

@@ -242,7 +234,7 @@ public class Config {
        long mask = 0;
        for (ProfileConfig config : PROFILE_SERVICES_AND_FLAGS) {
            if (config.mSupported) {
                mask |= config.mMask;
                mask |= (1L << config.mProfileId);
            }
        }
        return mask;
+12 −53
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import android.app.admin.DevicePolicyManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.IBluetoothCallback;
import android.companion.CompanionDeviceManager;
import android.content.Context;
@@ -70,37 +71,12 @@ import androidx.test.runner.AndroidJUnit4;

import com.android.bluetooth.TestUtils;
import com.android.bluetooth.Utils;
import com.android.bluetooth.a2dp.A2dpService;
import com.android.bluetooth.a2dpsink.A2dpSinkService;
import com.android.bluetooth.avrcp.AvrcpTargetService;
import com.android.bluetooth.avrcpcontroller.AvrcpControllerService;
import com.android.bluetooth.bas.BatteryService;
import com.android.bluetooth.bass_client.BassClientService;
import com.android.bluetooth.btservice.bluetoothkeystore.BluetoothKeystoreNativeInterface;
import com.android.bluetooth.csip.CsipSetCoordinatorService;
import com.android.bluetooth.gatt.AdvertiseManagerNativeInterface;
import com.android.bluetooth.gatt.DistanceMeasurementNativeInterface;
import com.android.bluetooth.gatt.GattNativeInterface;
import com.android.bluetooth.gatt.GattService;
import com.android.bluetooth.gatt.PeriodicScanNativeInterface;
import com.android.bluetooth.hap.HapClientService;
import com.android.bluetooth.hearingaid.HearingAidService;
import com.android.bluetooth.hfp.HeadsetService;
import com.android.bluetooth.hfpclient.HeadsetClientService;
import com.android.bluetooth.hid.HidDeviceService;
import com.android.bluetooth.hid.HidHostService;
import com.android.bluetooth.le_audio.LeAudioService;
import com.android.bluetooth.map.BluetoothMapService;
import com.android.bluetooth.mapclient.MapClientService;
import com.android.bluetooth.mcp.McpService;
import com.android.bluetooth.opp.BluetoothOppService;
import com.android.bluetooth.pan.PanService;
import com.android.bluetooth.pbap.BluetoothPbapService;
import com.android.bluetooth.pbapclient.PbapClientService;
import com.android.bluetooth.sap.SapService;
import com.android.bluetooth.sdp.SdpManagerNativeInterface;
import com.android.bluetooth.tbs.TbsService;
import com.android.bluetooth.vc.VolumeControlService;
import com.android.internal.app.IBatteryStats;

import libcore.util.HexEncoding;
@@ -183,32 +159,15 @@ public class AdapterServiceTest {

    static void configureEnabledProfiles() {
        Log.e(TAG, "configureEnabledProfiles");
        Config.setProfileEnabled(PanService.class, true);
        Config.setProfileEnabled(BluetoothPbapService.class, true);
        Config.setProfileEnabled(GattService.class, true);

        Config.setProfileEnabled(A2dpService.class, false);
        Config.setProfileEnabled(A2dpSinkService.class, false);
        Config.setProfileEnabled(AvrcpTargetService.class, false);
        Config.setProfileEnabled(AvrcpControllerService.class, false);
        Config.setProfileEnabled(BassClientService.class, false);
        Config.setProfileEnabled(BatteryService.class, false);
        Config.setProfileEnabled(CsipSetCoordinatorService.class, false);
        Config.setProfileEnabled(HapClientService.class, false);
        Config.setProfileEnabled(HeadsetService.class, false);
        Config.setProfileEnabled(HeadsetClientService.class, false);
        Config.setProfileEnabled(HearingAidService.class, false);
        Config.setProfileEnabled(HidDeviceService.class, false);
        Config.setProfileEnabled(HidHostService.class, false);
        Config.setProfileEnabled(LeAudioService.class, false);
        Config.setProfileEnabled(TbsService.class, false);
        Config.setProfileEnabled(BluetoothMapService.class, false);
        Config.setProfileEnabled(MapClientService.class, false);
        Config.setProfileEnabled(McpService.class, false);
        Config.setProfileEnabled(BluetoothOppService.class, false);
        Config.setProfileEnabled(PbapClientService.class, false);
        Config.setProfileEnabled(SapService.class, false);
        Config.setProfileEnabled(VolumeControlService.class, false);

        for (int profileId = 0; profileId <= BluetoothProfile.MAX_PROFILE_ID; profileId++) {
            boolean enabled =
                    profileId == BluetoothProfile.PAN
                            || profileId == BluetoothProfile.PBAP
                            || profileId == BluetoothProfile.GATT;

            Config.setProfileEnabled(profileId, enabled);
        }
    }

    <T> void mockGetSystemService(String serviceName, Class<T> serviceClass, T mockService) {
@@ -614,8 +573,8 @@ public class AdapterServiceTest {
        when(mockContext.getPackageManager()).thenReturn(mMockPackageManager);

        // Config is set to PBAP, PAN and GATT by default. Turn off PAN and PBAP.
        Config.setProfileEnabled(PanService.class, false);
        Config.setProfileEnabled(BluetoothPbapService.class, false);
        Config.setProfileEnabled(BluetoothProfile.PAN, false);
        Config.setProfileEnabled(BluetoothProfile.PBAP, false);

        Config.init(mockContext);
        doEnable(true);
+5 −3
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.bluetooth.btservice;

import static com.google.common.truth.Truth.assertThat;

import android.bluetooth.BluetoothProfile;

import com.android.bluetooth.csip.CsipSetCoordinatorService;

import org.junit.Test;
@@ -34,18 +36,18 @@ public final class ConfigTest {
                Arrays.stream(Config.getSupportedProfiles())
                        .anyMatch(cls -> cls == CsipSetCoordinatorService.class);

        Config.setProfileEnabled(CsipSetCoordinatorService.class, false);
        Config.setProfileEnabled(BluetoothProfile.CSIP_SET_COORDINATOR, false);
        assertThat(
                        Arrays.stream(Config.getSupportedProfiles())
                                .anyMatch(cls -> cls == CsipSetCoordinatorService.class))
                .isFalse();

        Config.setProfileEnabled(CsipSetCoordinatorService.class, true);
        Config.setProfileEnabled(BluetoothProfile.CSIP_SET_COORDINATOR, true);
        assertThat(
                        Arrays.stream(Config.getSupportedProfiles())
                                .anyMatch(cls -> cls == CsipSetCoordinatorService.class))
                .isTrue();

        Config.setProfileEnabled(CsipSetCoordinatorService.class, enabled);
        Config.setProfileEnabled(BluetoothProfile.CSIP_SET_COORDINATOR, enabled);
    }
}