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

Commit 5fc3bdef authored by Łukasz Rymanowski's avatar Łukasz Rymanowski
Browse files

GTBS: Track inband ringtone status per device

With this patch, GTBS starts tracking inaband ringtone status per
device.

This is in order to expose proper enable state for the devices which are
Active in the system and not.

Also it might be used for the use case when, remote device disables
Ringtone from the available context types

Bug: 242685105
Bug: 260660659
Test: atest BluetoothInstrumentationTests
Tag: #feature
Change-Id: I2f13a25f64f3bf7b37a3218ad6040e9a5c439c13
parent 4fac27a6
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -79,16 +79,38 @@ public class BluetoothGattServerProxy {
        return mBluetoothGattServer.getService(uuid);
    }

    /**
    * See {@link android.bluetooth.BluetoothGattServer#sendResponse(
    * android.bluetooth.BluetoothDevice, int, int, int, byte[])}
    */
    public boolean sendResponse(BluetoothDevice device, int requestId, int status, int offset,
            byte[] value) {
        return mBluetoothGattServer.sendResponse(device, requestId, status, offset, value);
    }

    /**
     * See {@link android.bluetooth.BluetoothGattServer#notifyCharacteristicChanged(
     * android.bluetooth.BluetoothDevice, BluetoothGattCharacteristic, boolean, byte[])}.
     */
    public int notifyCharacteristicChanged(BluetoothDevice device,
            BluetoothGattCharacteristic characteristic, boolean confirm, byte[] value) {
        return mBluetoothGattServer.notifyCharacteristicChanged(device, characteristic, confirm,
                                                                value);
    }

    /**
     * See {@link android.bluetooth.BluetoothGattServer#notifyCharacteristicChanged(
     * android.bluetooth.BluetoothDevice, BluetoothGattCharacteristic, boolean)}.
     */
    public boolean notifyCharacteristicChanged(BluetoothDevice device,
            BluetoothGattCharacteristic characteristic, boolean confirm) {
        return mBluetoothGattServer.notifyCharacteristicChanged(device, characteristic, confirm);
    }

    /**
     * Get connected devices
     * @return list of connected devices
     */
    public List<BluetoothDevice> getConnectedDevices() {
        return mBluetoothManager.getConnectedDevices(BluetoothProfile.GATT_SERVER);
    }
+103 −24
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ import com.android.internal.annotations.VisibleForTesting;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -141,6 +142,8 @@ public class TbsGatt {
    private final GattCharacteristic mTerminationReasonCharacteristic;
    private final GattCharacteristic mIncomingCallCharacteristic;
    private final GattCharacteristic mCallFriendlyNameCharacteristic;
    private boolean mSilentMode = false;
    private Map<BluetoothDevice, Integer> mStatusFlagValue = new HashMap<>();
    private List<BluetoothDevice> mSubscribers = new ArrayList<>();
    private BluetoothGattServerProxy mBluetoothGattServer;
    private Handler mHandler;
@@ -354,6 +357,14 @@ public class TbsGatt {
            return mSubscribers.contains(device);
        }

        private void notifyCharacteristicChanged(BluetoothDevice device,
                BluetoothGattCharacteristic characteristic, byte[] value) {
            if (mBluetoothGattServer != null) {
                mBluetoothGattServer.notifyCharacteristicChanged(device, characteristic, false,
                                                                 value);
            }
        }

        private void notifyCharacteristicChanged(BluetoothDevice device,
                BluetoothGattCharacteristic characteristic) {
            if (mBluetoothGattServer != null) {
@@ -361,6 +372,13 @@ public class TbsGatt {
            }
        }

        public void notifyWithValue(BluetoothDevice device,
                BluetoothGattCharacteristic characteristic, byte[] value) {
            if (isSubscribed(device)) {
                notifyCharacteristicChanged(device, characteristic, value);
            }
        }

        public void notify(BluetoothDevice device, BluetoothGattCharacteristic characteristic) {
            if (isSubscribed(device)) {
                notifyCharacteristicChanged(device, characteristic);
@@ -435,6 +453,11 @@ public class TbsGatt {
            return super.setValue(value);
        }

        public boolean notifyWithValue(BluetoothDevice device, byte[] value) {
            mNotifier.notifyWithValue(device, this, value);
            return true;
        }

        public boolean clearValue(boolean notify) {
            boolean success = super.setValue(new byte[0]);
            if (success && notify && isNotifiable()) {
@@ -604,34 +627,85 @@ public class TbsGatt {
        return mBearerListCurrentCallsCharacteristic.setValue(stream.toByteArray());
    }

    private boolean updateStatusFlags(int flag, boolean set) {
        Integer valueInt = mStatusFlagsCharacteristic
                .getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, 0);
    private boolean updateStatusFlags(BluetoothDevice device, int valueInt) {
        /* uint16_t */
        byte[] value = new byte[2];
        value[0] = (byte) (valueInt & 0xFF);
        value[1] = (byte) ((valueInt >> 8) & 0xFF);
        return mStatusFlagsCharacteristic.notifyWithValue(device, value);
    }

        if (((valueInt & flag) != 0) == set) {
    private boolean updateStatusFlagsInbandRingtone(BluetoothDevice device, boolean set) {
        boolean entryExist = mStatusFlagValue.containsKey(device);
        if (entryExist
                && (((mStatusFlagValue.get(device)
                        & STATUS_FLAG_INBAND_RINGTONE_ENABLED) != 0) == set)) {
            Log.i(TAG, "Silent mode already set for " + device);
            return false;
        }

        valueInt ^= flag;
        Integer valueInt = entryExist ? mStatusFlagValue.get(device) : 0;
        valueInt ^= STATUS_FLAG_INBAND_RINGTONE_ENABLED;

        return mStatusFlagsCharacteristic.setValue(valueInt,
                BluetoothGattCharacteristic.FORMAT_UINT16, 0);
        if (entryExist) {
            mStatusFlagValue.replace(device, valueInt);
        } else {
            mStatusFlagValue.put(device, valueInt);
        }
        return updateStatusFlags(device, valueInt);
    }

    public boolean setInbandRingtoneFlag() {
        return updateStatusFlags(STATUS_FLAG_INBAND_RINGTONE_ENABLED, true);
    private boolean updateStatusFlagsSilentMode(boolean set) {
        mSilentMode = set;
        for (BluetoothDevice device: mSubscribers) {
            boolean entryExist = mStatusFlagValue.containsKey(device);
            if (entryExist
                    && (((mStatusFlagValue.get(device)
                            & STATUS_FLAG_SILENT_MODE_ENABLED) != 0) == set)) {
                Log.i(TAG, "Silent mode already set for " + device);
                continue;
            }

            Integer valueInt = entryExist ? mStatusFlagValue.get(device) : 0;
            valueInt ^= STATUS_FLAG_SILENT_MODE_ENABLED;

            if (entryExist) {
                mStatusFlagValue.replace(device, valueInt);
            } else {
                mStatusFlagValue.put(device, valueInt);
            }
            updateStatusFlags(device, valueInt);
        }
        return true;
    }

    public boolean clearInbandRingtoneFlag() {
        return updateStatusFlags(STATUS_FLAG_INBAND_RINGTONE_ENABLED, false);
    /**
     * Set inband ringtone for the device.
     * When set, notification will be sent to given device.
     *
     * @param device    device for which inband ringtone has been set
     * @return          true, when notification has been sent, false otherwise
     */
    public boolean setInbandRingtoneFlag(BluetoothDevice device) {
        return updateStatusFlagsInbandRingtone(device, true);
    }

    /**
     * Clear inband ringtone for the device.
     * When set, notification will be sent to given device.
     *
     * @param device    device for which inband ringtone has been cleared
     * @return          true, when notification has been sent, false otherwise
     */
    public boolean clearInbandRingtoneFlag(BluetoothDevice device) {
        return updateStatusFlagsInbandRingtone(device, false);
    }
    public boolean setSilentModeFlag() {
        return updateStatusFlags(STATUS_FLAG_SILENT_MODE_ENABLED, true);
        return updateStatusFlagsSilentMode(true);
    }

    public boolean clearSilentModeFlag() {
        return updateStatusFlags(STATUS_FLAG_SILENT_MODE_ENABLED, false);
        return updateStatusFlagsSilentMode(false);
    }

    private void setCallControlPointOptionalOpcodes(boolean isLocalHoldOpcodeSupported,
@@ -810,18 +884,23 @@ public class TbsGatt {
            if (DBG) {
                Log.d(TAG, "onCharacteristicReadRequest: device=" + device);
            }
            byte[] value;
            if (characteristic.getUuid().equals(UUID_STATUS_FLAGS)) {
                value = new byte[2];
                int valueInt = mSilentMode ? STATUS_FLAG_SILENT_MODE_ENABLED : 0;
                if (mStatusFlagValue.containsKey(device)) {
                    valueInt = mStatusFlagValue.get(device);
                } else if (mCallback.isInbandRingtoneEnabled(device)) {
                    valueInt |= STATUS_FLAG_INBAND_RINGTONE_ENABLED;
                }
                value[0] = (byte) (valueInt & 0xFF);
                value[1] = (byte) ((valueInt >> 8) & 0xFF);
            } else {
                GattCharacteristic gattCharacteristic = (GattCharacteristic) characteristic;
            byte[] value = gattCharacteristic.getValue();
                value = gattCharacteristic.getValue();
                if (value == null) {
                    value = new byte[0];
                }
            /* TODO: Properly handle caching for multiple devices.
             * This patch assumes, LeAudio services just uses single value
             * for inband ringtone */
            if (characteristic.getUuid().equals(UUID_STATUS_FLAGS) && (value.length == 2)) {
                if (mCallback.isInbandRingtoneEnabled(device)) {
                    value[0] = (byte) (value[0] | STATUS_FLAG_INBAND_RINGTONE_ENABLED);
                }
            }

            int status;
+28 −0
Original line number Diff line number Diff line
@@ -216,6 +216,34 @@ public class TbsGeneric {
        mIsInitialized = false;
    }

    /**
     * Set inband ringtone for the device.
     * When set, notification will be sent to given device.
     *
     * @param device    device for which inband ringtone has been set
     */
    public synchronized void setInbandRingtoneSupport(BluetoothDevice device) {
        if (mTbsGatt == null) {
            Log.w(TAG, "setInbandRingtoneSupport, mTbsGatt is null");
            return;
        }
        mTbsGatt.setInbandRingtoneFlag(device);
    }

    /**
     * Clear inband ringtone for the device.
     * When set, notification will be sent to given device.
     *
     * @param device    device for which inband ringtone has been cleared
     */
    public synchronized void clearInbandRingtoneSupport(BluetoothDevice device) {
        if (mTbsGatt == null) {
            Log.w(TAG, "setInbandRingtoneSupport, mTbsGatt is null");
            return;
        }
        mTbsGatt.clearInbandRingtoneFlag(device);
    }

    private synchronized boolean isSilentModeEnabled() {
        return mStoredRingerMode != AudioManager.RINGER_MODE_NORMAL;
    }
+30 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@

package com.android.bluetooth.tbs;

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeCall;
import android.bluetooth.IBluetoothLeCallControl;
import android.bluetooth.IBluetoothLeCallControlCallback;
@@ -132,6 +133,35 @@ public class TbsService extends ProfileService {
        sTbsService = instance;
    }

    /**
     * Set inband ringtone for the device.
     * When set, notification will be sent to given device.
     *
     * @param device    device for which inband ringtone has been set
     */
    public void setInbandRingtoneSupport(BluetoothDevice device) {
        if (mTbsGeneric == null) {
            Log.i(TAG, "setInbandRingtoneSupport, mTbsGeneric not available");
            return;
        }
        mTbsGeneric.setInbandRingtoneSupport(device);
    }

    /**
     * Clear inband ringtone for the device.
     * When set, notification will be sent to given device.
     *
     * @param device    device for which inband ringtone has been clear
     */
    public void clearInbandRingtoneSupport(BluetoothDevice device) {
        if (mTbsGeneric == null) {
            Log.i(TAG, "clearInbandRingtoneSupport, mTbsGeneric not available");
            return;
        }
        mTbsGeneric.clearInbandRingtoneSupport(device);
    }


    /** Binder object: must be a static class or memory leak may occur */
    @VisibleForTesting
    static class TbsServerBinder extends IBluetoothLeCallControl.Stub implements IProfileServiceBinder {
+184 −56

File changed.

Preview size limit exceeded, changes collapsed.

Loading