blob: ec52113d5ae8dc16bf5cafbefe42aa9866949a4c [file] [log] [blame]
/*
* Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.bluetooth.btservice;
import static android.Manifest.permission.BLUETOOTH_CONNECT;
import static org.mockito.Mockito.*;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.HandlerThread;
import android.os.Message;
import android.os.ParcelUuid;
import android.os.UserHandle;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.bluetooth.TestUtils;
import com.android.bluetooth.Utils;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@MediumTest
@RunWith(AndroidJUnit4.class)
public class BondStateMachineTest {
private static final int TEST_BOND_REASON = 0;
private static final byte[] TEST_BT_ADDR_BYTES = {00, 11, 22, 33, 44, 55};
private static final byte[] TEST_BT_ADDR_BYTES_2 = {00, 11, 22, 33, 44, 66};
private static final ParcelUuid[] TEST_UUIDS =
{ParcelUuid.fromString("0000111E-0000-1000-8000-00805F9B34FB")};
private static final int BOND_NONE = BluetoothDevice.BOND_NONE;
private static final int BOND_BONDING = BluetoothDevice.BOND_BONDING;
private static final int BOND_BONDED = BluetoothDevice.BOND_BONDED;
private BluetoothManager mBluetoothManager;
private AdapterProperties mAdapterProperties;
private BluetoothDevice mDevice;
private Context mTargetContext;
private RemoteDevices mRemoteDevices;
private BondStateMachine mBondStateMachine;
private HandlerThread mHandlerThread;
private RemoteDevices.DeviceProperties mDeviceProperties;
private int mVerifyCount = 0;
@Mock private AdapterService mAdapterService;
@Before
public void setUp() throws Exception {
mTargetContext = InstrumentationRegistry.getTargetContext();
MockitoAnnotations.initMocks(this);
TestUtils.setAdapterService(mAdapterService);
mHandlerThread = new HandlerThread("BondStateMachineTestHandlerThread");
mHandlerThread.start();
mBluetoothManager = mTargetContext.getSystemService(BluetoothManager.class);
when(mAdapterService.getSystemService(Context.BLUETOOTH_SERVICE))
.thenReturn(mBluetoothManager);
when(mAdapterService.getSystemServiceName(BluetoothManager.class))
.thenReturn(Context.BLUETOOTH_SERVICE);
mRemoteDevices = new RemoteDevices(mAdapterService, mHandlerThread.getLooper());
mRemoteDevices.reset();
when(mAdapterService.getResources()).thenReturn(
mTargetContext.getResources());
mAdapterProperties = new AdapterProperties(mAdapterService);
mAdapterProperties.init(mRemoteDevices);
mBondStateMachine = BondStateMachine.make(mAdapterService, mAdapterProperties,
mRemoteDevices);
}
@After
public void tearDown() throws Exception {
mHandlerThread.quit();
TestUtils.clearAdapterService(mAdapterService);
}
@Test
public void testCreateBondAfterRemoveBond() {
// Set up two devices already bonded.
mRemoteDevices.reset();
RemoteDevices.DeviceProperties deviceProperties1, deviceProperties2;
deviceProperties1 = mRemoteDevices.addDeviceProperties(TEST_BT_ADDR_BYTES);
deviceProperties2 = mRemoteDevices.addDeviceProperties(TEST_BT_ADDR_BYTES_2);
BluetoothDevice device1, device2;
device1 = mRemoteDevices.getDevice(TEST_BT_ADDR_BYTES);
device2 = mRemoteDevices.getDevice(TEST_BT_ADDR_BYTES_2);
deviceProperties1.mBondState = BOND_BONDED;
deviceProperties2.mBondState = BOND_BONDED;
doReturn(true).when(mAdapterService).removeBondNative(any(byte[].class));
doReturn(true).when(mAdapterService).createBondNative(any(byte[].class),
eq(BluetoothDevice.ADDRESS_TYPE_PUBLIC), anyInt());
// The removeBond() request for a bonded device should invoke the removeBondNative() call.
Message removeBondMsg1 = mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND);
removeBondMsg1.obj = device1;
mBondStateMachine.sendMessage(removeBondMsg1);
TestUtils.waitForLooperToFinishScheduledTask(mBondStateMachine.getHandler().getLooper());
Message removeBondMsg2 = mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND);
removeBondMsg2.obj = device2;
mBondStateMachine.sendMessage(removeBondMsg2);
TestUtils.waitForLooperToFinishScheduledTask(mBondStateMachine.getHandler().getLooper());
verify(mAdapterService, times(1)).removeBondNative(eq(TEST_BT_ADDR_BYTES));
verify(mAdapterService, times(1)).removeBondNative(eq(TEST_BT_ADDR_BYTES_2));
mBondStateMachine.bondStateChangeCallback(AbstractionLayer.BT_STATUS_SUCCESS,
TEST_BT_ADDR_BYTES, BOND_NONE, 0);
TestUtils.waitForLooperToFinishScheduledTask(mBondStateMachine.getHandler().getLooper());
mBondStateMachine.bondStateChangeCallback(AbstractionLayer.BT_STATUS_SUCCESS,
TEST_BT_ADDR_BYTES_2, BOND_NONE, 0);
TestUtils.waitForLooperToFinishScheduledTask(mBondStateMachine.getHandler().getLooper());
// Try to pair these two devices again, createBondNative() should be invoked.
Message createBondMsg1 = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND);
createBondMsg1.obj = device1;
mBondStateMachine.sendMessage(createBondMsg1);
Message createBondMsg2 = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND);
createBondMsg2.obj = device2;
mBondStateMachine.sendMessage(createBondMsg2);
TestUtils.waitForLooperToFinishScheduledTask(mBondStateMachine.getHandler().getLooper());
verify(mAdapterService, times(1)).createBondNative(eq(TEST_BT_ADDR_BYTES),
eq(BluetoothDevice.ADDRESS_TYPE_PUBLIC), anyInt());
verify(mAdapterService, times(1)).createBondNative(eq(TEST_BT_ADDR_BYTES_2),
eq(BluetoothDevice.ADDRESS_TYPE_PUBLIC), anyInt());
}
@Test
public void testCreateBondWithLeDevice() {
mRemoteDevices.reset();
mBondStateMachine.mPendingBondedDevices.clear();
BluetoothDevice device1 = BluetoothAdapter.getDefaultAdapter().getRemoteLeDevice(
Utils.getAddressStringFromByte(TEST_BT_ADDR_BYTES),
BluetoothDevice.ADDRESS_TYPE_PUBLIC);
BluetoothDevice device2 = BluetoothAdapter.getDefaultAdapter().getRemoteLeDevice(
Utils.getAddressStringFromByte(TEST_BT_ADDR_BYTES_2),
BluetoothDevice.ADDRESS_TYPE_RANDOM);
// The createBond() request for two devices with different address types.
Message createBondMsg1 = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND);
createBondMsg1.obj = device1;
mBondStateMachine.sendMessage(createBondMsg1);
Message createBondMsg2 = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND);
createBondMsg2.obj = device2;
mBondStateMachine.sendMessage(createBondMsg2);
TestUtils.waitForLooperToFinishScheduledTask(mBondStateMachine.getHandler().getLooper());
verify(mAdapterService, times(1)).createBondNative(eq(TEST_BT_ADDR_BYTES),
eq(BluetoothDevice.ADDRESS_TYPE_PUBLIC), anyInt());
verify(mAdapterService, times(1)).createBondNative(eq(TEST_BT_ADDR_BYTES_2),
eq(BluetoothDevice.ADDRESS_TYPE_RANDOM), anyInt());
}
@Test
public void testUuidUpdateWithPendingDevice() {
mRemoteDevices.reset();
mBondStateMachine.mPendingBondedDevices.clear();
RemoteDevices.DeviceProperties pendingDeviceProperties =
mRemoteDevices.addDeviceProperties(TEST_BT_ADDR_BYTES_2);
BluetoothDevice pendingDevice = pendingDeviceProperties.getDevice();
Assert.assertNotNull(pendingDevice);
mBondStateMachine.sendIntent(pendingDevice, BOND_BONDED, TEST_BOND_REASON, false);
RemoteDevices.DeviceProperties testDeviceProperties =
mRemoteDevices.addDeviceProperties(TEST_BT_ADDR_BYTES);
testDeviceProperties.mUuids = TEST_UUIDS;
BluetoothDevice testDevice = testDeviceProperties.getDevice();
Assert.assertNotNull(testDevice);
Message bondingMsg = mBondStateMachine.obtainMessage(BondStateMachine.BONDING_STATE_CHANGE);
bondingMsg.obj = testDevice;
bondingMsg.arg1 = BOND_BONDING;
bondingMsg.arg2 = AbstractionLayer.BT_STATUS_RMT_DEV_DOWN;
mBondStateMachine.sendMessage(bondingMsg);
pendingDeviceProperties.mUuids = TEST_UUIDS;
Message uuidUpdateMsg = mBondStateMachine.obtainMessage(BondStateMachine.UUID_UPDATE);
uuidUpdateMsg.obj = pendingDevice;
mBondStateMachine.sendMessage(uuidUpdateMsg);
Message bondedMsg = mBondStateMachine.obtainMessage(BondStateMachine.BONDING_STATE_CHANGE);
bondedMsg.obj = testDevice;
bondedMsg.arg1 = BOND_BONDED;
bondedMsg.arg2 = AbstractionLayer.BT_STATUS_SUCCESS;
mBondStateMachine.sendMessage(bondedMsg);
TestUtils.waitForLooperToFinishScheduledTask(mBondStateMachine.getHandler().getLooper());
Assert.assertTrue(mBondStateMachine.mPendingBondedDevices.isEmpty());
}
@Test
public void testSendIntent() {
int badBondState = 42;
mVerifyCount = 0;
// Reset mRemoteDevices for the test.
mRemoteDevices.reset();
mDeviceProperties = mRemoteDevices.addDeviceProperties(TEST_BT_ADDR_BYTES);
mDevice = mDeviceProperties.getDevice();
Assert.assertNotNull(mDevice);
// Uuid not available, mPendingBondedDevice is empty.
testSendIntentNoPendingDevice(BOND_NONE, BOND_NONE, false, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDevice(BOND_NONE, BOND_BONDING, false, BOND_BONDING,
true, BOND_NONE, BOND_BONDING, false);
testSendIntentNoPendingDevice(BOND_NONE, BOND_BONDED, false, BOND_BONDED,
true, BOND_NONE, BOND_BONDING, true);
testSendIntentNoPendingDevice(BOND_NONE, badBondState, false, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDevice(BOND_BONDING, BOND_NONE, false, BOND_NONE,
true, BOND_BONDING, BOND_NONE, false);
testSendIntentNoPendingDevice(BOND_BONDING, BOND_BONDING, false, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDevice(BOND_BONDING, BOND_BONDED, false, BOND_BONDED,
false, BOND_NONE, BOND_NONE, true);
testSendIntentNoPendingDevice(BOND_BONDING, badBondState, false, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDevice(BOND_BONDED, BOND_NONE, false, BOND_NONE,
true, BOND_BONDED, BOND_NONE, false);
testSendIntentNoPendingDevice(BOND_BONDED, BOND_BONDING, false, BOND_BONDING,
true, BOND_BONDED, BOND_BONDING, false);
testSendIntentNoPendingDevice(BOND_BONDED, BOND_BONDED, false, BOND_BONDED,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDevice(BOND_BONDED, badBondState, false, BOND_BONDED,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDevice(BOND_NONE, BOND_NONE, true, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDevice(BOND_NONE, BOND_BONDING, true, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDevice(BOND_NONE, BOND_BONDED, true, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDevice(BOND_NONE, badBondState, true, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDevice(BOND_BONDING, BOND_NONE, true, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDevice(BOND_BONDING, BOND_BONDING, true, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDevice(BOND_BONDING, BOND_BONDED, true, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDevice(BOND_BONDING, badBondState, true, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDevice(BOND_BONDED, BOND_NONE, true, BOND_BONDED,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDevice(BOND_BONDED, BOND_BONDING, true, BOND_BONDED,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDevice(BOND_BONDED, BOND_BONDED, true, BOND_BONDED,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDevice(BOND_BONDED, badBondState, true, BOND_BONDED,
false, BOND_NONE, BOND_NONE, false);
// Uuid not available, mPendingBondedDevice contains a remote device.
testSendIntentPendingDevice(BOND_NONE, BOND_NONE, false, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDevice(BOND_NONE, BOND_BONDING, false, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDevice(BOND_NONE, BOND_BONDED, false, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDevice(BOND_NONE, badBondState, false, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDevice(BOND_BONDING, BOND_NONE, false, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDevice(BOND_BONDING, BOND_BONDING, false, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDevice(BOND_BONDING, BOND_BONDED, false, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDevice(BOND_BONDING, badBondState, false, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDevice(BOND_BONDED, BOND_NONE, false, BOND_NONE,
true, BOND_BONDING, BOND_NONE, false);
testSendIntentPendingDevice(BOND_BONDED, BOND_BONDING, false, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDevice(BOND_BONDED, BOND_BONDED, false, BOND_BONDED,
false, BOND_NONE, BOND_NONE, true);
testSendIntentPendingDevice(BOND_BONDED, badBondState, false, BOND_BONDED,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDevice(BOND_NONE, BOND_NONE, true, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDevice(BOND_NONE, BOND_BONDING, true, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDevice(BOND_NONE, BOND_BONDED, true, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDevice(BOND_NONE, badBondState, true, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDevice(BOND_BONDING, BOND_NONE, true, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDevice(BOND_BONDING, BOND_BONDING, true, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDevice(BOND_BONDING, BOND_BONDED, true, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDevice(BOND_BONDING, badBondState, true, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDevice(BOND_BONDED, BOND_NONE, true, BOND_BONDED,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDevice(BOND_BONDED, BOND_BONDING, true, BOND_BONDED,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDevice(BOND_BONDED, BOND_BONDED, true, BOND_BONDED,
true, BOND_BONDING, BOND_BONDED, false);
testSendIntentPendingDevice(BOND_BONDED, badBondState, true, BOND_BONDED,
false, BOND_NONE, BOND_NONE, false);
// Uuid available, mPendingBondedDevice is empty.
testSendIntentNoPendingDeviceWithUuid(BOND_NONE, BOND_NONE, false, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDeviceWithUuid(BOND_NONE, BOND_BONDING, false, BOND_BONDING,
true, BOND_NONE, BOND_BONDING, false);
testSendIntentNoPendingDeviceWithUuid(BOND_NONE, BOND_BONDED, false, BOND_BONDED,
true, BOND_NONE, BOND_BONDED, false);
testSendIntentNoPendingDeviceWithUuid(BOND_NONE, badBondState, false, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDeviceWithUuid(BOND_BONDING, BOND_NONE, false, BOND_NONE,
true, BOND_BONDING, BOND_NONE, false);
testSendIntentNoPendingDeviceWithUuid(BOND_BONDING, BOND_BONDING, false, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDeviceWithUuid(BOND_BONDING, BOND_BONDED, false, BOND_BONDED,
true, BOND_BONDING, BOND_BONDED, false);
testSendIntentNoPendingDeviceWithUuid(BOND_BONDING, badBondState, false, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDeviceWithUuid(BOND_BONDED, BOND_NONE, false, BOND_NONE,
true, BOND_BONDED, BOND_NONE, false);
testSendIntentNoPendingDeviceWithUuid(BOND_BONDED, BOND_BONDING, false, BOND_BONDING,
true, BOND_BONDED, BOND_BONDING, false);
testSendIntentNoPendingDeviceWithUuid(BOND_BONDED, BOND_BONDED, false, BOND_BONDED,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDeviceWithUuid(BOND_BONDED, badBondState, false, BOND_BONDED,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDeviceWithUuid(BOND_NONE, BOND_NONE, true, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDeviceWithUuid(BOND_NONE, BOND_BONDING, true, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDeviceWithUuid(BOND_NONE, BOND_BONDED, true, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDeviceWithUuid(BOND_NONE, badBondState, true, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDeviceWithUuid(BOND_BONDING, BOND_NONE, true, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDeviceWithUuid(BOND_BONDING, BOND_BONDING, true, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDeviceWithUuid(BOND_BONDING, BOND_BONDED, true, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDeviceWithUuid(BOND_BONDING, badBondState, true, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDeviceWithUuid(BOND_BONDED, BOND_NONE, true, BOND_BONDED,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDeviceWithUuid(BOND_BONDED, BOND_BONDING, true, BOND_BONDED,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDeviceWithUuid(BOND_BONDED, BOND_BONDED, true, BOND_BONDED,
false, BOND_NONE, BOND_NONE, false);
testSendIntentNoPendingDeviceWithUuid(BOND_BONDED, badBondState, true, BOND_BONDED,
false, BOND_NONE, BOND_NONE, false);
// Uuid available, mPendingBondedDevice contains a remote device.
testSendIntentPendingDeviceWithUuid(BOND_NONE, BOND_NONE, false, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDeviceWithUuid(BOND_NONE, BOND_BONDING, false, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDeviceWithUuid(BOND_NONE, BOND_BONDED, false, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDeviceWithUuid(BOND_NONE, badBondState, false, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDeviceWithUuid(BOND_BONDING, BOND_NONE, false, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDeviceWithUuid(BOND_BONDING, BOND_BONDING, false, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDeviceWithUuid(BOND_BONDING, BOND_BONDED, false, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDeviceWithUuid(BOND_BONDING, badBondState, false, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDeviceWithUuid(BOND_BONDED, BOND_NONE, false, BOND_NONE,
true, BOND_BONDING, BOND_NONE, false);
testSendIntentPendingDeviceWithUuid(BOND_BONDED, BOND_BONDING, false, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDeviceWithUuid(BOND_BONDED, BOND_BONDED, false, BOND_BONDED,
true, BOND_BONDING, BOND_BONDED, false);
testSendIntentPendingDeviceWithUuid(BOND_BONDED, badBondState, false, BOND_BONDED,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDeviceWithUuid(BOND_NONE, BOND_NONE, true, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDeviceWithUuid(BOND_NONE, BOND_BONDING, true, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDeviceWithUuid(BOND_NONE, BOND_BONDED, true, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDeviceWithUuid(BOND_NONE, badBondState, true, BOND_NONE,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDeviceWithUuid(BOND_BONDING, BOND_NONE, true, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDeviceWithUuid(BOND_BONDING, BOND_BONDING, true, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDeviceWithUuid(BOND_BONDING, BOND_BONDED, true, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDeviceWithUuid(BOND_BONDING, badBondState, true, BOND_BONDING,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDeviceWithUuid(BOND_BONDED, BOND_NONE, true, BOND_BONDED,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDeviceWithUuid(BOND_BONDED, BOND_BONDING, true, BOND_BONDED,
false, BOND_NONE, BOND_NONE, false);
testSendIntentPendingDeviceWithUuid(BOND_BONDED, BOND_BONDED, true, BOND_BONDED,
true, BOND_BONDING, BOND_BONDED, false);
testSendIntentPendingDeviceWithUuid(BOND_BONDED, badBondState, true, BOND_BONDED,
false, BOND_NONE, BOND_NONE, false);
}
private void testSendIntentCase(int oldState, int newState, boolean isTriggerFromDelayMessage,
int expectedNewState, boolean shouldBroadcast, int broadcastOldState,
int broadcastNewState, boolean shouldDelayMessageExist) {
ArgumentCaptor<Intent> intentArgument = ArgumentCaptor.forClass(Intent.class);
// Setup old state before start test.
mDeviceProperties.mBondState = oldState;
try {
mBondStateMachine.sendIntent(mDevice, newState, TEST_BOND_REASON,
isTriggerFromDelayMessage);
} catch (IllegalArgumentException e) {
// Do nothing.
}
Assert.assertEquals(expectedNewState, mDeviceProperties.getBondState());
// Check for bond state Intent status.
if (shouldBroadcast) {
verify(mAdapterService, times(++mVerifyCount)).sendBroadcastAsUser(
intentArgument.capture(), eq(UserHandle.ALL),
eq(BLUETOOTH_CONNECT), any(Bundle.class));
verifyBondStateChangeIntent(broadcastOldState, broadcastNewState,
intentArgument.getValue());
} else {
verify(mAdapterService, times(mVerifyCount)).sendBroadcastAsUser(any(Intent.class),
any(UserHandle.class), anyString(), any(Bundle.class));
}
if (shouldDelayMessageExist) {
Assert.assertTrue(mBondStateMachine.hasMessage(mBondStateMachine.BONDED_INTENT_DELAY));
mBondStateMachine.removeMessage(mBondStateMachine.BONDED_INTENT_DELAY);
} else {
Assert.assertFalse(mBondStateMachine.hasMessage(mBondStateMachine.BONDED_INTENT_DELAY));
}
}
private void testSendIntentNoPendingDeviceWithUuid(int oldState, int newState,
boolean isTriggerFromDelayMessage, int expectedNewState, boolean shouldBroadcast,
int broadcastOldState, int broadcastNewState, boolean shouldDelayMessageExist) {
// Add dummy UUID for the device.
mDeviceProperties.mUuids = TEST_UUIDS;
testSendIntentNoPendingDevice(oldState, newState, isTriggerFromDelayMessage,
expectedNewState, shouldBroadcast, broadcastOldState, broadcastNewState,
shouldDelayMessageExist);
}
private void testSendIntentPendingDeviceWithUuid(int oldState, int newState,
boolean isTriggerFromDelayMessage, int expectedNewState, boolean shouldBroadcast,
int broadcastOldState, int broadcastNewState, boolean shouldDelayMessageExist) {
// Add dummy UUID for the device.
mDeviceProperties.mUuids = TEST_UUIDS;
testSendIntentPendingDevice(oldState, newState, isTriggerFromDelayMessage, expectedNewState,
shouldBroadcast, broadcastOldState, broadcastNewState, shouldDelayMessageExist);
}
private void testSendIntentPendingDevice(int oldState, int newState,
boolean isTriggerFromDelayMessage, int expectedNewState, boolean shouldBroadcast,
int broadcastOldState, int broadcastNewState, boolean shouldDelayMessageExist) {
// Test for classic remote device.
mDeviceProperties.mDeviceType = BluetoothDevice.DEVICE_TYPE_CLASSIC;
mBondStateMachine.mPendingBondedDevices.clear();
mBondStateMachine.mPendingBondedDevices.add(mDevice);
testSendIntentCase(oldState, newState, isTriggerFromDelayMessage, expectedNewState,
shouldBroadcast, broadcastOldState, broadcastNewState, shouldDelayMessageExist);
// Test for dual-mode remote device.
mDeviceProperties.mDeviceType = BluetoothDevice.DEVICE_TYPE_DUAL;
mBondStateMachine.mPendingBondedDevices.clear();
mBondStateMachine.mPendingBondedDevices.add(mDevice);
testSendIntentCase(oldState, newState, isTriggerFromDelayMessage, expectedNewState,
shouldBroadcast, broadcastOldState, broadcastNewState, shouldDelayMessageExist);
// Test for low energy remote device.
mDeviceProperties.mDeviceType = BluetoothDevice.DEVICE_TYPE_LE;
mBondStateMachine.mPendingBondedDevices.clear();
mBondStateMachine.mPendingBondedDevices.add(mDevice);
testSendIntentCase(oldState, newState, isTriggerFromDelayMessage, expectedNewState,
shouldBroadcast, broadcastOldState, broadcastNewState, shouldDelayMessageExist);
}
private void testSendIntentNoPendingDevice(int oldState, int newState,
boolean isTriggerFromDelayMessage, int expectedNewState, boolean shouldBroadcast,
int broadcastOldState, int broadcastNewState, boolean shouldDelayMessageExist) {
// Test for classic remote device.
mDeviceProperties.mDeviceType = BluetoothDevice.DEVICE_TYPE_CLASSIC;
mBondStateMachine.mPendingBondedDevices.clear();
testSendIntentCase(oldState, newState, isTriggerFromDelayMessage, expectedNewState,
shouldBroadcast, broadcastOldState, broadcastNewState, shouldDelayMessageExist);
// Test for dual-mode remote device.
mDeviceProperties.mDeviceType = BluetoothDevice.DEVICE_TYPE_DUAL;
mBondStateMachine.mPendingBondedDevices.clear();
testSendIntentCase(oldState, newState, isTriggerFromDelayMessage, expectedNewState,
shouldBroadcast, broadcastOldState, broadcastNewState, shouldDelayMessageExist);
// Test for low energy remote device.
mDeviceProperties.mDeviceType = BluetoothDevice.DEVICE_TYPE_LE;
mBondStateMachine.mPendingBondedDevices.clear();
testSendIntentCase(oldState, newState, isTriggerFromDelayMessage, expectedNewState,
shouldBroadcast, broadcastOldState, broadcastNewState, shouldDelayMessageExist);
}
private void verifyBondStateChangeIntent(int oldState, int newState, Intent intent) {
Assert.assertNotNull(intent);
Assert.assertEquals(BluetoothDevice.ACTION_BOND_STATE_CHANGED, intent.getAction());
Assert.assertEquals(mDevice, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE));
Assert.assertEquals(newState, intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1));
Assert.assertEquals(oldState, intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE,
-1));
if (newState == BOND_NONE) {
Assert.assertEquals(TEST_BOND_REASON,
intent.getIntExtra(BluetoothDevice.EXTRA_UNBOND_REASON, -1));
} else {
Assert.assertEquals(-1, intent.getIntExtra(BluetoothDevice.EXTRA_UNBOND_REASON, -1));
}
}
}