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

Commit e04b8832 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "LeAudioTestApp: Add switch to connect GATT over BR/EDR" into main

parents fa76e4cc cf8eccd4
Loading
Loading
Loading
Loading
+52 −0
Original line number Original line Diff line number Diff line
@@ -60,6 +60,7 @@ public class BluetoothProxy {
    private BluetoothCsipSetCoordinator bluetoothCsis = null;
    private BluetoothCsipSetCoordinator bluetoothCsis = null;
    private BluetoothVolumeControl bluetoothVolumeControl = null;
    private BluetoothVolumeControl bluetoothVolumeControl = null;
    private BluetoothHapClient bluetoothHapClient = null;
    private BluetoothHapClient bluetoothHapClient = null;
    private Map<LeAudioDeviceStateWrapper, BluetoothGatt> bluetoothGattMap = new HashMap<>();
    private BluetoothProfile.ServiceListener profileListener = null;
    private BluetoothProfile.ServiceListener profileListener = null;
    private BluetoothHapClient.Callback hapCallback = null;
    private BluetoothHapClient.Callback hapCallback = null;
    private OnBassEventListener mBassEventListener;
    private OnBassEventListener mBassEventListener;
@@ -1350,6 +1351,57 @@ public class BluetoothProxy {
        }
        }
    }
    }


    public void connectGattBr(
            Context context, LeAudioDeviceStateWrapper device_wrapper, boolean connect) {

        BluetoothGatt bluetoothGatt = bluetoothGattMap.get(device_wrapper);
        if (bluetoothGatt == null) {
            bluetoothGatt =
                    device_wrapper.device.connectGatt(
                            context,
                            false,
                            new BluetoothGattCallback() {
                                public void onConnectionStateChange(
                                        BluetoothGatt gatt, int status, int newState) {
                                    LeAudioDeviceStateWrapper device_wrapper = null;
                                    for (Map.Entry<LeAudioDeviceStateWrapper, BluetoothGatt> entry :
                                            bluetoothGattMap.entrySet()) {
                                        if (gatt == entry.getValue()) {
                                            device_wrapper = entry.getKey();
                                            break;
                                        }
                                    }
                                    if (device_wrapper == null) {
                                        return;
                                    }

                                    switch (newState) {
                                        case BluetoothProfile.STATE_DISCONNECTED:
                                            device_wrapper.isGattBrConnectedMutable.postValue(
                                                    false);
                                            break;
                                        case BluetoothProfile.STATE_CONNECTED:
                                            device_wrapper.isGattBrConnectedMutable.postValue(true);
                                            break;
                                        default:
                                            break;
                                    }
                                }
                            }, BluetoothDevice.TRANSPORT_BREDR);
            bluetoothGattMap.put(device_wrapper, bluetoothGatt);
        }

        if (bluetoothGatt == null) {
            return;
        }

        if (connect) {
            bluetoothGatt.connect();
        } else {
            bluetoothGatt.disconnect();
        }
    }

    public boolean hapReadPresetInfo(BluetoothDevice device, int preset_index) {
    public boolean hapReadPresetInfo(BluetoothDevice device, int preset_index) {
        if (bluetoothHapClient == null) return false;
        if (bluetoothHapClient == null) return false;


+2 −0
Original line number Original line Diff line number Diff line
@@ -36,6 +36,8 @@ public class LeAudioDeviceStateWrapper {
    public BassData bassData = null;
    public BassData bassData = null;
    public HapData hapData = null;
    public HapData hapData = null;


    public MutableLiveData<Boolean> isGattBrConnectedMutable = new MutableLiveData<>();

    public LeAudioDeviceStateWrapper(BluetoothDevice device) {
    public LeAudioDeviceStateWrapper(BluetoothDevice device) {
        this.device = device;
        this.device = device;
    }
    }
+49 −0
Original line number Original line Diff line number Diff line
@@ -77,6 +77,7 @@ public class LeAudioRecycleViewAdapter
    private OnVolumeControlInteractionListener volumeControlInteractionListener;
    private OnVolumeControlInteractionListener volumeControlInteractionListener;
    private OnBassInteractionListener bassInteractionListener;
    private OnBassInteractionListener bassInteractionListener;
    private OnHapInteractionListener hapInteractionListener;
    private OnHapInteractionListener hapInteractionListener;
    private OnGattBrListener gattBrListener;
    private final ArrayList<LeAudioDeviceStateWrapper> devices;
    private final ArrayList<LeAudioDeviceStateWrapper> devices;


    private int GROUP_NODE_ADDED = 1;
    private int GROUP_NODE_ADDED = 1;
@@ -139,6 +140,11 @@ public class LeAudioRecycleViewAdapter
                                        .contains(
                                        .contains(
                                                ParcelUuid.fromString(
                                                ParcelUuid.fromString(
                                                        parent.getString(R.string.svc_uuid_has))));
                                                        parent.getString(R.string.svc_uuid_has))));
                holder.itemView
                        .findViewById(R.id.gatt_br_switch)
                        .setEnabled(
                                leAudioDeviceStateWrapper.device.getType()
                                        == BluetoothDevice.DEVICE_TYPE_DUAL);


                holder.itemView
                holder.itemView
                        .findViewById(R.id.bass_switch)
                        .findViewById(R.id.bass_switch)
@@ -153,6 +159,7 @@ public class LeAudioRecycleViewAdapter
        }
        }


        // Set state observables
        // Set state observables
        setGattBrConnectionObserver(holder, leAudioDeviceStateWrapper);
        setLeAudioStateObservers(holder, leAudioDeviceStateWrapper);
        setLeAudioStateObservers(holder, leAudioDeviceStateWrapper);
        setVolumeControlStateObservers(holder, leAudioDeviceStateWrapper);
        setVolumeControlStateObservers(holder, leAudioDeviceStateWrapper);
        setVolumeControlUiStateObservers(holder, leAudioDeviceStateWrapper);
        setVolumeControlUiStateObservers(holder, leAudioDeviceStateWrapper);
@@ -161,6 +168,23 @@ public class LeAudioRecycleViewAdapter
        setBassUiStateObservers(holder, leAudioDeviceStateWrapper);
        setBassUiStateObservers(holder, leAudioDeviceStateWrapper);
    }
    }


    private void setGattBrConnectionObserver(
            @NonNull ViewHolder holder, LeAudioDeviceStateWrapper leAudioDeviceStateWrapper) {
        if (leAudioDeviceStateWrapper.isGattBrConnectedMutable.hasObservers()) {
            leAudioDeviceStateWrapper.isGattBrConnectedMutable.removeObservers(this.parent);
        }
        leAudioDeviceStateWrapper.isGattBrConnectedMutable.observe(
                this.parent,
                is_connected -> {
                    // FIXME: How to prevent the callback from firing when we set this by code
                    if (is_connected != holder.gattBrConnectionSwitch.isChecked()) {
                        holder.gattBrConnectionSwitch.setActivated(false);
                        holder.gattBrConnectionSwitch.setChecked(is_connected);
                        holder.gattBrConnectionSwitch.setActivated(true);
                    }
                });
    }

    private void setLeAudioStateObservers(
    private void setLeAudioStateObservers(
            @NonNull ViewHolder holder, LeAudioDeviceStateWrapper leAudioDeviceStateWrapper) {
            @NonNull ViewHolder holder, LeAudioDeviceStateWrapper leAudioDeviceStateWrapper) {
        LeAudioDeviceStateWrapper.LeAudioData le_audio_svc_data =
        LeAudioDeviceStateWrapper.LeAudioData le_audio_svc_data =
@@ -997,6 +1021,10 @@ public class LeAudioRecycleViewAdapter
        this.hapInteractionListener = listener;
        this.hapInteractionListener = listener;
    }
    }


    public void setOnGattBrConnectListener(@Nullable OnGattBrListener listener) {
        this.gattBrListener = listener;
    }

    // Device list update routine
    // Device list update routine
    // -----------------------------
    // -----------------------------
    public void updateLeAudioDeviceList(@Nullable List<LeAudioDeviceStateWrapper> devices) {
    public void updateLeAudioDeviceList(@Nullable List<LeAudioDeviceStateWrapper> devices) {
@@ -1119,6 +1147,10 @@ public class LeAudioRecycleViewAdapter
                String description);
                String description);
    }
    }


    public interface OnGattBrListener {
        void onToggleSwitch(LeAudioDeviceStateWrapper device, boolean switchState);
    }

    public interface OnHapInteractionListener {
    public interface OnHapInteractionListener {
        void onConnectClick(LeAudioDeviceStateWrapper leAudioDeviceStateWrapper);
        void onConnectClick(LeAudioDeviceStateWrapper leAudioDeviceStateWrapper);


@@ -1184,6 +1216,7 @@ public class LeAudioRecycleViewAdapter


        // LeAudio HAP stuff
        // LeAudio HAP stuff
        private Switch hapConnectionSwitch;
        private Switch hapConnectionSwitch;
        private Switch gattBrConnectionSwitch;
        private TextView leAudioHapState;
        private TextView leAudioHapState;
        private TextView leAudioHapFeatures;
        private TextView leAudioHapFeatures;
        private TextView leAudioHapActivePresetIndex;
        private TextView leAudioHapActivePresetIndex;
@@ -1249,6 +1282,7 @@ public class LeAudioRecycleViewAdapter
            SetupLeAudioView(itemView);
            SetupLeAudioView(itemView);
            setupVcView(itemView);
            setupVcView(itemView);
            setupHapView(itemView);
            setupHapView(itemView);
            setupGattBrView(itemView);
            setupBassView(itemView);
            setupBassView(itemView);


            // Notify viewmodel via parent's click listener
            // Notify viewmodel via parent's click listener
@@ -1261,6 +1295,21 @@ public class LeAudioRecycleViewAdapter
                    });
                    });
        }
        }


        private void setupGattBrView(@NonNull View itemView) {
            gattBrConnectionSwitch = itemView.findViewById(R.id.gatt_br_switch);
            gattBrConnectionSwitch.setActivated(true);

            gattBrConnectionSwitch.setOnCheckedChangeListener(
                    (compoundButton, b) -> {
                        if (!compoundButton.isActivated()) return;

                        if (gattBrListener != null) {
                            gattBrListener.onToggleSwitch(
                                    devices.get(ViewHolder.this.getAdapterPosition()), b);
                        }
                    });
        }

        private void setupHapView(@NonNull View itemView) {
        private void setupHapView(@NonNull View itemView) {
            hapConnectionSwitch = itemView.findViewById(R.id.hap_switch);
            hapConnectionSwitch = itemView.findViewById(R.id.hap_switch);
            hapConnectionSwitch.setActivated(true);
            hapConnectionSwitch.setActivated(true);
+6 −0
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@ package com.android.bluetooth.leaudio;
import android.app.Application;
import android.app.Application;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.content.Context;


import androidx.annotation.NonNull;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.AndroidViewModel;
@@ -73,6 +74,11 @@ public class LeAudioViewModel extends AndroidViewModel {
        bluetoothProxy.connectHap(device, connect);
        bluetoothProxy.connectHap(device, connect);
    }
    }


    public void connectGattBr(
            Context context, LeAudioDeviceStateWrapper device_wrapper, boolean connect) {
        bluetoothProxy.connectGattBr(context, device_wrapper, connect);
    }

    public void hapReadPresetInfo(BluetoothDevice device, int preset_index) {
    public void hapReadPresetInfo(BluetoothDevice device, int preset_index) {
        bluetoothProxy.hapReadPresetInfo(device, preset_index);
        bluetoothProxy.hapReadPresetInfo(device, preset_index);
    }
    }
+14 −0
Original line number Original line Diff line number Diff line
@@ -567,6 +567,20 @@ public class MainActivity extends AppCompatActivity {
                    }
                    }
                });
                });


        recyclerViewAdapter.setOnGattBrConnectListener(
                new LeAudioRecycleViewAdapter.OnGattBrListener() {
                    @Override
                    public void onToggleSwitch(
                            LeAudioDeviceStateWrapper device_wrapper, boolean switchState) {
                        Toast.makeText(
                                        MainActivity.this,
                                        "Connecting GATT BR to " + device_wrapper.device.toString(),
                                        Toast.LENGTH_SHORT)
                                .show();
                        leAudioViewModel.connectGattBr(
                                getApplicationContext(), device_wrapper, switchState);
                    }
                });
        recyclerViewAdapter.setOnHapInteractionListener(
        recyclerViewAdapter.setOnHapInteractionListener(
                new LeAudioRecycleViewAdapter.OnHapInteractionListener() {
                new LeAudioRecycleViewAdapter.OnHapInteractionListener() {
                    @Override
                    @Override
Loading