com.notifier.desktop.transport.usb.impl.UsbPortForwarder.java Source code

Java tutorial

Introduction

Here is the source code for com.notifier.desktop.transport.usb.impl.UsbPortForwarder.java

Source

/*
 * Android Notifier Desktop is a multiplatform remote notification client for Android devices.
 *
 * Copyright (C) 2010  Leandro Aparecido
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation version 3 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.notifier.desktop.transport.usb.impl;

import java.io.*;
import java.util.*;

import org.slf4j.*;

import com.google.common.base.*;
import com.google.common.collect.*;
import com.google.inject.*;

public class UsbPortForwarder implements Runnable {

    private static final Logger logger = LoggerFactory.getLogger(UsbPortForwarder.class);

    private static final int LOCAL_PORT = 10602;
    private static final String ANDROID_SOCKET_NAME = "androidnotifier";

    private Provider<UsbPortClient> portClientProvider;

    private Adb adb;
    private int localPortCounter;
    private Map<Adb.Device, UsbPortClient> devicesAndListeners;

    public UsbPortForwarder(File androidSdkHome, Provider<UsbPortClient> portClientProvider) {
        this.adb = new Adb();
        this.adb.setSdkHome(androidSdkHome);
        this.portClientProvider = portClientProvider;
        this.localPortCounter = LOCAL_PORT;
        this.devicesAndListeners = Maps.newConcurrentMap();
    }

    @Override
    public void run() {
        logger.trace("Listing adb devices");
        Collection<Adb.Device> actualDevices = Collections.emptyList();
        try {
            List<Adb.Device> devices = adb.devices();
            purgeDisconnectedDevices(devices);
            actualDevices = Collections2.filter(devices, new Adb.Device.TypePredicate(Adb.Device.Type.DEVICE));
            actualDevices = Collections2.filter(actualDevices, new Predicate<Adb.Device>() {
                public boolean apply(Adb.Device input) {
                    return !devicesAndListeners.keySet().contains(input);
                }
            });
        } catch (IOException e) {
            logger.error("Error running adb", e);
        } catch (InterruptedException e) {
            return;
        } catch (Exception e) {
            logger.error("Error running adb", e);
        }
        if (!actualDevices.isEmpty()) {
            logger.debug("Found [{}] new device(s)", actualDevices.size());

            for (Adb.Device device : actualDevices) {
                try {
                    forwardAndListen(device);
                } catch (InterruptedException e) {
                    return;
                } catch (Exception e) {
                    logger.error("Error forwarding port for device [" + device.getSerialNumber() + "]", e);
                }
            }
        }
    }

    public void stop() {
        for (UsbPortClient client : devicesAndListeners.values()) {
            client.stop();
        }
    }

    protected void forwardAndListen(Adb.Device device) throws InterruptedException, IOException {
        if (!devicesAndListeners.containsKey(device)) {
            int port = localPortCounter++;
            logger.debug("Forwarding port [{}] for device [{}]", port, device);
            adb.forward(device, port, ANDROID_SOCKET_NAME);
            logger.debug("Forwarded successfully, starting client");
            UsbPortClient client = portClientProvider.get();
            client.setDevice(device);
            client.setPort(port);
            devicesAndListeners.put(device, client);
            client.start();
        }
    }

    protected void purgeDisconnectedDevices(List<Adb.Device> devices) {
        for (Iterator<Map.Entry<Adb.Device, UsbPortClient>> iterator = devicesAndListeners.entrySet()
                .iterator(); iterator.hasNext();) {
            Map.Entry<Adb.Device, UsbPortClient> entry = iterator.next();
            if (!devices.contains(entry.getKey())) {
                logger.debug("Device [{}] has been disconnected from usb", entry.getKey());
                entry.getValue().stop();
                iterator.remove();
            }
        }
    }

    public void setSdkHome(File sdkHome) {
        adb.setSdkHome(sdkHome);
    }

    public ImmutableMap<Adb.Device, UsbPortClient> getDevicesAndListeners() {
        return ImmutableMap.copyOf(devicesAndListeners);
    }

}