Package org.jboss.arquillian.android.impl

Source Code of org.jboss.arquillian.android.impl.AndroidDeviceSelector

/*
* 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.jboss.arquillian.android.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.jboss.arquillian.android.api.AndroidBridge;
import org.jboss.arquillian.android.api.AndroidDevice;
import org.jboss.arquillian.android.api.AndroidExecutionException;
import org.jboss.arquillian.android.configuration.AndroidConfigurationException;
import org.jboss.arquillian.android.configuration.AndroidExtensionConfiguration;
import org.jboss.arquillian.android.configuration.AndroidSdk;
import org.jboss.arquillian.android.spi.event.AndroidBridgeInitialized;
import org.jboss.arquillian.android.spi.event.AndroidDeviceReady;
import org.jboss.arquillian.android.spi.event.AndroidVirtualDeviceAvailable;
import org.jboss.arquillian.android.spi.event.AndroidVirtualDeviceCreated;
import org.jboss.arquillian.core.api.Event;
import org.jboss.arquillian.core.api.InstanceProducer;
import org.jboss.arquillian.core.api.annotation.Inject;
import org.jboss.arquillian.core.api.annotation.Observes;
import org.jboss.arquillian.test.spi.annotation.SuiteScoped;

/**
* Select either a real device or virtual device for execution. If a real device is specified via its serial number, it will
* check if it is connected, otherwise it will use an virtual device.
*
* Observes:
* <ul>
* <li>{@link AndroidBridgeInitialized}</li>
* </ul>
*
* Creates:
* <ul>
* <li>{@link AndroidDevice}</li>
* </ul>
*
* Fires:
* <ul>
* <li>{@link AndroidVirtualDeviceCreated}</li>
* <li>{@link AndroidVirtualDeviceAvailable}</li>
* <li>{@link AndroidDeviceReady}</li>
* </ul>
*
* @author <a href="kpiwko@redhat.com">Karel Piwko</a>
*
*/
public class AndroidDeviceSelector {
    private static Logger log = Logger.getLogger(AndroidDeviceSelector.class.getName());

    @Inject
    @SuiteScoped
    private InstanceProducer<AndroidDevice> androidDevice;

    @Inject
    private Event<AndroidVirtualDeviceCreated> avdCreated;

    @Inject
    private Event<AndroidVirtualDeviceAvailable> avdAvailable;

    @Inject
    private Event<AndroidDeviceReady> androidDeviceReady;

    @SuppressWarnings("serial")
    public void getOrCreateAndroidDevice(@Observes AndroidBridgeInitialized event, ProcessExecutor executor,
            AndroidExtensionConfiguration configuration, AndroidSdk sdk) throws AndroidConfigurationException,
            AndroidExecutionException {

        String avdName = configuration.getAvdName();
        String serialId = configuration.getSerialId();
        AndroidBridge bridge = event.getBridge();

        // get priority for device specified by serialId if such device is connected
        AndroidDevice device = checkIfRealDeviceIsConnected(bridge, serialId);
        if (device != null) {
            androidDevice.set(device);
            androidDeviceReady.fire(new AndroidDeviceReady(device));
            return;
        }

        Set<String> devices = getAvdDeviceNames(executor, sdk);

        // check out avd availability
        if (!devices.contains(avdName) || configuration.isForce()) {
            if (log.isLoggable(Level.FINE)) {
                log.fine("Creating an Android virtual device named " + avdName);
            }

            Validate.notNullOrEmpty(configuration.getSdSize(), "Memory SD card size must be defined");

            try {
                List<String> args = new ArrayList<String>(Arrays.asList(sdk.getAndroidPath(), "create", "avd", "-n", avdName, "-t", "android-" + configuration.getApiLevel(), "-f",
                        "-p", avdName, "-c", configuration.getSdSize()));
                if (configuration.getAbi() != null) {
                    args.add("--abi");
                    args.add(configuration.getAbi());
                }
                String[] argsArrays = new String[args.size()];
                executor.execute(new HashMap<String, String>() {
                    {
                        put("Do you wish to create a custom hardware profile [no]", "no\n");
                    }
                }, args.toArray(argsArrays));
            } catch (InterruptedException e) {
                throw new AndroidExecutionException("Unable to create a new AVD Device", e);
            } catch (ExecutionException e) {
                throw new AndroidExecutionException("Unable to create a new AVD Device", e);
            }

            log.info("Android virtual device " + avdName + " was created");
            avdCreated.fire(new AndroidVirtualDeviceCreated(avdName));
        } else {
            // device exists, will not be created
            log.info("Android virtual device " + avdName + " already exists, will be reused in tests");
            avdAvailable.fire(new AndroidVirtualDeviceAvailable(avdName));

        }

    }

    private AndroidDevice checkIfRealDeviceIsConnected(AndroidBridge bridge, String serialId) {
        // no serialId was specified
        if (serialId == null || serialId.trim().isEmpty()) {
            return null;
        }

        for (AndroidDevice device : bridge.getDevices()) {
            if (serialId.equals(device.getSerialNumber())) {
                return device;
            }
        }

        log.warning("SerialId " + serialId
                + " was specified, however no such device was connected. Trying to connect to an emulator instead.");

        return null;

    }

    private Set<String> getAvdDeviceNames(ProcessExecutor executor, AndroidSdk sdk) throws AndroidExecutionException {

        final Pattern deviceName = Pattern.compile("[\\s]*Name: ([^\\s]+)[\\s]*");

        Set<String> names = new HashSet<String>();

        List<String> output;
        try {
            output = executor.execute(sdk.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);
                if (log.isLoggable(Level.FINE)) {
                    log.fine("Available Android Device: " + name);
                }
            }
        }

        return names;
    }
}
TOP

Related Classes of org.jboss.arquillian.android.impl.AndroidDeviceSelector

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.