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

Commit 4c31cbde authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes from topic "bt-test-fix-java-instrumentation-test"

* changes:
  Test: Fix broken tests in HeadsetClientStateMachineTest
  Test: Fix broken tests in RemoteDevicesTest
  Revert "port this change to aosp/ I3fb908c43f869e8816f6e46c6b271ef0bbd15be0"
parents 2aaf2a2c 895e60ab
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.ParcelUuid;
@@ -394,7 +395,7 @@ public class AdapterService extends Service {
    public void onCreate() {
        super.onCreate();
        debugLog("onCreate()");
        mRemoteDevices = new RemoteDevices(this);
        mRemoteDevices = new RemoteDevices(this, Looper.getMainLooper());
        mRemoteDevices.init();
        mBinder = new AdapterServiceBinder(this);
        mAdapterProperties = new AdapterProperties(this);
+27 −15
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelUuid;
import android.support.annotation.VisibleForTesting;
@@ -59,6 +60,30 @@ final class RemoteDevices {
    private final HashMap<String, DeviceProperties> mDevices;
    private Queue<String> mDeviceQueue;

    private final Handler mHandler;
    private class RemoteDevicesHandler extends Handler {

        /**
         * Handler must be created from an explicit looper to avoid threading ambiguity
         * @param looper The looper that this handler should be executed on
         */
        RemoteDevicesHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MESSAGE_UUID_INTENT:
                    BluetoothDevice device = (BluetoothDevice) msg.obj;
                    if (device != null) {
                        sendUuidIntent(device);
                    }
                    break;
            }
        }
    }

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
@@ -80,12 +105,13 @@ final class RemoteDevices {
        }
    };

    RemoteDevices(AdapterService service) {
    RemoteDevices(AdapterService service, Looper looper) {
        sAdapter = BluetoothAdapter.getDefaultAdapter();
        sAdapterService = service;
        sSdpTracker = new ArrayList<BluetoothDevice>();
        mDevices = new HashMap<String, DeviceProperties>();
        mDeviceQueue = new LinkedList<String>();
        mHandler = new RemoteDevicesHandler(looper);
    }

    /**
@@ -782,20 +808,6 @@ final class RemoteDevices {
        return batteryLevel * 100 / numberOfLevels;
    }

    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MESSAGE_UUID_INTENT:
                    BluetoothDevice device = (BluetoothDevice) msg.obj;
                    if (device != null) {
                        sendUuidIntent(device);
                    }
                    break;
            }
        }
    };

    private static void errorLog(String msg) {
        Log.e(TAG, msg);
    }
+27 −24
Original line number Diff line number Diff line
@@ -8,13 +8,17 @@ import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
import android.content.Intent;
import android.os.Looper;
import android.os.HandlerThread;
import android.os.Message;
import android.os.TestLooperManager;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;

import com.android.bluetooth.Utils;
import com.android.bluetooth.hfp.HeadsetHalConstants;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -34,26 +38,39 @@ public class RemoteDevicesTest {
    private ArgumentCaptor<String> mStringArgument = ArgumentCaptor.forClass(String.class);
    private BluetoothDevice mDevice1;
    private RemoteDevices mRemoteDevices;
    private HandlerThread mHandlerThread;
    private TestLooperManager mTestLooperManager;

    @Mock private AdapterService mAdapterService;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        if (Looper.myLooper() == null) {
            Looper.prepare();
        }
        mDevice1 = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(TEST_BT_ADDR_1);
        mRemoteDevices = new RemoteDevices(mAdapterService);
        mHandlerThread = new HandlerThread("RemoteDevicesTestHandlerThread");
        mHandlerThread.start();
        mTestLooperManager = InstrumentationRegistry.getInstrumentation()
                .acquireLooperManager(mHandlerThread.getLooper());
        mRemoteDevices = new RemoteDevices(mAdapterService, mHandlerThread.getLooper());
    }

    @After
    public void tearDown() {
        mTestLooperManager.release();
        mHandlerThread.quit();
    }

    @Test
    public void testSendUuidIntent() {
        MyAdapterSvc m = new MyAdapterSvc();
        RemoteDevices instance = new RemoteDevices(m);
        instance.updateUuids(mDevice1);
        Looper.loop();
        Assert.assertTrue(m.isRecvd());
        // Verify that a handler message is sent by the method call
        mRemoteDevices.updateUuids(mDevice1);
        Message msg = mTestLooperManager.next();
        Assert.assertNotNull(msg);

        // Verify that executing that message results in a broadcast intent
        mTestLooperManager.execute(msg);
        verify(mAdapterService).sendBroadcast(any(), anyString());
        verifyNoMoreInteractions(mAdapterService);
    }

    @Test
@@ -462,18 +479,4 @@ public class RemoteDevicesTest {
        list.add(0);
        return list.toArray();
    }

    public class MyAdapterSvc extends AdapterService {
        private boolean recvd = false;

        @Override
        public void sendBroadcast(Intent intent, String receiverPermission) {
            recvd = (intent.getAction() == BluetoothDevice.ACTION_UUID);
            if (recvd || Looper.myQueue().isIdle()) Looper.myLooper().quitSafely();
        }

        boolean isRecvd() {
            return recvd;
        }
    }
}
+73 −88
Original line number Diff line number Diff line
@@ -8,30 +8,57 @@ import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.support.test.InstrumentationRegistry;
import android.os.HandlerThread;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;

import com.android.bluetooth.btservice.AdapterService;

import org.hamcrest.core.IsInstanceOf;
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 HeadsetClientStateMachineTest {
    private BluetoothAdapter mAdapter = null;
    private Context mTargetContext;
    private BluetoothAdapter mAdapter;
    private HandlerThread mHandlerThread;
    private HeadsetClientStateMachine mHeadsetClientStateMachine;
    private BluetoothDevice mTestDevice;

    @Mock private HeadsetClientService mHeadsetClientService;
    @Mock private AudioManager mAudioManager;

    @Before
    public void setUp() throws Exception {
        mTargetContext = InstrumentationRegistry.getTargetContext();
        AdapterService inst = mock(AdapterService.class);
        Assert.assertTrue(inst != null);
    public void setUp() {
        // Setup mocks and test assets
        MockitoAnnotations.initMocks(this);
        // Set a valid volume
        when(mAudioManager.getStreamVolume(anyInt())).thenReturn(2);
        when(mAudioManager.getStreamMaxVolume(anyInt())).thenReturn(10);
        when(mAudioManager.getStreamMinVolume(anyInt())).thenReturn(1);
        when(mHeadsetClientService.getSystemService(Context.AUDIO_SERVICE)).thenReturn(
                mAudioManager);
        // This line must be called to make sure relevant objects are initialized properly
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        // Get a device for testing
        mTestDevice = mAdapter.getRemoteDevice("00:01:02:03:04:05");

        // Setup thread and looper
        mHandlerThread = new HandlerThread("HeadsetClientStateMachineTestHandlerThread");
        mHandlerThread.start();
        // Manage looper execution in main test thread explicitly to guarantee timing consistency
        mHeadsetClientStateMachine =
                new HeadsetClientStateMachine(mHeadsetClientService, mHandlerThread.getLooper());
    }

    @After
    public void tearDown() {
        mHandlerThread.quit();
    }

    /**
@@ -39,14 +66,7 @@ public class HeadsetClientStateMachineTest {
     */
    @Test
    public void testDefaultDisconnectedState() {
        HeadsetClientService mockService = mock(HeadsetClientService.class);
        AudioManager mockAudioManager = mock(AudioManager.class);

        when(mockService.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mockAudioManager);

        HeadsetClientStateMachine mockSM =
                new HeadsetClientStateMachine(mockService, mTargetContext.getMainLooper());
        Assert.assertEquals(mockSM.getConnectionState((BluetoothDevice) null),
        Assert.assertEquals(mHeadsetClientStateMachine.getConnectionState(null),
                BluetoothProfile.STATE_DISCONNECTED);
    }

@@ -55,33 +75,23 @@ public class HeadsetClientStateMachineTest {
     */
    @Test
    public void testIncomingPriorityReject() {
        HeadsetClientService mockService = mock(HeadsetClientService.class);
        AudioManager mockAudioManager = mock(AudioManager.class);
        BluetoothDevice device = mAdapter.getRemoteDevice("00:01:02:03:04:05");

        when(mockService.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mockAudioManager);

        HeadsetClientStateMachine mockSM =
                new HeadsetClientStateMachine(mockService, mTargetContext.getMainLooper());
        mockSM.start();
        mHeadsetClientStateMachine.start();

        // Return false for priority.
        when(mockService.getPriority(any(BluetoothDevice.class))).thenReturn(
        when(mHeadsetClientService.getPriority(any(BluetoothDevice.class))).thenReturn(
                BluetoothProfile.PRIORITY_OFF);

        // Inject an event for when incoming connection is requested
        StackEvent connStCh = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
        connStCh.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_CONNECTED;
        connStCh.valueInt2 = 0;
        connStCh.valueInt3 = 0;
        connStCh.device = device;
        mockSM.sendMessage(StackEvent.STACK_EVENT, connStCh);
        connStCh.device = mTestDevice;
        mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, connStCh);

        // Verify that no connection state broadcast is executed
        verify(mockService, never()).sendBroadcast(any(Intent.class), anyString());
        verify(mHeadsetClientService, never()).sendBroadcast(any(Intent.class), anyString());
        // Check we are in disconnected state still.
        Assert.assertTrue(
                mockSM.getCurrentState() instanceof HeadsetClientStateMachine.Disconnected);
        Assert.assertThat(mHeadsetClientStateMachine.getCurrentState(),
                IsInstanceOf.instanceOf(HeadsetClientStateMachine.Disconnected.class));
    }

    /**
@@ -89,58 +99,45 @@ public class HeadsetClientStateMachineTest {
     */
    @Test
    public void testIncomingPriorityAccept() {
        HeadsetClientService mockService = mock(HeadsetClientService.class);
        AudioManager mockAudioManager = mock(AudioManager.class);
        BluetoothDevice device = mAdapter.getRemoteDevice("00:01:02:03:04:05");

        when(mockService.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mockAudioManager);
        // Set a valid volume
        when(mockAudioManager.getStreamVolume(anyInt())).thenReturn(2);
        when(mockAudioManager.getStreamMaxVolume(anyInt())).thenReturn(10);
        when(mockAudioManager.getStreamMinVolume(anyInt())).thenReturn(1);
        mHeadsetClientStateMachine.start();


        HeadsetClientStateMachine mockSM =
                new HeadsetClientStateMachine(mockService, mTargetContext.getMainLooper());
        mockSM.start();

        // Return false for priority.
        when(mockService.getPriority(any(BluetoothDevice.class))).thenReturn(
        // Return true for priority.
        when(mHeadsetClientService.getPriority(any(BluetoothDevice.class))).thenReturn(
                BluetoothProfile.PRIORITY_ON);

        // Inject an event for when incoming connection is requested
        StackEvent connStCh = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
        connStCh.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_CONNECTED;
        connStCh.valueInt2 = 0;
        connStCh.valueInt3 = 0;
        connStCh.device = device;
        mockSM.sendMessage(StackEvent.STACK_EVENT, connStCh);
        connStCh.device = mTestDevice;
        mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, connStCh);

        // Verify that one connection state broadcast is executed
        ArgumentCaptor<Intent> intentArgument1 = ArgumentCaptor.forClass(Intent.class);
        verify(mockService, timeout(1000)).sendBroadcast(intentArgument1.capture(), anyString());
        verify(mHeadsetClientService, timeout(1000)).sendBroadcast(intentArgument1.capture(),
                anyString());
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTING,
                intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1));

        // Check we are in connecting state now.
        Assert.assertTrue(mockSM.getCurrentState() instanceof HeadsetClientStateMachine.Connecting);
        Assert.assertThat(mHeadsetClientStateMachine.getCurrentState(),
                IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connecting.class));

        // Send a message to trigger SLC connection
        StackEvent slcEvent = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
        slcEvent.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_SLC_CONNECTED;
        slcEvent.valueInt2 = HeadsetClientHalConstants.PEER_FEAT_ECS;
        slcEvent.valueInt3 = 0;
        slcEvent.device = device;
        mockSM.sendMessage(StackEvent.STACK_EVENT, slcEvent);
        slcEvent.device = mTestDevice;
        mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, slcEvent);

        // Verify that one connection state broadcast is executed
        ArgumentCaptor<Intent> intentArgument2 = ArgumentCaptor.forClass(Intent.class);
        verify(mockService, timeout(1000).times(2)).sendBroadcast(intentArgument2.capture(),
                anyString());
        verify(mHeadsetClientService, timeout(1000).times(2)).sendBroadcast(
                intentArgument2.capture(), anyString());
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTED,
                intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1));
        // Check we are in connecting state now.
        Assert.assertTrue(mockSM.getCurrentState() instanceof HeadsetClientStateMachine.Connected);
        Assert.assertThat(mHeadsetClientStateMachine.getCurrentState(),
                IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connected.class));
    }

    /**
@@ -148,51 +145,39 @@ public class HeadsetClientStateMachineTest {
     */
    @Test
    public void testIncomingTimeout() {
        HeadsetClientService mockService = mock(HeadsetClientService.class);
        AudioManager mockAudioManager = mock(AudioManager.class);
        BluetoothDevice device = mAdapter.getRemoteDevice("00:01:02:03:04:05");
        mHeadsetClientStateMachine.start();

        when(mockService.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mockAudioManager);
        // Set a valid volume
        when(mockAudioManager.getStreamVolume(anyInt())).thenReturn(2);
        when(mockAudioManager.getStreamMaxVolume(anyInt())).thenReturn(10);
        when(mockAudioManager.getStreamMinVolume(anyInt())).thenReturn(1);


        HeadsetClientStateMachine mockSM =
                new HeadsetClientStateMachine(mockService, mTargetContext.getMainLooper());
        mockSM.start();

        // Return false for priority.
        when(mockService.getPriority(any(BluetoothDevice.class))).thenReturn(
        // Return true for priority.
        when(mHeadsetClientService.getPriority(any(BluetoothDevice.class))).thenReturn(
                BluetoothProfile.PRIORITY_ON);

        // Inject an event for when incoming connection is requested
        StackEvent connStCh = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
        connStCh.valueInt = HeadsetClientHalConstants.CONNECTION_STATE_CONNECTED;
        connStCh.valueInt2 = 0;
        connStCh.valueInt3 = 0;
        connStCh.device = device;
        mockSM.sendMessage(StackEvent.STACK_EVENT, connStCh);
        connStCh.device = mTestDevice;
        mHeadsetClientStateMachine.sendMessage(StackEvent.STACK_EVENT, connStCh);

        // Verify that one connection state broadcast is executed
        ArgumentCaptor<Intent> intentArgument1 = ArgumentCaptor.forClass(Intent.class);
        verify(mockService, timeout(1000)).sendBroadcast(intentArgument1.capture(), anyString());
        verify(mHeadsetClientService, timeout(1000)).sendBroadcast(intentArgument1.capture(),
                anyString());
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTING,
                intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1));

        // Check we are in connecting state now.
        Assert.assertTrue(mockSM.getCurrentState() instanceof HeadsetClientStateMachine.Connecting);
        Assert.assertThat(mHeadsetClientStateMachine.getCurrentState(),
                IsInstanceOf.instanceOf(HeadsetClientStateMachine.Connecting.class));

        // Verify that one connection state broadcast is executed
        ArgumentCaptor<Intent> intentArgument2 = ArgumentCaptor.forClass(Intent.class);
        verify(mockService, timeout(HeadsetClientStateMachine.CONNECTING_TIMEOUT_MS * 2).times(
        verify(mHeadsetClientService,
                timeout(HeadsetClientStateMachine.CONNECTING_TIMEOUT_MS * 2).times(
                        2)).sendBroadcast(intentArgument2.capture(), anyString());
        Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTED,
                intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1));

        // Check we are in connecting state now.
        Assert.assertTrue(
                mockSM.getCurrentState() instanceof HeadsetClientStateMachine.Disconnected);
        Assert.assertThat(mHeadsetClientStateMachine.getCurrentState(),
                IsInstanceOf.instanceOf(HeadsetClientStateMachine.Disconnected.class));
    }
}