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

Commit 4aa7d1c8 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 11896415 from 3deead7f to 24Q3-release

Change-Id: Iac09af7746e4acc10465d9acedaadce4357ee7a7
parents 036d4313 3deead7f
Loading
Loading
Loading
Loading
+1 −16
Original line number Diff line number Diff line
@@ -1749,15 +1749,7 @@ public class BassClientStateMachine extends StateMachine {
            log("Enter Connected(" + mDevice + "): "
                    + messageWhatToString(getCurrentMessage().what));
            removeDeferredMessages(CONNECT);
            if (mLastConnectionState == BluetoothProfile.STATE_CONNECTED) {
                log("CONNECTED->CONNECTED: Ignore");
                // Broadcast for testing purpose only
                if (Utils.isInstrumentationTestMode()) {
                    Intent intent = new Intent("android.bluetooth.bass_client.NOTIFY_TEST");
                    mService.sendBroadcast(
                            intent, BLUETOOTH_CONNECT, Utils.getTempBroadcastOptions().toBundle());
                }
            } else {
            if (mLastConnectionState != BluetoothProfile.STATE_CONNECTED) {
                broadcastConnectionState(mDevice, mLastConnectionState,
                        BluetoothProfile.STATE_CONNECTED);
            }
@@ -2169,13 +2161,6 @@ public class BassClientStateMachine extends StateMachine {
        public void enter() {
            log("Enter ConnectedProcessing(" + mDevice + "): "
                    + messageWhatToString(getCurrentMessage().what));

            // Broadcast for testing purpose only
            if (Utils.isInstrumentationTestMode()) {
                Intent intent = new Intent("android.bluetooth.bass_client.NOTIFY_TEST");
                mService.sendBroadcast(
                        intent, BLUETOOTH_CONNECT, Utils.getTempBroadcastOptions().toBundle());
            }
        }
        @Override
        public void exit() {
+10 −8
Original line number Diff line number Diff line
@@ -1247,6 +1247,7 @@ public class RemoteDevices {
        String address = device.getAddress();
        if (Flags.temporaryPairingDeviceProperties() && oldState != BluetoothDevice.BOND_BONDED) {
            DeviceProperties deviceProperties = mDevices.get(address);
            if (deviceProperties != null) {
                int leConnectionHandle =
                        deviceProperties.getConnectionHandle(BluetoothDevice.TRANSPORT_LE);
                int bredrConnectionHandle =
@@ -1257,6 +1258,7 @@ public class RemoteDevices {
                    return;
                }
            }
        }

        if (Flags.removeAddressMapOnUnbond() && newState == BluetoothDevice.BOND_NONE) {
            removeAddressMapping(address);
+76 −7
Original line number Diff line number Diff line
@@ -18,6 +18,11 @@ package com.android.bluetooth.bass_client;

import static android.bluetooth.BluetoothGatt.GATT_FAILURE;
import static android.bluetooth.BluetoothGatt.GATT_SUCCESS;
import static android.Manifest.permission.BLUETOOTH_CONNECT;

import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction;
import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra;
import static androidx.test.espresso.intent.matcher.IntentMatchers.hasFlag;

import static com.android.bluetooth.bass_client.BassClientStateMachine.ADD_BCAST_SOURCE;
import static com.android.bluetooth.bass_client.BassClientStateMachine.CONNECT;
@@ -68,6 +73,7 @@ import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothLeAudioCodecConfigMetadata;
import android.bluetooth.BluetoothLeAudioContentMetadata;
import android.bluetooth.BluetoothLeBroadcastAssistant;
import android.bluetooth.BluetoothLeBroadcastChannel;
import android.bluetooth.BluetoothLeBroadcastMetadata;
import android.bluetooth.BluetoothLeBroadcastReceiveState;
@@ -97,7 +103,9 @@ import com.android.bluetooth.flags.Flags;

import com.google.common.primitives.Bytes;

import org.hamcrest.core.AllOf;
import org.hamcrest.core.IsInstanceOf;
import org.hamcrest.Matcher;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
@@ -106,6 +114,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.ArgumentCaptor;
import org.mockito.hamcrest.MockitoHamcrest;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnit;
@@ -127,6 +136,7 @@ public class BassClientStateMachineTest {

    private static final int CONNECTION_TIMEOUT_MS = 1_000;
    private static final int TIMEOUT_MS = 2_000;
    private static final int NO_TIMEOUT_MS = 0;
    private static final int WAIT_MS = 1_200;
    private static final String TEST_BROADCAST_NAME = "Test";
    private static final String EMPTY_BLUETOOTH_DEVICE_ADDRESS = "00:00:00:00:00:00";
@@ -179,6 +189,20 @@ public class BassClientStateMachineTest {
        mBassClientStateMachine.start();
    }

    private int classTypeToConnectionState(Class type) {
        if (type == BassClientStateMachine.Disconnected.class) {
            return BluetoothProfile.STATE_DISCONNECTED;
        } else if (type == BassClientStateMachine.Connecting.class) {
            return BluetoothProfile.STATE_CONNECTING;
        } else if (type == BassClientStateMachine.Connected.class
                || type == BassClientStateMachine.ConnectedProcessing.class) {
            return BluetoothProfile.STATE_CONNECTED;
        } else {
            Assert.fail("Invalid class type given: " + type);
            return 0;
        }
    }

    @After
    public void tearDown() throws Exception {
        if (mBassClientStateMachine == null) {
@@ -316,6 +340,9 @@ public class BassClientStateMachineTest {
        allowConnection(true);
        allowConnectGatt(true);

        BassClientStateMachine.BluetoothGattTestableWrapper btGatt =
                Mockito.mock(BassClientStateMachine.BluetoothGattTestableWrapper.class);
        mBassClientStateMachine.mBluetoothGatt = btGatt;
        // need this to ensure expected mock behavior for getActiveSyncedSource
        when(mBassClientService.getActiveSyncedSources(any())).thenReturn(null);

@@ -327,19 +354,25 @@ public class BassClientStateMachineTest {
                mBassClientStateMachine.obtainMessage(CONNECT),
                BassClientStateMachine.Connecting.class);
        sendMessageAndVerifyTransition(
                mBassClientStateMachine.obtainMessage(BassClientStateMachine.CONNECT_TIMEOUT),
                mBassClientStateMachine.obtainMessage(
                        BassClientStateMachine.CONNECT_TIMEOUT, mTestDevice),
                BassClientStateMachine.Disconnected.class);

        // disconnected -> connecting ---DISCONNECT---> disconnected
        // disconnected -> connecting ---DISCONNECT---> CONNECTION_STATE_CHANGED(connected)
        // --> connected -> disconnected
        mBassClientStateMachine.mBluetoothGatt = btGatt;
        sendMessageAndVerifyTransition(
                mBassClientStateMachine.obtainMessage(CONNECT),
                BassClientStateMachine.Connecting.class);
        sendMessageAndVerifyTransition(
                mBassClientStateMachine.obtainMessage(BassClientStateMachine.DISCONNECT),
                BassClientStateMachine.Disconnected.class);
                BassClientStateMachine.Connecting.class);
        mBassClientStateMachine.sendMessage(
                CONNECTION_STATE_CHANGED, Integer.valueOf(BluetoothProfile.STATE_CONNECTED));

        // disconnected -> connecting ---CONNECTION_STATE_CHANGED(connected)---> connected -->
        // disconnected
        mBassClientStateMachine.mBluetoothGatt = btGatt;
        sendMessageAndVerifyTransition(
                mBassClientStateMachine.obtainMessage(CONNECT),
                BassClientStateMachine.Connecting.class);
@@ -2248,13 +2281,49 @@ public class BassClientStateMachineTest {
        Mockito.clearInvocations(mBassClientService);
    }

    private boolean isConnectionIntentExpected(Class currentType, Class nextType) {
        if (currentType == nextType) {
            return false; // Same state, no intent expected
        }

        if ((currentType == BassClientStateMachine.ConnectedProcessing.class)
                || (nextType == BassClientStateMachine.ConnectedProcessing.class)) {
            return false; // ConnectedProcessing is an internal state that doesn't generate a
            // broadcast
        } else {
            return true; // All other state are generating broadcast
        }
    }

    @SafeVarargs
    private void verifyIntentSent(int timeout_ms, Matcher<Intent>... matchers) {
        verify(mBassClientService, timeout(timeout_ms).times(1))
                .sendBroadcast(
                        MockitoHamcrest.argThat(AllOf.allOf(matchers)),
                        eq(BLUETOOTH_CONNECT),
                        any());
    }

    private <T> void sendMessageAndVerifyTransition(Message msg, Class<T> type) {
        Mockito.clearInvocations(mBassClientService);

        mBassClientStateMachine.sendMessage(msg);
        // Verify that one connection state broadcast is executed
        verify(mBassClientService, timeout(TIMEOUT_MS)
                .times(1))
                .sendBroadcast(any(Intent.class), anyString(), any());
        TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper());
        Class currentStateClass = mBassClientStateMachine.getCurrentState().getClass();
        if (isConnectionIntentExpected(currentStateClass, type)) {
            verifyIntentSent(
                    NO_TIMEOUT_MS,
                    hasAction(BluetoothLeBroadcastAssistant.ACTION_CONNECTION_STATE_CHANGED),
                    hasExtra(
                            BluetoothProfile.EXTRA_STATE,
                            classTypeToConnectionState(currentStateClass)),
                    hasExtra(
                            BluetoothProfile.EXTRA_PREVIOUS_STATE,
                            classTypeToConnectionState(type)),
                    hasFlag(
                            Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
                                    | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND));
        }
        Assert.assertThat(mBassClientStateMachine.getCurrentState(), IsInstanceOf.instanceOf(type));
    }

+3 −0
Original line number Diff line number Diff line
@@ -188,6 +188,9 @@ uint16_t bta_hh_get_uuid16(tBTA_HH_DEV_CB* p_dev_cb, Uuid uuid) {
       uuid == ANDROID_HEADTRACKER_CONTROL_CHARAC_UUID ||
       uuid == ANDROID_HEADTRACKER_REPORT_CHARAC_UUID)) {
    return GATT_UUID_HID_REPORT;
  } else if (!uuid.Is16Bit()) {
    log::warn("UUID is not 16 bit");
    return 0;
  } else {
    return uuid.As16Bit();
  }
+25 −2
Original line number Diff line number Diff line
@@ -658,7 +658,7 @@ static bool bta_hh_le_write_ccc(tBTA_HH_DEV_CB* p_cb, uint16_t char_handle,

static bool bta_hh_le_write_rpt_clt_cfg(tBTA_HH_DEV_CB* p_cb);

static void write_rpt_ctl_cfg_cb(uint16_t conn_id, tGATT_STATUS status,
static void write_rpt_clt_cfg_cb(uint16_t conn_id, tGATT_STATUS status,
                                 uint16_t handle, uint16_t len,
                                 const uint8_t* value, void* data) {
  uint8_t srvc_inst_id;
@@ -666,6 +666,16 @@ static void write_rpt_ctl_cfg_cb(uint16_t conn_id, tGATT_STATUS status,
  tBTA_HH_DEV_CB* p_dev_cb = (tBTA_HH_DEV_CB*)data;
  const gatt::Characteristic* characteristic =
      BTA_GATTC_GetOwningCharacteristic(conn_id, handle);
  if (characteristic == nullptr) {
    log::error("Characteristic with handle {} not found clt cfg", handle);
    return;
  }
  if (!characteristic->uuid.Is16Bit()) {
    log::error("Unexpected len characteristic ID clt cfg: {}",
               characteristic->uuid.ToString());
    return;
  }

  uint16_t char_uuid = bta_hh_get_uuid16(p_dev_cb, characteristic->uuid);

  srvc_inst_id = BTA_GATTC_GetOwningService(conn_id, handle)->handle;
@@ -706,7 +716,7 @@ static bool bta_hh_le_write_rpt_clt_cfg(tBTA_HH_DEV_CB* p_cb) {
    if (p_rpt->rpt_type == BTA_HH_RPTT_INPUT) {
      if (bta_hh_le_write_ccc(p_cb, p_rpt->char_inst_id,
                              GATT_CLT_CONFIG_NOTIFICATION,
                              write_rpt_ctl_cfg_cb, p_cb)) {
                              write_rpt_clt_cfg_cb, p_cb)) {
        p_cb->clt_cfg_idx = i;
        return true;
      }
@@ -1646,6 +1656,11 @@ static void bta_hh_le_input_rpt_notify(tBTA_GATTC_NOTIFY* p_data) {
  const gatt::Service* p_svc =
      BTA_GATTC_GetOwningService(p_dev_cb->conn_id, p_char->value_handle);

  if (!p_char->uuid.Is16Bit()) {
    log::error("Unexpected characteristic len: {}", p_char->uuid.ToString());
    return;
  }

  p_rpt = bta_hh_le_find_report_entry(p_dev_cb, p_svc->handle,
                                      bta_hh_get_uuid16(p_dev_cb, p_char->uuid),
                                      p_char->value_handle);
@@ -1838,6 +1853,10 @@ static void read_report_cb(uint16_t conn_id, tGATT_STATUS status,
    log::error("Unknown handle");
    return;
  }
  if (!p_char->uuid.Is16Bit()) {
    log::error("Unexpected characteristic len: {}", p_char->uuid.ToString());
    return;
  }

  uint16_t char_uuid = bta_hh_get_uuid16(p_dev_cb, p_char->uuid);

@@ -1924,6 +1943,10 @@ static void write_report_cb(uint16_t conn_id, tGATT_STATUS status,
      BTA_GATTC_GetCharacteristic(conn_id, handle);

  if (p_char == nullptr) return;
  if (!p_char->uuid.Is16Bit()) {
    log::error("Unexpected characteristic len: {}", p_char->uuid.ToString());
    return;
  }

  uint16_t uuid16 = bta_hh_get_uuid16(p_dev_cb, p_char->uuid);
  if (uuid16 != GATT_UUID_HID_REPORT && uuid16 != GATT_UUID_HID_BT_KB_INPUT &&
Loading