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

Commit 3615d8fa authored by Kihong Seong's avatar Kihong Seong
Browse files

Add GATT_CONNECTION_TIMEOUT and change connection timeout flow

Replace GATT_ERROR being returned to the developer when GATT connection
times out after 30 seconds, with new status code
GATT_CONNECTION_TIMEOUT.

Bug: 201571634
Bug: 320574336
Test: atest GattClientTest
Change-Id: I09e7fe32b67b40f5281f1f8cddfd2863bee2993e
parent 3a8de3f7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -627,6 +627,7 @@ package android.bluetooth {
    field public static final int CONNECTION_PRIORITY_HIGH = 1; // 0x1
    field public static final int CONNECTION_PRIORITY_LOW_POWER = 2; // 0x2
    field public static final int GATT_CONNECTION_CONGESTED = 143; // 0x8f
    field @FlaggedApi("com.android.bluetooth.flags.enumerate_gatt_errors") public static final int GATT_CONNECTION_TIMEOUT = 147; // 0x93
    field public static final int GATT_FAILURE = 257; // 0x101
    field public static final int GATT_INSUFFICIENT_AUTHENTICATION = 5; // 0x5
    field public static final int GATT_INSUFFICIENT_AUTHORIZATION = 8; // 0x8
+9 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.bluetooth;

import static android.bluetooth.BluetoothUtils.getSyncTimeout;

import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.RequiresNoPermission;
@@ -35,6 +36,7 @@ import android.os.ParcelUuid;
import android.os.RemoteException;
import android.util.Log;

import com.android.bluetooth.flags.Flags;
import com.android.modules.utils.SynchronousResultReceiver;

import java.lang.annotation.Retention;
@@ -128,6 +130,13 @@ public final class BluetoothGatt implements BluetoothProfile {
    /** A remote device connection is congested. */
    public static final int GATT_CONNECTION_CONGESTED = 0x8f;

    /**
     * GATT connection timed out, likely due to the remote device being out of range or not
     * advertising as connectable.
     */
    @FlaggedApi(Flags.FLAG_ENUMERATE_GATT_ERRORS)
    public static final int GATT_CONNECTION_TIMEOUT = 0x93;

    /** A GATT operation failed, errors other than the above */
    public static final int GATT_FAILURE = 0x101;

+1 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ android_test_helper_app {
        "androidx.test.rules",
        "bluetooth-test-util-lib",
        "compatibility-device-util-axt",
        "flag-junit",
        "grpc-java-lite",
        "grpc-java-okhttp-client-lite",
        "mockito-kotlin2",
+28 −3
Original line number Diff line number Diff line
@@ -31,10 +31,14 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;

import android.bluetooth.le.BluetoothLeScanner;
import android.content.Context;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;

import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;

import com.android.bluetooth.flags.Flags;
import com.android.compatibility.common.util.AdoptShellPermissionsRule;

import org.junit.ClassRule;
@@ -45,6 +49,9 @@ import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.invocation.Invocation;

import java.util.Collection;
import java.util.UUID;

import pandora.GattProto.GattCharacteristicParams;
import pandora.GattProto.GattServiceParams;
import pandora.GattProto.RegisterServiceRequest;
@@ -52,9 +59,6 @@ import pandora.HostProto.AdvertiseRequest;
import pandora.HostProto.AdvertiseResponse;
import pandora.HostProto.OwnAddressType;

import java.util.Collection;
import java.util.UUID;

@RunWith(AndroidJUnit4.class)
public class GattClientTest {
    private static final String TAG = "GattClientTest";
@@ -68,6 +72,9 @@ public class GattClientTest {

    @Rule public final PandoraDevice mBumble = new PandoraDevice();

    @Rule
    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();

    private final Context mContext = ApplicationProvider.getApplicationContext();
    private final BluetoothManager mManager = mContext.getSystemService(BluetoothManager.class);
    private final BluetoothAdapter mAdapter = mManager.getAdapter();
@@ -221,6 +228,24 @@ public class GattClientTest {
        }
    }

    @Test
    @RequiresFlagsEnabled(Flags.FLAG_ENUMERATE_GATT_ERRORS)
    public void connectTimeout() {
        BluetoothDevice device =
                mAdapter.getRemoteLeDevice(
                        Utils.BUMBLE_RANDOM_ADDRESS, BluetoothDevice.ADDRESS_TYPE_RANDOM);
        BluetoothGattCallback gattCallback = mock(BluetoothGattCallback.class);

        // Connecting to a device not advertising results in connection timeout after 30 seconds
        device.connectGatt(mContext, false, gattCallback);

        verify(gattCallback, timeout(35000))
                .onConnectionStateChange(
                        any(),
                        eq(BluetoothGatt.GATT_CONNECTION_TIMEOUT),
                        eq(BluetoothProfile.STATE_DISCONNECTED));
    }

    private void registerWritableGattService() {

        String characteristicUuidString = "11111111-1111-1111-1111-111111111111";
+17 −5
Original line number Diff line number Diff line
@@ -358,12 +358,24 @@ void bta_gattc_open_error(tBTA_GATTC_CLCB* p_clcb,

void bta_gattc_open_fail(tBTA_GATTC_CLCB* p_clcb,
                         UNUSED_ATTR const tBTA_GATTC_DATA* p_data) {
  if (IS_FLAG_ENABLED(enumerate_gatt_errors) &&
      p_data->int_conn.reason == GATT_CONN_TIMEOUT) {
    LOG(WARNING) << __func__
                 << ": Connection timed out after 30 seconds. conn_id="
                 << loghex(p_clcb->bta_conn_id)
                 << ". Return GATT_CONNECTION_TIMEOUT("
                 << +GATT_CONNECTION_TIMEOUT << ")";
    bta_gattc_send_open_cback(p_clcb->p_rcb, GATT_CONNECTION_TIMEOUT,
                              p_clcb->bda, p_clcb->bta_conn_id,
                              p_clcb->transport, 0);
  } else {
    LOG(WARNING) << __func__ << ": Cannot establish Connection. conn_id="
                 << loghex(p_clcb->bta_conn_id) << ". Return GATT_ERROR("
                 << +GATT_ERROR << ")";

    bta_gattc_send_open_cback(p_clcb->p_rcb, GATT_ERROR, p_clcb->bda,
                              p_clcb->bta_conn_id, p_clcb->transport, 0);
  }

  /* open failure, remove clcb */
  bta_gattc_clcb_dealloc(p_clcb);
}
Loading