All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.arquillian.droidium.container.impl.AndroidDeviceSelectorImpl Maven / Gradle / Ivy

The newest version!
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2012, Red Hat Middleware LLC, and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * 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 org.arquillian.droidium.container.impl;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.arquillian.droidium.container.api.AndroidBridge;
import org.arquillian.droidium.container.api.AndroidDevice;
import org.arquillian.droidium.container.api.AndroidDeviceSelector;
import org.arquillian.droidium.container.api.AndroidExecutionException;
import org.arquillian.droidium.container.api.IdentifierGenerator;
import org.arquillian.droidium.container.api.Screenshooter;
import org.arquillian.droidium.container.configuration.AndroidContainerConfiguration;
import org.arquillian.droidium.container.configuration.AndroidSDK;
import org.arquillian.droidium.container.configuration.Validate;
import org.arquillian.droidium.container.spi.event.AndroidBridgeInitialized;
import org.arquillian.droidium.container.spi.event.AndroidDeviceReady;
import org.arquillian.droidium.container.spi.event.AndroidVirtualDeviceAvailable;
import org.arquillian.droidium.container.spi.event.AndroidVirtualDeviceCreate;
import org.arquillian.droidium.container.utils.IdentifierType;
import org.jboss.arquillian.container.spi.context.annotation.ContainerScoped;
import org.jboss.arquillian.core.api.Event;
import org.jboss.arquillian.core.api.Instance;
import org.jboss.arquillian.core.api.InstanceProducer;
import org.jboss.arquillian.core.api.annotation.Inject;
import org.jboss.arquillian.core.api.annotation.Observes;

/**
 * Selects real physical Android device if serial id was specified in the configuration. If serial number was not specified one
 * of the following holds:
 *
 * 
*
* 1. If console port was specified but avd name was not, we try to connect to running emulator which listens to specified port. * If we fails to connect, {@link AndroidExecutionException} is thrown.
* 2. If avd name was specified but console port was not, we try to connect to the first running emulator of such avd name.
* 3. If both avd name and console port were specified, we try to connect to this combination.
* 4. We can fail to get device in all above steps: *
    *
  1. If AVD name was not specified, random AVD indentifier is generated.
  2. *
  3. Checking whether such AVD is already existing is performed, if it does not, such AVD name is created and marked as * generated one. This AVD will be deleted after the whole test suite.
  4. *
* * Observes: *
    *
  • {@link AndroidBridgeInitialized}
  • *
* * Creates: *
    *
  • {@link AndroidDevice}
  • *
  • {@link Screenshooter}
  • *
* * Fires: *
    *
  • {@link AndroidVirtualDeviceCreate} - when we are going to create new Android virtual device
  • *
  • {@link AndroidVirtualDeviceAvailable} - when there is already avd of name we want in the system
  • *
  • {@link AndroidDeviceReady} - when we get intance of running Android device
  • *
* * @author Karel Piwko * @author Stefan Miklosovic * */ public class AndroidDeviceSelectorImpl implements AndroidDeviceSelector { private static Logger logger = Logger.getLogger(AndroidDeviceSelectorImpl.class.getSimpleName()); @Inject @ContainerScoped private InstanceProducer androidDevice; @Inject @ContainerScoped private InstanceProducer screenshooter; @Inject private Instance androidBridge; @Inject private Instance configuration; @Inject private Instance androidSDK; @Inject private Instance executor; @Inject private Instance idGenerator; @Inject private Event androidVirtualDeviceAvailable; @Inject private Event androidVirtualDeviceCreate; @Inject private Event androidDeviceReady; public void selectDevice(@Observes AndroidBridgeInitialized event) throws AndroidExecutionException { AndroidDevice device = null; if (isConnectingToPhysicalDevice()) { device = getPhysicalDevice(); if (device != null) { setDronePorts(device); androidDevice.set(device); screenshooter.set(new AndroidScreenshooter(device)); androidDeviceReady.fire(new AndroidDeviceReady(device)); return; } } if (isConnectingToVirtualDevice()) { device = getVirtualDevice(); if (device != null) { setDronePorts(device); androidDevice.set(device); screenshooter.set(new AndroidScreenshooter(device)); androidDeviceReady.fire(new AndroidDeviceReady(device)); return; } } if (configuration.get().getAvdName() == null) { String generatedAvdName = idGenerator.get().getIdentifier(IdentifierType.AVD.getClass()); configuration.get().setAvdName(generatedAvdName); configuration.get().setAvdGenerated(true); } if (!androidVirtualDeviceExists(configuration.get().getAvdName())) { androidVirtualDeviceCreate.fire(new AndroidVirtualDeviceCreate()); } else { androidVirtualDeviceAvailable.fire(new AndroidVirtualDeviceAvailable(configuration.get().getAvdName())); } } private void setDronePorts(AndroidDevice device) { device.setDroneHostPort(configuration.get().getDroneHostPort()); device.setDroneGuestPort(configuration.get().getDroneGuestPort()); } private boolean isConnectingToVirtualDevice() { return isConsolePortDefined() || isAvdNameDefined(); } private boolean isConnectingToPhysicalDevice() { String serialId = configuration.get().getSerialId(); return serialId != null && !serialId.trim().isEmpty(); } private boolean isConsolePortDefined() { String consolePort = configuration.get().getConsolePort(); return consolePort != null && !consolePort.trim().equals(""); } private boolean isAvdNameDefined() { String avdName = configuration.get().getAvdName(); return avdName != null && !avdName.trim().equals(""); } private boolean isOnlyConsolePortAvailable() { return isConsolePortDefined() && !isAvdNameDefined(); } private boolean isOnlyAvdNameAvailable() { return isAvdNameDefined() && !isConsolePortDefined(); } private AndroidDevice getVirtualDevice() throws AndroidExecutionException { String consolePort = configuration.get().getConsolePort(); String avdName = configuration.get().getAvdName(); if (isOnlyConsolePortAvailable()) { try { return getVirtualDeviceByConsolePort(consolePort); } catch (AndroidExecutionException ex) { return null; } } if (isOnlyAvdNameAvailable()) { try { return getVirtualDeviceByAvdName(avdName); } catch (AndroidExecutionException ex) { return null; } } try { return getVirtualDevice(consolePort, avdName); } catch (AndroidExecutionException ex) { return null; } } private AndroidDevice getVirtualDevice(String consolePort, String avdName) throws AndroidExecutionException { Validate.notNullOrEmpty(consolePort, "Console port to get emulator of is a null object or an empty string."); Validate.notNullOrEmpty(avdName, "AVD name to get emulator of is a null object or an empty string."); List devices = androidBridge.get().getEmulators(); if (devices == null || devices.size() == 0) { throw new AndroidExecutionException("There are no emulators on the Android bridge."); } for (AndroidDevice device : devices) { try { if (device.getConsolePort().equals(consolePort) && device.getAvdName().equals(avdName)) { return device; } } catch (NullPointerException ex) { logger.severe("Unable to connect to the emulator. Please be sure you are running adb server."); } } return null; } private AndroidDevice getVirtualDeviceByConsolePort(String consolePort) throws AndroidExecutionException { Validate.notNullOrEmpty(consolePort, "Console port to get emulator of is a null object or an empty string."); List devices = androidBridge.get().getEmulators(); if (devices == null || devices.size() == 0) { throw new AndroidExecutionException("There are no emulators on the Android bridge."); } for (AndroidDevice device : devices) { String deviceConsolePort = device.getConsolePort(); if (deviceConsolePort != null && deviceConsolePort.equals(consolePort)) { return device; } } throw new AndroidExecutionException("Unable to get Android emulator running on the console port " + consolePort); } private AndroidDevice getVirtualDeviceByAvdName(String avdName) throws AndroidExecutionException { Validate.notNullOrEmpty(avdName, "AVD name to get emulator of is a null object or an empty string"); List devices = androidBridge.get().getEmulators(); if (devices == null || devices.size() == 0) { throw new AndroidExecutionException("There are no emulators on the Android bridge."); } for (AndroidDevice device : devices) { String deviceAvdName = device.getAvdName(); if (deviceAvdName != null && deviceAvdName.equals(avdName)) { return device; } } throw new AndroidExecutionException("No running emulator of AVD name " + avdName + "."); } private AndroidDevice getPhysicalDevice() throws AndroidExecutionException { String serialId = configuration.get().getSerialId(); List devices = androidBridge.get().getDevices(); if (devices == null || devices.size() == 0) { throw new AndroidExecutionException("There are no devices on the Android bridge."); } for (AndroidDevice device : devices) { if (!device.isEmulator() && serialId.equals(device.getSerialNumber())) { logger.info("Detected physical device with serial ID " + serialId + "."); return device; } } throw new AndroidExecutionException("Unable to get device with serial ID " + serialId + "."); } private boolean androidVirtualDeviceExists(String avdName) throws AndroidExecutionException { ProcessExecutor executor = this.executor.get(); Set devices = getAndroidVirtualDeviceNames(executor); return devices.contains(avdName); } private Set getAndroidVirtualDeviceNames(ProcessExecutor executor) throws AndroidExecutionException { final Pattern deviceName = Pattern.compile("[\\s]*Name: ([^\\s]+)[\\s]*"); Set names = new HashSet(); List output; try { output = executor.execute(androidSDK.get().getAndroidPath(), "list", "avd"); } catch (InterruptedException e) { throw new AndroidExecutionException("Unable to get list of available AVDs", e); } catch (ExecutionException e) { throw new AndroidExecutionException("Unable to get list of available AVDs", e); } for (String line : output) { Matcher m; if (line.trim().startsWith("Name: ") && (m = deviceName.matcher(line)).matches()) { String name = m.group(1); // skip a device which has no name if (name == null || name.trim().length() == 0) { continue; } names.add(name); logger.info("Available Android Device: " + name); } } return names; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy