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

Commit a6b81d3f authored by William Escande's avatar William Escande Committed by Gerrit Code Review
Browse files

Merge changes Idca8b425,I05f80175,I7ab00978,I88151930

* changes:
  BT5.3 Subrating -- feature flags
  BT5.3 Subrating -- Gd cleanup
  BT5.3 Enhanced conn update - Bluetooth apk and SDK API
  BT5.3 Enhanced Connection update
parents 1b2f9cbc abdf101a
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
@@ -143,6 +143,7 @@ static jmethodID method_onClientPhyUpdate;
static jmethodID method_onClientPhyRead;
static jmethodID method_onClientConnUpdate;
static jmethodID method_onServiceChanged;
static jmethodID method_onClientSubrateChange;

/**
 * Server callback methods
@@ -164,6 +165,7 @@ static jmethodID method_onServerMtuChanged;
static jmethodID method_onServerPhyUpdate;
static jmethodID method_onServerPhyRead;
static jmethodID method_onServerConnUpdate;
static jmethodID method_onServerSubrateChange;

/**
 * Advertiser callback methods
@@ -571,6 +573,18 @@ void btgattc_service_changed_cb(int conn_id) {
  sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onServiceChanged, conn_id);
}

void btgattc_subrate_change_cb(int conn_id, uint16_t subrate_factor,
                               uint16_t latency, uint16_t cont_num,
                               uint16_t timeout, uint8_t status) {
  std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid() || !mCallbacksObj) return;

  sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onClientSubrateChange,
                               conn_id, subrate_factor, latency, cont_num,
                               timeout, status);
}

static const btgatt_scanner_callbacks_t sGattScannerCallbacks = {
    btgattc_scan_result_cb,
    btgattc_batchscan_reports_cb,
@@ -599,6 +613,7 @@ static const btgatt_client_callbacks_t sGattClientCallbacks = {
    btgattc_phy_updated_cb,
    btgattc_conn_updated_cb,
    btgattc_service_changed_cb,
    btgattc_subrate_change_cb,
};

/**
@@ -795,6 +810,18 @@ void btgatts_conn_updated_cb(int conn_id, uint16_t interval, uint16_t latency,
                               conn_id, interval, latency, timeout, status);
}

void btgatts_subrate_change_cb(int conn_id, uint16_t subrate_factor,
                               uint16_t latency, uint16_t cont_num,
                               uint16_t timeout, uint8_t status) {
  std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid() || !mCallbacksObj) return;

  sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onServerSubrateChange,
                               conn_id, subrate_factor, latency, cont_num,
                               timeout, status);
}

static const btgatt_server_callbacks_t sGattServerCallbacks = {
    btgatts_register_app_cb,
    btgatts_connection_cb,
@@ -812,6 +839,7 @@ static const btgatt_server_callbacks_t sGattServerCallbacks = {
    btgatts_mtu_changed_cb,
    btgatts_phy_updated_cb,
    btgatts_conn_updated_cb,
    btgatts_subrate_change_cb,
};

/**
@@ -1175,6 +1203,8 @@ static void classInitNative(JNIEnv* env, jclass clazz) {
      env->GetMethodID(clazz, "onClientConnUpdate", "(IIIII)V");
  method_onServiceChanged =
      env->GetMethodID(clazz, "onServiceChanged", "(I)V");
  method_onClientSubrateChange =
      env->GetMethodID(clazz, "onClientSubrateChange", "(IIIIII)V");

  // Server callbacks

@@ -1211,6 +1241,8 @@ static void classInitNative(JNIEnv* env, jclass clazz) {
      env->GetMethodID(clazz, "onServerPhyUpdate", "(IIII)V");
  method_onServerConnUpdate =
      env->GetMethodID(clazz, "onServerConnUpdate", "(IIIII)V");
  method_onServerSubrateChange =
      env->GetMethodID(clazz, "onServerSubrateChange", "(IIIIII)V");

  info("classInitNative: Success!");
}
@@ -1787,6 +1819,17 @@ static void gattConnectionParameterUpdateNative(JNIEnv* env, jobject object,
      (uint16_t)min_ce_len, (uint16_t)max_ce_len);
}

static void gattSubrateRequestNative(JNIEnv* env, jobject object,
                                     jint client_if, jstring address,
                                     jint subrate_min, jint subrate_max,
                                     jint max_latency, jint cont_num,
                                     jint sup_timeout) {
  if (!sGattIf) return;
  sGattIf->client->subrate_request(str2addr(env, address), subrate_min,
                                   subrate_max, max_latency, cont_num,
                                   sup_timeout);
}

void batchscan_cfg_storage_cb(uint8_t client_if, uint8_t status) {
  std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
  CallbackEnv sCallbackEnv(__func__);
@@ -2588,6 +2631,8 @@ static JNINativeMethod sMethods[] = {
     (void*)gattServerSendNotificationNative},
    {"gattServerSendResponseNative", "(IIIIII[BI)V",
     (void*)gattServerSendResponseNative},
    {"gattSubrateRequestNative", "(ILjava/lang/String;IIIII)V",
     (void*)gattSubrateRequestNative},

    {"gattTestNative", "(IJJLjava/lang/String;IIIII)V", (void*)gattTestNative},
};
+23 −0
Original line number Diff line number Diff line
@@ -40,6 +40,29 @@
    <integer name="gatt_balanced_priority_latency">0</integer>
    <integer name="gatt_low_power_latency">2</integer>

    <!-- Specifies the min/max subrate factor parameters for high priority,
         balanced and low power subrate request configurations. -->
    <integer name="subrate_mode_high_priority_min_subrate">2</integer>
    <integer name="subrate_mode_high_priority_max_subrate">4</integer>
    <integer name="subrate_mode_balanced_min_subrate">4</integer>
    <integer name="subrate_mode_balanced_max_subrate">7</integer>
    <integer name="subrate_mode_low_power_min_subrate">4</integer>
    <integer name="subrate_mode_low_power_max_subrate">10</integer>

    <!-- Specifies max latency parameters for high priority, balanced
         and low power subrate request configurations. These values
         represents the number of subrate events a peripheral device
         is allowed to skip. -->
    <integer name="subrate_mode_high_priority_latency">0</integer>
    <integer name="subrate_mode_balanced_latency">1</integer>
    <integer name="subrate_mode_low_power_latency">1</integer>

    <!-- Specifies continuation number parameters for high priority,
         balanced and low power subrate request configurations. -->
    <integer name="subrate_mode_high_priority_cont_number">2</integer>
    <integer name="subrate_mode_balanced_cont_number">2</integer>
    <integer name="subrate_mode_low_power_cont_number">2</integer>

    <bool name="headset_client_initial_audio_route_allowed">true</bool>

    <!-- @deprecated: use a2dp_absolute_volume_initial_threshold_percent
+24 −0
Original line number Diff line number Diff line
@@ -104,6 +104,12 @@ public class GattNativeInterface {
        getGattService().onServiceChanged(connId);
    }

    void onClientSubrateChange(int connId, int subrateFactor, int latency, int contNum, int timeout,
            int status) throws RemoteException {
        getGattService().onClientSubrateChange(connId, subrateFactor, latency, contNum, timeout,
                status);
    }

    void onServerPhyUpdate(int connId, int txPhy, int rxPhy, int status) throws RemoteException {
        getGattService().onServerPhyUpdate(connId, txPhy, rxPhy, status);
    }
@@ -118,6 +124,13 @@ public class GattNativeInterface {
        getGattService().onServerConnUpdate(connId, interval, latency, timeout, status);
    }

    void onServerSubrateChange(int connId, int subrateFactor, int latency, int contNum, int timeout,
            int status)
            throws RemoteException {
        getGattService().onServerSubrateChange(connId, subrateFactor, latency, contNum, timeout,
                status);
    }

    void onSearchCompleted(int connId, int status) throws RemoteException {
        getGattService().onSearchCompleted(connId, status);
    }
@@ -345,6 +358,8 @@ public class GattNativeInterface {
            byte[] val);
    private native void gattServerSendResponseNative(int serverIf, int connId, int transId,
            int status, int handle, int offset, byte[] val, int authReq);
    private native void gattSubrateRequestNative(int clientIf, String address, int subrateMin,
            int subrateMax, int maxLatency, int contNumber, int supervisionTimeout);
    private native void gattTestNative(int command, long uuid1Lsb, long uuid1Msb, String bda1,
            int p1, int p2, int p3, int p4, int p5);

@@ -534,6 +549,15 @@ public class GattNativeInterface {
                timeout, minConnectionEventLen, maxConnectionEventLen);
    }

    /**
     * Update connection parameter.
     */
    public void gattSubrateRequest(int clientIf, String address, int subrateMin, int subrateMax,
            int maxLatency, int contNumber, int supervisionTimeout) {
        gattSubrateRequestNative(clientIf, address, subrateMin, subrateMax, maxLatency, contNumber,
                supervisionTimeout);
    }

    /**
     * Register GATT server
     */
+160 −1
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothProtoEnums;
import android.bluetooth.BluetoothStatusCodes;
import android.bluetooth.BluetoothUtils;
import android.bluetooth.IBluetoothGatt;
import android.bluetooth.IBluetoothGattCallback;
import android.bluetooth.IBluetoothGattServerCallback;
@@ -94,9 +95,10 @@ import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Predicate;

import android.content.res.Resources;

/**
 * Provides Bluetooth Gatt profile, as a service in
 * the Bluetooth application.
@@ -1166,6 +1168,48 @@ public class GattService extends ProfileService {
                                       maxConnectionEventLen, attributionSource);
        }

        @Override
        public void subrateModeRequest(int clientIf, String address, int subrateMode,
                AttributionSource attributionSource, SynchronousResultReceiver receiver) {
            try {
                subrateModeRequest(clientIf, address, subrateMode, attributionSource);
                receiver.send(null);
            } catch (RuntimeException e) {
                receiver.propagateException(e);
            }
        }
        private void subrateModeRequest(int clientIf, String address, int subrateMode,
                AttributionSource attributionSource) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.subrateModeRequest(clientIf, address, subrateMode, attributionSource);
        }

        @Override
        public void leSubrateRequest(int clientIf, String address, int subrateMin, int subrateMax,
                int maxLatency, int contNumber, int supervisionTimeout,
                AttributionSource attributionSource, SynchronousResultReceiver receiver) {
            try {
                leSubrateRequest(clientIf, address, subrateMin, subrateMax, maxLatency, contNumber,
                                 supervisionTimeout, attributionSource);
                receiver.send(null);
            } catch (RuntimeException e) {
                receiver.propagateException(e);
            }
        }
        private void leSubrateRequest(int clientIf, String address, int subrateMin, int subrateMax,
                int maxLatency, int contNumber, int supervisionTimeout,
                AttributionSource attributionSource) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.leSubrateRequest(clientIf, address, subrateMin, subrateMax, maxLatency,
                                     contNumber, supervisionTimeout, attributionSource);
        }

        @Override
        public void registerServer(ParcelUuid uuid, IBluetoothGattServerCallback callback,
                boolean eattSupport, AttributionSource attributionSource,
@@ -2155,6 +2199,25 @@ public class GattService extends ProfileService {
        app.callback.onServiceChanged(address);
    }

    void onClientSubrateChange(int connId, int subrateFactor, int latency, int contNum,
            int timeout, int status) throws RemoteException {
        if (DBG) {
            Log.d(TAG, "onClientSubrateChange() - connId=" + connId + ", status=" + status);
        }

        String address = mClientMap.addressByConnId(connId);
        if (address == null) {
            return;
        }

        ClientMap.App app = mClientMap.getByConnId(connId);
        if (app == null) {
            return;
        }

        app.callback.onSubrateChange(address, subrateFactor, latency, contNum, timeout, status);
    }

    void onServerPhyUpdate(int connId, int txPhy, int rxPhy, int status) throws RemoteException {
        if (DBG) {
            Log.d(TAG, "onServerPhyUpdate() - connId=" + connId + ", status=" + status);
@@ -2212,6 +2275,26 @@ public class GattService extends ProfileService {
        app.callback.onConnectionUpdated(address, interval, latency, timeout, status);
    }

    void onServerSubrateChange(int connId, int subrateFactor, int latency, int contNum,
            int timeout, int status)
            throws RemoteException {
        if (DBG) {
            Log.d(TAG, "onServerSubrateChange() - connId=" + connId + ", status=" + status);
        }

        String address = mServerMap.addressByConnId(connId);
        if (address == null) {
            return;
        }

        ServerMap.App app = mServerMap.getByConnId(connId);
        if (app == null) {
            return;
        }

        app.callback.onSubrateChange(address, subrateFactor, latency, contNum, timeout, status);
    }

    void onSearchCompleted(int connId, int status) throws RemoteException {
        if (DBG) {
            Log.d(TAG, "onSearchCompleted() - connId=" + connId + ", status=" + status);
@@ -3909,6 +3992,82 @@ public class GattService extends ProfileService {
                                            minConnectionEventLen, maxConnectionEventLen);
    }

    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    void subrateModeRequest(int clientIf, String address, int subrateMode,
                                   AttributionSource attributionSource) {
        if (!Utils.checkConnectPermissionForDataDelivery(
                this, attributionSource, "GattService subrateModeRequest")) {
            return;
        }

        int subrateMin;
        int subrateMax;
        int maxLatency;
        int contNumber;
        // Link supervision timeout is measured in N * 10ms
        int supervisionTimeout = 500; // 5s

        Resources res = getResources();

        switch (subrateMode) {
            case BluetoothGatt.SUBRATE_REQUEST_MODE_HIGH:
                subrateMin = res.getInteger(R.integer.subrate_mode_high_priority_min_subrate);
                subrateMax = res.getInteger(R.integer.subrate_mode_high_priority_max_subrate);
                maxLatency = res.getInteger(R.integer.subrate_mode_high_priority_latency);
                contNumber = res.getInteger(R.integer.subrate_mode_high_priority_cont_number);
                break;

            case BluetoothGatt.SUBRATE_REQUEST_MODE_LOW_POWER:
                subrateMin = res.getInteger(R.integer.subrate_mode_low_power_min_subrate);
                subrateMax = res.getInteger(R.integer.subrate_mode_low_power_max_subrate);
                maxLatency = res.getInteger(R.integer.subrate_mode_low_power_latency);
                contNumber = res.getInteger(R.integer.subrate_mode_low_power_cont_number);
                break;

            case BluetoothGatt.SUBRATE_REQUEST_MODE_BALANCED:
            default:
                subrateMin = res.getInteger(R.integer.subrate_mode_balanced_min_subrate);
                subrateMax = res.getInteger(R.integer.subrate_mode_balanced_max_subrate);
                maxLatency = res.getInteger(R.integer.subrate_mode_balanced_latency);
                contNumber = res.getInteger(R.integer.subrate_mode_balanced_cont_number);
                break;
        }

        if (DBG) {
            Log.d(TAG, "subrateModeRequest() - "
                    + "address=" + BluetoothUtils.toAnonymizedAddress(address)
                    + ", subrate min/max=" + subrateMin + "/" + subrateMax
                    + ", maxLatency=" + maxLatency
                    + ", continuation Number=" + contNumber
                    + ", timeout=" + supervisionTimeout);
        }

        mNativeInterface.gattSubrateRequest(clientIf, address, subrateMin, subrateMax, maxLatency,
                                 contNumber, supervisionTimeout);
    }

    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    void leSubrateRequest(int clientIf, String address, int subrateMin, int subrateMax,
            int maxLatency, int contNumber, int supervisionTimeout,
            AttributionSource attributionSource) {
        if (!Utils.checkConnectPermissionForDataDelivery(
                this, attributionSource, "GattService leSubrateRequest")) {
            return;
        }

        if (DBG) {
            Log.d(TAG, "leSubrateRequest() - "
                    + "address=" + BluetoothUtils.toAnonymizedAddress(address)
                    + ", subrate min/max=" + subrateMin + "/" + subrateMax
                    + ", maxLatency=" + maxLatency
                    + ", continuation Number=" + contNumber
                    + ", timeout=" + supervisionTimeout);
        }

        mNativeInterface.gattSubrateRequest(clientIf, address, subrateMin, subrateMax, maxLatency,
                contNumber, supervisionTimeout);
    }

    /**************************************************************************
     * Callback functions - SERVER
     *************************************************************************/
+133 −0
Original line number Diff line number Diff line
@@ -149,6 +149,38 @@ public final class BluetoothGatt implements BluetoothProfile {
    /** Connection parameter update - Request low power, reduced data rate connection parameters. */
    public static final int CONNECTION_PRIORITY_LOW_POWER = 2;

    /**
     * Connection subrate request - Balanced.
     *
     * @hide
     */
    public static final int SUBRATE_REQUEST_MODE_BALANCED = 0;

    /**
     * Connection subrate request - High.
     *
     * @hide
     */
    public static final int SUBRATE_REQUEST_MODE_HIGH = 1;

    /**
     * Connection Subrate Request - Low Power.
     *
     * @hide
     */
    public static final int SUBRATE_REQUEST_MODE_LOW_POWER = 2;

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = {"SUBRATE_REQUEST_MODE"},
            value =
                    {
                            SUBRATE_REQUEST_MODE_BALANCED,
                            SUBRATE_REQUEST_MODE_HIGH,
                            SUBRATE_REQUEST_MODE_LOW_POWER,
                    })
    public @interface SubrateRequestMode {}

    /**
     * No authentication required.
     *
@@ -769,6 +801,36 @@ public final class BluetoothGatt implements BluetoothProfile {
                        }
                    });
                }

                /**
                 * Callback invoked when the given connection's subrate is changed
                 * @hide
                 */
                @Override
                public void onSubrateChange(String address, int subrateFactor, int latency,
                        int contNum, int timeout, int status) {
                    Log.d(TAG,
                            "onSubrateChange() - "
                                    + "Device=" + BluetoothUtils.toAnonymizedAddress(address)
                                    + ", subrateFactor=" + subrateFactor + ", latency=" + latency
                                    + ", contNum=" + contNum + ", timeout=" + timeout
                                    + ", status=" + status);

                    if (!address.equals(mDevice.getAddress())) {
                        return;
                    }

                    runOrQueueCallback(new Runnable() {
                        @Override
                        public void run() {
                            final BluetoothGattCallback callback = mCallback;
                            if (callback != null) {
                                callback.onSubrateChange(BluetoothGatt.this, subrateFactor, latency,
                                        contNum, timeout, status);
                            }
                        }
                    });
                }
            };

    /* package */ BluetoothGatt(IBluetoothGatt iGatt, BluetoothDevice device, int transport,
@@ -1879,6 +1941,77 @@ public final class BluetoothGatt implements BluetoothProfile {
        return true;
    }

    /**
     * Request LE subrate mode.
     *
     * <p>This function will send a LE subrate request to the remote device.
     *
     * @param subrateMode Request a specific subrate mode.
     * @throws IllegalArgumentException If the parameters are outside of their specified range.
     * @return true, if the request is send to the Bluetooth stack.
     * @hide
     */
    @RequiresBluetoothConnectPermission
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public boolean requestSubrateMode(@SubrateRequestMode int subrateMode) {
        if (subrateMode < SUBRATE_REQUEST_MODE_BALANCED
                || subrateMode > SUBRATE_REQUEST_MODE_LOW_POWER) {
            throw new IllegalArgumentException("Subrate Mode not within valid range");
        }

        if (DBG) {
            Log.d(TAG, "requestsubrateMode() - subrateMode: " + subrateMode);
        }
        if (mService == null || mClientIf == 0) {
            return false;
        }

        try {
            final SynchronousResultReceiver recv = SynchronousResultReceiver.get();
            mService.subrateModeRequest(
                    mClientIf, mDevice.getAddress(), subrateMode, mAttributionSource, recv);
            recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
        } catch (RemoteException | TimeoutException e) {
            Log.e(TAG, "", e);
            return false;
        }
        return true;
    }

    /**
     * Request a LE subrate request.
     *
     * <p>This function will send a LE subrate request to the remote device.
     *
     * @return true, if the request is send to the Bluetooth stack.
     * @hide
     */
    @RequiresBluetoothConnectPermission
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public boolean bleSubrateRequest(int subrateMin, int subrateMax, int maxLatency, int contNumber,
            int supervisionTimeout) {
        if (DBG) {
            Log.d(TAG,
                    "bleSubrateRequest() - subrateMin=" + subrateMin + " subrateMax=" + (subrateMax)
                            + " maxLatency= " + maxLatency + "contNumber=" + contNumber
                            + " supervisionTimeout=" + supervisionTimeout);
        }
        if (mService == null || mClientIf == 0) {
            return false;
        }

        try {
            final SynchronousResultReceiver recv = SynchronousResultReceiver.get();
            mService.leSubrateRequest(mClientIf, mDevice.getAddress(), subrateMin, subrateMax,
                    maxLatency, contNumber, supervisionTimeout, mAttributionSource, recv);
            recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
        } catch (RemoteException | TimeoutException e) {
            Log.e(TAG, "", e);
            return false;
        }
        return true;
    }

    /**
     * @deprecated Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
     * with {@link BluetoothProfile#GATT} as argument
Loading