public void createAndroidVirtualDeviceAvailable( @Observes AndroidVirtualDeviceEvent event, AndroidBridge bridge, AndroidExtensionConfiguration configuration, AndroidSdk sdk, ProcessExecutor executor) throws AndroidExecutionException { if (!bridge.isConnected()) { throw new IllegalStateException( "Android debug bridge must be connected in order to spawn emulator"); } String name = configuration.getAvdName(); AndroidDevice running = null; for (AndroidDevice device : bridge.getDevices()) { if (equalsIgnoreNulls(name, device.getAvdName())) { running = device; break; } } if (running == null) { CountDownWatch countdown = new CountDownWatch(configuration.getEmulatorBootupTimeoutInSeconds(), TimeUnit.SECONDS); log.log( Level.INFO, "Waiting {0} seconds for emulator {1} to be started and connected.", new Object[] {countdown.timeout(), name}); // discover what device was added here DeviceConnectDiscovery deviceDiscovery = new DeviceConnectDiscovery(); AndroidDebugBridge.addDeviceChangeListener(deviceDiscovery); Process emulator = startEmulator(executor, sdk, name, configuration.getEmulatorOptions()); androidEmulator.set(new AndroidEmulator(emulator)); log.log( Level.FINE, "Emulator process started, {0} seconds remaining to start the device {1}", new Object[] {countdown.timeLeft(), name}); waitUntilBootUpIsComplete(deviceDiscovery, executor, sdk, countdown); running = deviceDiscovery.getDiscoveredDevice(); AndroidDebugBridge.removeDeviceChangeListener(deviceDiscovery); } else { log.info( "Emulator for device " + name + " is already started, device serial is " + running.getSerialNumber() + ". Emulator will not be reinitialized."); } // fire event that we have a device ready androidDevice.set(running); androidDeviceReady.fire(new AndroidDeviceReady(running)); }
private void waitUntilBootUpIsComplete( final DeviceConnectDiscovery deviceDiscovery, final ProcessExecutor executor, final AndroidSdk sdk, final CountDownWatch countdown) throws AndroidExecutionException { try { boolean isOnline = executor.scheduleUntilTrue( new Callable<Boolean>() { @Override public Boolean call() throws Exception { return deviceDiscovery.isOnline(); } }, countdown.timeLeft(), countdown.getTimeUnit().convert(1, TimeUnit.SECONDS), countdown.getTimeUnit()); if (isOnline == false) { throw new IllegalStateException( "No emulator device was brough online during " + countdown.timeout() + " seconds to Android Debug Bridge. Please increase the time limit in order to get emulator connected."); } // device is connected to ADB final AndroidDevice connectedDevice = deviceDiscovery.getDiscoveredDevice(); isOnline = executor.scheduleUntilTrue( new Callable<Boolean>() { @Override public Boolean call() throws Exception { // check properties of underlying process List<String> props = executor.execute( Collections.<String, String>emptyMap(), sdk.getAdbPath(), "-s", connectedDevice.getSerialNumber(), "shell", "getprop"); for (String line : props) { if (line.contains("[ro.runtime.firstboot]")) { // boot is completed return true; } } return false; } }, countdown.timeLeft(), countdown.getTimeUnit().convert(1, TimeUnit.SECONDS), countdown.getTimeUnit()); if (log.isLoggable(Level.INFO)) { log.log( Level.INFO, "Android emulator {0} was started within {1} seconds", new Object[] {connectedDevice.getAvdName(), countdown.timeElapsed()}); } if (isOnline == false) { throw new AndroidExecutionException( "Emulator device hasn't started properly in " + countdown.timeout() + " seconds. Please increase the time limit in order to get emulator booted."); } } catch (InterruptedException e) { throw new AndroidExecutionException(e, "Emulator device startup failed."); } catch (ExecutionException e) { throw new AndroidExecutionException(e, "Emulator device startup failed."); } }