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

Commit 8d60d9af authored by Łukasz Rymanowski's avatar Łukasz Rymanowski Committed by Gerrit Code Review
Browse files

Merge "GTBS: Track inband ringtone status per device"

parents a7705759 5fc3bdef
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