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

Commit 813da462 authored by Eric Laurent's avatar Eric Laurent Committed by Android (Google) Code Review
Browse files

Merge "AudioService: Add support for LE headset groups in device inventory" into main

parents f5d586ae 740c912b
Loading
Loading
Loading
Loading
+63 −13
Original line number Diff line number Diff line
@@ -70,7 +70,6 @@ import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;


@@ -172,7 +171,7 @@ public class AudioDeviceBroker {
            @NonNull AudioSystemAdapter audioSystem) {
        mContext = context;
        mAudioService = service;
        mBtHelper = new BtHelper(this);
        mBtHelper = new BtHelper(this, context);
        mDeviceInventory = new AudioDeviceInventory(this);
        mSystemServer = SystemServerAdapter.getDefaultAdapter(mContext);
        mAudioSystem = audioSystem;
@@ -188,7 +187,7 @@ public class AudioDeviceBroker {
                      @NonNull AudioSystemAdapter audioSystem) {
        mContext = context;
        mAudioService = service;
        mBtHelper = new BtHelper(this);
        mBtHelper = new BtHelper(this, context);
        mDeviceInventory = mockDeviceInventory;
        mSystemServer = mockSystemServer;
        mAudioSystem = audioSystem;
@@ -1392,6 +1391,10 @@ public class AudioDeviceBroker {
        return mAudioService.hasAudioFocusUsers();
    }

    /*package*/ void postInitSpatializerHeadTrackingSensors() {
        mAudioService.postInitSpatializerHeadTrackingSensors();
    }

    //---------------------------------------------------------------------
    // Message handling on behalf of helper classes.
    // Each of these methods posts a message to mBrokerHandler message queue.
@@ -1475,6 +1478,15 @@ public class AudioDeviceBroker {
        sendLMsgNoDelay(MSG_L_RECEIVED_BT_EVENT, SENDMSG_QUEUE, intent);
    }

    /*package*/ void postUpdateLeAudioGroupAddresses(int groupId) {
        sendIMsgNoDelay(
                MSG_I_UPDATE_LE_AUDIO_GROUP_ADDRESSES, SENDMSG_QUEUE, groupId);
    }

    /*package*/ void postSynchronizeLeDevicesInInventory(AdiDeviceState deviceState) {
        sendLMsgNoDelay(MSG_L_SYNCHRONIZE_LE_DEVICES_IN_INVENTORY, SENDMSG_QUEUE, deviceState);
    }

    /*package*/ static final class CommunicationDeviceInfo {
        final @NonNull IBinder mCb; // Identifies the requesting client for death handler
        final int mUid; // Requester UID
@@ -1604,6 +1616,14 @@ public class AudioDeviceBroker {
        }
    }

    /*package*/ int getLeAudioDeviceGroupId(BluetoothDevice device) {
        return mBtHelper.getLeAudioDeviceGroupId(device);
    }

    /*package*/ List<String> getLeAudioGroupAddresses(int groupId) {
        return mBtHelper.getLeAudioGroupAddresses(groupId);
    }

    /*package*/ void broadcastStickyIntentToCurrentProfileGroup(Intent intent) {
        mSystemServer.broadcastStickyIntentToCurrentProfileGroup(intent);
    }
@@ -1976,6 +1996,22 @@ public class AudioDeviceBroker {
                        onCheckCommunicationRouteClientState(msg.arg1, msg.arg2 == 1);
                    }
                } break;

                case MSG_I_UPDATE_LE_AUDIO_GROUP_ADDRESSES:
                    synchronized (mSetModeLock) {
                        synchronized (mDeviceStateLock) {
                            mDeviceInventory.onUpdateLeAudioGroupAddresses(msg.arg1);
                        }
                    } break;

                case MSG_L_SYNCHRONIZE_LE_DEVICES_IN_INVENTORY:
                    synchronized (mSetModeLock) {
                        synchronized (mDeviceStateLock) {
                            mDeviceInventory.onSynchronizeLeDevicesInInventory(
                                    (AdiDeviceState) msg.obj);
                        }
                    } break;

                default:
                    Log.wtf(TAG, "Invalid message " + msg.what);
            }
@@ -2058,6 +2094,10 @@ public class AudioDeviceBroker {
    private static final int MSG_L_RECEIVED_BT_EVENT = 55;

    private static final int MSG_CHECK_COMMUNICATION_ROUTE_CLIENT_STATE = 56;
    private static final int MSG_I_UPDATE_LE_AUDIO_GROUP_ADDRESSES = 57;
    private static final int MSG_L_SYNCHRONIZE_LE_DEVICES_IN_INVENTORY = 58;



    private static boolean isMessageHandledUnderWakelock(int msgId) {
        switch(msgId) {
@@ -2582,9 +2622,9 @@ public class AudioDeviceBroker {
        }
    }

    @Nullable UUID getDeviceSensorUuid(AudioDeviceAttributes device) {
    List<String> getDeviceAddresses(AudioDeviceAttributes device) {
        synchronized (mDeviceStateLock) {
            return mDeviceInventory.getDeviceSensorUuid(device);
            return mDeviceInventory.getDeviceAddresses(device);
        }
    }

@@ -2605,15 +2645,19 @@ public class AudioDeviceBroker {
     * in order to be mocked by a test a the same package
     * (see https://code.google.com/archive/p/mockito/issues/127)
     */
    public void persistAudioDeviceSettings() {
    public void postPersistAudioDeviceSettings() {
        sendMsg(MSG_PERSIST_AUDIO_DEVICE_SETTINGS, SENDMSG_REPLACE, /*delay*/ 1000);
    }

    void onPersistAudioDeviceSettings() {
        final String deviceSettings = mDeviceInventory.getDeviceSettings();
        Log.v(TAG, "saving AdiDeviceState: " + deviceSettings);
        final SettingsAdapter settings = mAudioService.getSettings();
        boolean res = settings.putSecureStringForUser(mAudioService.getContentResolver(),
        Log.v(TAG, "onPersistAudioDeviceSettings AdiDeviceState: " + deviceSettings);
        String currentSettings = readDeviceSettings();
        if (deviceSettings.equals(currentSettings)) {
            return;
        }
        final SettingsAdapter settingsAdapter = mAudioService.getSettings();
        boolean res = settingsAdapter.putSecureStringForUser(mAudioService.getContentResolver(),
                Settings.Secure.AUDIO_DEVICE_INVENTORY,
                deviceSettings, UserHandle.USER_CURRENT);
        if (!res) {
@@ -2621,11 +2665,17 @@ public class AudioDeviceBroker {
        }
    }

    void onReadAudioDeviceSettings() {
    private String readDeviceSettings() {
        final SettingsAdapter settingsAdapter = mAudioService.getSettings();
        final ContentResolver contentResolver = mAudioService.getContentResolver();
        String settings = settingsAdapter.getSecureStringForUser(contentResolver,
        return settingsAdapter.getSecureStringForUser(contentResolver,
                Settings.Secure.AUDIO_DEVICE_INVENTORY, UserHandle.USER_CURRENT);
    }

    void onReadAudioDeviceSettings() {
        final SettingsAdapter settingsAdapter = mAudioService.getSettings();
        final ContentResolver contentResolver = mAudioService.getContentResolver();
        String settings = readDeviceSettings();
        if (settings == null) {
            Log.i(TAG, "reading AdiDeviceState from legacy key"
                    + Settings.Secure.SPATIAL_AUDIO_ENABLED);
@@ -2688,8 +2738,8 @@ public class AudioDeviceBroker {
    }

    @Nullable
    AdiDeviceState findBtDeviceStateForAddress(String address, boolean isBle) {
        return mDeviceInventory.findBtDeviceStateForAddress(address, isBle);
    AdiDeviceState findBtDeviceStateForAddress(String address, int deviceType) {
        return mDeviceInventory.findBtDeviceStateForAddress(address, deviceType);
    }

    //------------------------------------------------
+179 −60

File changed.

Preview size limit exceeded, changes collapsed.

+8 −6
Original line number Diff line number Diff line
@@ -237,7 +237,6 @@ import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@@ -11054,7 +11053,9 @@ public class AudioService extends IAudioService.Stub
        final String addr = Objects.requireNonNull(address);
        AdiDeviceState deviceState = mDeviceBroker.findBtDeviceStateForAddress(addr, isBle);
        AdiDeviceState deviceState = mDeviceBroker.findBtDeviceStateForAddress(addr,
                (isBle ? AudioSystem.DEVICE_OUT_BLE_HEADSET
                        : AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP));
        int internalType = !isBle ? DEVICE_OUT_BLUETOOTH_A2DP
                : ((btAudioDeviceCategory == AUDIO_DEVICE_CATEGORY_HEADPHONES)
@@ -11070,7 +11071,7 @@ public class AudioService extends IAudioService.Stub
        deviceState.setAudioDeviceCategory(btAudioDeviceCategory);
        mDeviceBroker.addOrUpdateBtAudioDeviceCategoryInInventory(deviceState);
        mDeviceBroker.persistAudioDeviceSettings();
        mDeviceBroker.postPersistAudioDeviceSettings();
        mSpatializerHelper.refreshDevice(deviceState.getAudioDeviceAttributes());
        mSoundDoseHelper.setAudioDeviceCategory(addr, internalType,
@@ -11084,7 +11085,8 @@ public class AudioService extends IAudioService.Stub
        super.getBluetoothAudioDeviceCategory_enforcePermission();
        final AdiDeviceState deviceState = mDeviceBroker.findBtDeviceStateForAddress(
                Objects.requireNonNull(address), isBle);
                Objects.requireNonNull(address), (isBle ? AudioSystem.DEVICE_OUT_BLE_HEADSET
                        : AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP));
        if (deviceState == null) {
            return AUDIO_DEVICE_CATEGORY_UNKNOWN;
        }
@@ -13596,8 +13598,8 @@ public class AudioService extends IAudioService.Stub
        return activeAssistantUids;
    }
    UUID getDeviceSensorUuid(AudioDeviceAttributes device) {
        return mDeviceBroker.getDeviceSensorUuid(device);
    List<String> getDeviceAddresses(AudioDeviceAttributes device) {
        return mDeviceBroker.getDeviceAddresses(device);
    }
    //======================
+59 −1
Original line number Diff line number Diff line
@@ -26,7 +26,9 @@ import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothHearingAid;
import android.bluetooth.BluetoothLeAudio;
import android.bluetooth.BluetoothLeAudioCodecStatus;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.media.AudioDeviceAttributes;
import android.media.AudioManager;
@@ -43,6 +45,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.server.utils.EventLogger;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -57,9 +60,11 @@ public class BtHelper {
    private static final String TAG = "AS.BtHelper";

    private final @NonNull AudioDeviceBroker mDeviceBroker;
    private final @NonNull Context mContext;

    BtHelper(@NonNull AudioDeviceBroker broker) {
    BtHelper(@NonNull AudioDeviceBroker broker, Context context) {
        mDeviceBroker = broker;
        mContext = context;
    }

    // BluetoothHeadset API to control SCO connection
@@ -498,6 +503,32 @@ public class BtHelper {
        }
    }

    // BluetoothLeAudio callback used to update the list of addresses in the same group as a
    // connected LE Audio device
    MyLeAudioCallback mLeAudioCallback = null;

    class MyLeAudioCallback implements BluetoothLeAudio.Callback {
        @Override
        public void onCodecConfigChanged(int groupId,
                                  @NonNull BluetoothLeAudioCodecStatus status) {
            // Do nothing
        }

        @Override
        public void onGroupNodeAdded(@NonNull BluetoothDevice device, int groupId) {
            mDeviceBroker.postUpdateLeAudioGroupAddresses(groupId);
        }

        @Override
        public void onGroupNodeRemoved(@NonNull BluetoothDevice device, int groupId) {
            mDeviceBroker.postUpdateLeAudioGroupAddresses(groupId);
        }
        @Override
        public void onGroupStatusChanged(int groupId, int groupStatus) {
            mDeviceBroker.postUpdateLeAudioGroupAddresses(groupId);
        }
    }

    // @GuardedBy("mDeviceBroker.mSetModeLock")
    @GuardedBy("AudioDeviceBroker.this.mDeviceStateLock")
    /*package*/ synchronized void onBtProfileConnected(int profile, BluetoothProfile proxy) {
@@ -519,6 +550,11 @@ public class BtHelper {
                mHearingAid = (BluetoothHearingAid) proxy;
                break;
            case BluetoothProfile.LE_AUDIO:
                if (mLeAudio == null) {
                    mLeAudioCallback = new MyLeAudioCallback();
                    ((BluetoothLeAudio) proxy).registerCallback(
                            mContext.getMainExecutor(), mLeAudioCallback);
                }
                mLeAudio = (BluetoothLeAudio) proxy;
                break;
            case BluetoothProfile.A2DP_SINK:
@@ -977,6 +1013,28 @@ public class BtHelper {
        return result;
    }

    /*package*/ int getLeAudioDeviceGroupId(BluetoothDevice device) {
        if (mLeAudio == null || device == null) {
            return BluetoothLeAudio.GROUP_ID_INVALID;
        }
        return mLeAudio.getGroupId(device);
    }

    /*package*/ List<String> getLeAudioGroupAddresses(int groupId) {
        List<String> addresses = new ArrayList<String>();
        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        if (adapter == null || mLeAudio == null) {
            return addresses;
        }
        List<BluetoothDevice> activeDevices = adapter.getActiveDevices(BluetoothProfile.LE_AUDIO);
        for (BluetoothDevice device : activeDevices) {
            if (device != null && mLeAudio.getGroupId(device) == groupId) {
                addresses.add(device.getAddress());
            }
        }
        return addresses;
    }

    /**
     * Returns the String equivalent of the btCodecType.
     *
+24 −16
Original line number Diff line number Diff line
@@ -564,7 +564,7 @@ public class SpatializerHelper {
        }
        if (updatedDevice != null) {
            onRoutingUpdated();
            mDeviceBroker.persistAudioDeviceSettings();
            mDeviceBroker.postPersistAudioDeviceSettings();
            logDeviceState(updatedDevice, "addCompatibleAudioDevice");
        }
    }
@@ -614,7 +614,7 @@ public class SpatializerHelper {
        if (deviceState != null && deviceState.isSAEnabled()) {
            deviceState.setSAEnabled(false);
            onRoutingUpdated();
            mDeviceBroker.persistAudioDeviceSettings();
            mDeviceBroker.postPersistAudioDeviceSettings();
            logDeviceState(deviceState, "removeCompatibleAudioDevice");
        }
    }
@@ -716,7 +716,7 @@ public class SpatializerHelper {
                            ada.getAddress());
            initSAState(deviceState);
            mDeviceBroker.addOrUpdateDeviceSAStateInInventory(deviceState);
            mDeviceBroker.persistAudioDeviceSettings();
            mDeviceBroker.postPersistAudioDeviceSettings();
            logDeviceState(deviceState, "addWirelessDeviceIfNew"); // may be updated later.
        }
    }
@@ -1206,7 +1206,7 @@ public class SpatializerHelper {
        }
        Log.i(TAG, "setHeadTrackerEnabled enabled:" + enabled + " device:" + ada);
        deviceState.setHeadTrackerEnabled(enabled);
        mDeviceBroker.persistAudioDeviceSettings();
        mDeviceBroker.postPersistAudioDeviceSettings();
        logDeviceState(deviceState, "setHeadTrackerEnabled");

        // check current routing to see if it affects the headtracking mode
@@ -1248,7 +1248,7 @@ public class SpatializerHelper {
        if (deviceState != null) {
            if (!deviceState.hasHeadTracker()) {
                deviceState.setHasHeadTracker(true);
                mDeviceBroker.persistAudioDeviceSettings();
                mDeviceBroker.postPersistAudioDeviceSettings();
                logDeviceState(deviceState, "setHasHeadTracker");
            }
            return deviceState.isHeadTrackerEnabled();
@@ -1631,13 +1631,17 @@ public class SpatializerHelper {
            return headHandle;
        }
        final AudioDeviceAttributes currentDevice = sRoutingDevices.get(0);
        UUID routingDeviceUuid = mAudioService.getDeviceSensorUuid(currentDevice);
        List<String> deviceAddresses = mAudioService.getDeviceAddresses(currentDevice);

        // We limit only to Sensor.TYPE_HEAD_TRACKER here to avoid confusion
        // with gaming sensors. (Note that Sensor.TYPE_ROTATION_VECTOR
        // and Sensor.TYPE_GAME_ROTATION_VECTOR are supported internally by
        // SensorPoseProvider).
        // Note: this is a dynamic sensor list right now.
        List<Sensor> sensors = mSensorManager.getDynamicSensorList(Sensor.TYPE_HEAD_TRACKER);
        for (String address : deviceAddresses) {
            UUID routingDeviceUuid = UuidUtils.uuidFromAudioDeviceAttributes(
                    new AudioDeviceAttributes(currentDevice.getInternalType(), address));
            for (Sensor sensor : sensors) {
                final UUID uuid = sensor.getUuid();
                if (uuid.equals(routingDeviceUuid)) {
@@ -1652,6 +1656,10 @@ public class SpatializerHelper {
                    // we do not break, perhaps we find a head tracker on device.
                }
            }
            if (headHandle != -1) {
                break;
            }
        }
        return headHandle;
    }

Loading