Merge "Ensure we release device in recovery properly"
diff --git a/src/com/android/tradefed/device/DeviceManager.java b/src/com/android/tradefed/device/DeviceManager.java
index 75e8103..7e08c4f 100644
--- a/src/com/android/tradefed/device/DeviceManager.java
+++ b/src/com/android/tradefed/device/DeviceManager.java
@@ -108,7 +108,7 @@
*
* <p>serial2 offline
*/
- private static final String DEVICE_LIST_PATTERN = ".*\n(%s)\\s+(device|offline).*";
+ private static final String DEVICE_LIST_PATTERN = ".*\n(%s)\\s+(device|offline|recovery).*";
private Semaphore mConcurrentFlashLock = null;
diff --git a/tests/src/com/android/tradefed/device/DeviceManagerTest.java b/tests/src/com/android/tradefed/device/DeviceManagerTest.java
index 47b0358..3d1d564 100644
--- a/tests/src/com/android/tradefed/device/DeviceManagerTest.java
+++ b/tests/src/com/android/tradefed/device/DeviceManagerTest.java
@@ -1048,6 +1048,67 @@
assertEquals(1, manager.getDeviceList().size());
}
+ /** Ensure that an unavailable device in recovery mode is released properly. */
+ @Test
+ public void testFreeDevice_recovery() {
+ EasyMock.expect(mMockIDevice.isEmulator()).andStubReturn(Boolean.FALSE);
+ EasyMock.expect(mMockIDevice.getState()).andReturn(DeviceState.ONLINE);
+ EasyMock.expect(mMockStateMonitor.waitForDeviceShell(EasyMock.anyLong()))
+ .andReturn(Boolean.TRUE);
+ mMockStateMonitor.setState(TestDeviceState.NOT_AVAILABLE);
+
+ CommandResult stubAdbDevices = new CommandResult(CommandStatus.SUCCESS);
+ stubAdbDevices.setStdout("List of devices attached\nserial\trecovery\n");
+ EasyMock.expect(
+ mMockRunUtil.runTimedCmd(
+ EasyMock.anyLong(), EasyMock.eq("adb"), EasyMock.eq("devices")))
+ .andReturn(stubAdbDevices);
+
+ replayMocks();
+ IManagedTestDevice testDevice = new TestDevice(mMockIDevice, mMockStateMonitor, null);
+ DeviceManager manager = createDeviceManagerNoInit();
+ manager.init(
+ null,
+ null,
+ new ManagedTestDeviceFactory(false, null, null) {
+ @Override
+ public IManagedTestDevice createDevice(IDevice idevice) {
+ mMockTestDevice.setIDevice(idevice);
+ return testDevice;
+ }
+
+ @Override
+ protected CollectingOutputReceiver createOutputReceiver() {
+ return new CollectingOutputReceiver() {
+ @Override
+ public String getOutput() {
+ return "/system/bin/pm";
+ }
+ };
+ }
+
+ @Override
+ public void setFastbootEnabled(boolean enable) {
+ // ignore
+ }
+ });
+
+ mDeviceListener.deviceConnected(mMockIDevice);
+
+ IManagedTestDevice device = (IManagedTestDevice) manager.allocateDevice(mDeviceSelections);
+ assertNotNull(device);
+ // Device becomes unavailable
+ device.setDeviceState(TestDeviceState.NOT_AVAILABLE);
+ // A freed 'unavailable' device becomes UNAVAILABLE state
+ manager.freeDevice(device, FreeDeviceState.UNAVAILABLE);
+ // Ensure device cannot be allocated again
+ ITestDevice device2 = manager.allocateDevice(mDeviceSelections);
+ assertNull(device2);
+ verifyMocks();
+ // We still have the device in the list because device is not lost.
+ assertEquals(1, manager.getDeviceList().size());
+ }
+
/**
* Test that when freeing an Unavailable device that is not in 'adb devices' we correctly remove
* it from our tracking list.