Loading android/app/tests/unit/src/com/android/bluetooth/TestUtils.java +64 −0 Original line number Original line Diff line number Diff line Loading @@ -21,6 +21,8 @@ import static org.mockito.Mockito.*; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice; import android.content.Intent; import android.content.Intent; import android.os.Handler; import android.os.Looper; import android.support.test.InstrumentationRegistry; import android.support.test.InstrumentationRegistry; import android.support.test.rule.ServiceTestRule; import android.support.test.rule.ServiceTestRule; Loading Loading @@ -170,4 +172,66 @@ public class TestUtils { Assert.assertNotNull(testDevice); Assert.assertNotNull(testDevice); return testDevice; return testDevice; } } /** * Run synchronously a runnable action on a looper. * The method will return after the action has been execution to completion. * * Example: * <pre> * {@code * TestUtils.runOnMainSync(new Runnable() { * public void run() { * Assert.assertTrue(mA2dpService.stop()); * } * }); * } * </pre> * * @param looper the looper used to run the action * @param action the action to run */ public static void runOnLooperSync(Looper looper, Runnable action) { if (Looper.myLooper() == looper) { // requested thread is the same as the current thread. call directly. action.run(); } else { Handler handler = new Handler(looper); SyncRunnable sr = new SyncRunnable(action); handler.post(sr); sr.waitForComplete(); } } /** * Helper class used to run synchronously a runnable action on a looper. */ private static final class SyncRunnable implements Runnable { private final Runnable mTarget; private volatile boolean mComplete = false; SyncRunnable(Runnable target) { mTarget = target; } @Override public void run() { mTarget.run(); synchronized (this) { mComplete = true; notifyAll(); } } public void waitForComplete() { synchronized (this) { while (!mComplete) { try { wait(); } catch (InterruptedException e) { } } } } } } } android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceTest.java +67 −1 Original line number Original line Diff line number Diff line Loading @@ -50,6 +50,7 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations; import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit; Loading Loading @@ -255,13 +256,39 @@ public class A2dpServiceTest { } } /** /** * Test getting A2DP Service: getA2dpService(); * Test getting A2DP Service: getA2dpService() */ */ @Test @Test public void testGetA2dpService() { public void testGetA2dpService() { Assert.assertEquals(mA2dpService, A2dpService.getA2dpService()); Assert.assertEquals(mA2dpService, A2dpService.getA2dpService()); } } /** * Test stop A2DP Service */ @Test public void testStopA2dpService() { // Prepare: connect and set active device doReturn(true).when(mA2dpNativeInterface).setActiveDevice(any(BluetoothDevice.class)); connectDevice(mTestDevice); Assert.assertTrue(mA2dpService.setActiveDevice(mTestDevice)); verify(mA2dpNativeInterface).setActiveDevice(mTestDevice); // A2DP Service is already running: test stop(). Note: must be done on the main thread. InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { public void run() { Assert.assertTrue(mA2dpService.stop()); } }); // Verify that setActiveDevice(null) was called during shutdown verify(mA2dpNativeInterface).setActiveDevice(null); // Try to restart the service. Note: must be done on the main thread. InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { public void run() { Assert.assertTrue(mA2dpService.start()); } }); } /** /** * Test get/set priority for BluetoothDevice * Test get/set priority for BluetoothDevice */ */ Loading Loading @@ -704,6 +731,45 @@ public class A2dpServiceTest { Assert.assertFalse(mA2dpService.getDevices().contains(mTestDevice)); Assert.assertFalse(mA2dpService.getDevices().contains(mTestDevice)); } } private void connectDevice(BluetoothDevice device) { A2dpStackEvent connCompletedEvent; List<BluetoothDevice> prevConnectedDevices = mA2dpService.getConnectedDevices(); // Update the device priority so okToConnect() returns true mA2dpService.setPriority(device, BluetoothProfile.PRIORITY_ON); doReturn(true).when(mA2dpNativeInterface).connectA2dp(device); doReturn(true).when(mA2dpNativeInterface).disconnectA2dp(device); // Send a connect request Assert.assertTrue("Connect failed", mA2dpService.connect(device)); // Verify the connection state broadcast, and that we are in Connecting state verifyConnectionStateIntent(TIMEOUT_MS, device, BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED); Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, mA2dpService.getConnectionState(device)); // Send a message to trigger connection completed connCompletedEvent = new A2dpStackEvent(A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); connCompletedEvent.device = device; connCompletedEvent.valueInt = A2dpStackEvent.CONNECTION_STATE_CONNECTED; mA2dpService.messageFromNative(connCompletedEvent); // Verify the connection state broadcast, and that we are in Connected state verifyConnectionStateIntent(TIMEOUT_MS, device, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING); Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mA2dpService.getConnectionState(device)); // Verify that the device is in the list of connected devices Assert.assertTrue(mA2dpService.getConnectedDevices().contains(device)); // Verify the list of previously connected devices for (BluetoothDevice prevDevice : prevConnectedDevices) { Assert.assertTrue(mA2dpService.getConnectedDevices().contains(prevDevice)); } } private void generateConnectionMessageFromNative(BluetoothDevice device, int newConnectionState, private void generateConnectionMessageFromNative(BluetoothDevice device, int newConnectionState, int oldConnectionState) { int oldConnectionState) { A2dpStackEvent stackEvent = A2dpStackEvent stackEvent = Loading Loading
android/app/tests/unit/src/com/android/bluetooth/TestUtils.java +64 −0 Original line number Original line Diff line number Diff line Loading @@ -21,6 +21,8 @@ import static org.mockito.Mockito.*; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice; import android.content.Intent; import android.content.Intent; import android.os.Handler; import android.os.Looper; import android.support.test.InstrumentationRegistry; import android.support.test.InstrumentationRegistry; import android.support.test.rule.ServiceTestRule; import android.support.test.rule.ServiceTestRule; Loading Loading @@ -170,4 +172,66 @@ public class TestUtils { Assert.assertNotNull(testDevice); Assert.assertNotNull(testDevice); return testDevice; return testDevice; } } /** * Run synchronously a runnable action on a looper. * The method will return after the action has been execution to completion. * * Example: * <pre> * {@code * TestUtils.runOnMainSync(new Runnable() { * public void run() { * Assert.assertTrue(mA2dpService.stop()); * } * }); * } * </pre> * * @param looper the looper used to run the action * @param action the action to run */ public static void runOnLooperSync(Looper looper, Runnable action) { if (Looper.myLooper() == looper) { // requested thread is the same as the current thread. call directly. action.run(); } else { Handler handler = new Handler(looper); SyncRunnable sr = new SyncRunnable(action); handler.post(sr); sr.waitForComplete(); } } /** * Helper class used to run synchronously a runnable action on a looper. */ private static final class SyncRunnable implements Runnable { private final Runnable mTarget; private volatile boolean mComplete = false; SyncRunnable(Runnable target) { mTarget = target; } @Override public void run() { mTarget.run(); synchronized (this) { mComplete = true; notifyAll(); } } public void waitForComplete() { synchronized (this) { while (!mComplete) { try { wait(); } catch (InterruptedException e) { } } } } } } }
android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceTest.java +67 −1 Original line number Original line Diff line number Diff line Loading @@ -50,6 +50,7 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations; import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit; Loading Loading @@ -255,13 +256,39 @@ public class A2dpServiceTest { } } /** /** * Test getting A2DP Service: getA2dpService(); * Test getting A2DP Service: getA2dpService() */ */ @Test @Test public void testGetA2dpService() { public void testGetA2dpService() { Assert.assertEquals(mA2dpService, A2dpService.getA2dpService()); Assert.assertEquals(mA2dpService, A2dpService.getA2dpService()); } } /** * Test stop A2DP Service */ @Test public void testStopA2dpService() { // Prepare: connect and set active device doReturn(true).when(mA2dpNativeInterface).setActiveDevice(any(BluetoothDevice.class)); connectDevice(mTestDevice); Assert.assertTrue(mA2dpService.setActiveDevice(mTestDevice)); verify(mA2dpNativeInterface).setActiveDevice(mTestDevice); // A2DP Service is already running: test stop(). Note: must be done on the main thread. InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { public void run() { Assert.assertTrue(mA2dpService.stop()); } }); // Verify that setActiveDevice(null) was called during shutdown verify(mA2dpNativeInterface).setActiveDevice(null); // Try to restart the service. Note: must be done on the main thread. InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { public void run() { Assert.assertTrue(mA2dpService.start()); } }); } /** /** * Test get/set priority for BluetoothDevice * Test get/set priority for BluetoothDevice */ */ Loading Loading @@ -704,6 +731,45 @@ public class A2dpServiceTest { Assert.assertFalse(mA2dpService.getDevices().contains(mTestDevice)); Assert.assertFalse(mA2dpService.getDevices().contains(mTestDevice)); } } private void connectDevice(BluetoothDevice device) { A2dpStackEvent connCompletedEvent; List<BluetoothDevice> prevConnectedDevices = mA2dpService.getConnectedDevices(); // Update the device priority so okToConnect() returns true mA2dpService.setPriority(device, BluetoothProfile.PRIORITY_ON); doReturn(true).when(mA2dpNativeInterface).connectA2dp(device); doReturn(true).when(mA2dpNativeInterface).disconnectA2dp(device); // Send a connect request Assert.assertTrue("Connect failed", mA2dpService.connect(device)); // Verify the connection state broadcast, and that we are in Connecting state verifyConnectionStateIntent(TIMEOUT_MS, device, BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED); Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, mA2dpService.getConnectionState(device)); // Send a message to trigger connection completed connCompletedEvent = new A2dpStackEvent(A2dpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); connCompletedEvent.device = device; connCompletedEvent.valueInt = A2dpStackEvent.CONNECTION_STATE_CONNECTED; mA2dpService.messageFromNative(connCompletedEvent); // Verify the connection state broadcast, and that we are in Connected state verifyConnectionStateIntent(TIMEOUT_MS, device, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING); Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mA2dpService.getConnectionState(device)); // Verify that the device is in the list of connected devices Assert.assertTrue(mA2dpService.getConnectedDevices().contains(device)); // Verify the list of previously connected devices for (BluetoothDevice prevDevice : prevConnectedDevices) { Assert.assertTrue(mA2dpService.getConnectedDevices().contains(prevDevice)); } } private void generateConnectionMessageFromNative(BluetoothDevice device, int newConnectionState, private void generateConnectionMessageFromNative(BluetoothDevice device, int newConnectionState, int oldConnectionState) { int oldConnectionState) { A2dpStackEvent stackEvent = A2dpStackEvent stackEvent = Loading