/** * Starts the debug bridge. * * @return true if success. */ boolean start() { if (mAdbOsLocation != null && sAdbServerPort != 0 && (!mVersionCheck || !startAdb())) { return false; } mStarted = true; // now that the bridge is connected, we start the underlying services. mDeviceMonitor = new DeviceMonitor(this); mDeviceMonitor.start(); return true; }
/** * Returns the devices. * @see #hasInitialDeviceList() */ public IDevice[] getDevices() { synchronized (sLock) { if (mDeviceMonitor != null) { return mDeviceMonitor.getDevices(); } } return new IDevice[0]; }
/** * Returns whether the bridge has acquired the initial list from adb after being created. * <p>Calling {@link #getDevices()} right after {@link #createBridge(String, boolean)} will * generally result in an empty list. This is due to the internal asynchronous communication * mechanism with <code>adb</code> that does not guarantee that the {@link IDevice} list has been * built before the call to {@link #getDevices()}. * <p>The recommended way to get the list of {@link IDevice} objects is to create a * {@link IDeviceChangeListener} object. */ public boolean hasInitialDeviceList() { if (mDeviceMonitor != null) { return mDeviceMonitor.hasInitialDeviceList(); } return false; }
/** * Removes a {@link Client} from the list. * @param client the client to remove. * @param notify Whether or not to notify the listeners of a change. */ void removeClient(Client client, boolean notify) { mMonitor.addPortToAvailableList(client.getDebuggerListenPort()); synchronized (mClients) { mClients.remove(client); } if (notify) { mMonitor.getServer().deviceChanged(this, CHANGE_CLIENT_LIST); } }
String result = read(monitorSocket, buffer); openClient(device, newPid, getNextDebuggerPort(), monitorThread);
/** * Terminates the ddm library. This must be called upon application termination. */ public static synchronized void terminate() { // kill the monitoring services if (sThis != null && sThis.mDeviceMonitor != null) { sThis.mDeviceMonitor.stop(); sThis.mDeviceMonitor = null; } sBridgeListeners.clear(); sDeviceListeners.clear(); sInitialized = false; }
DeviceListComparisonResult result = DeviceListComparisonResult.compare(mDevices, newList); for (IDevice device : result.removed) { removeDevice((Device) device); AndroidDebugBridge.deviceDisconnected(device); if (!startMonitoringDevice(device)) { Log.e("DeviceMonitor", "Failed to start monitoring " + device.getSerialNumber()); queryAvdName(device);
if (startMonitoringDevice(device) == false) { Log.e("DeviceMonitor", "Failed to start monitoring " removeDevice(device); mServer.deviceDisconnected(device); } else { startMonitoringDevice(newDevice); queryNewDeviceForInfo(d);
// An Activity IS a Context so pass 'this' DeviceMonitor MyDevice = new DeviceMonitor(this);
/** * Reads the length of the next message from a socket. * @param socket The {@link SocketChannel} to read from. * @return the length, or 0 (zero) if no data is available from the socket. * @throws IOException if the connection failed. */ private int readLength(SocketChannel socket, byte[] buffer) throws IOException { String msg = read(socket, buffer); if (msg != null) { try { return Integer.parseInt(msg, 16); } catch (NumberFormatException nfe) { // we'll throw an exception below. } } // we receive something we can't read. It's better to reset the connection at this point. throw new IOException("Unable to read length"); }
/** * Check that the client is opened with the proper debugger port for the * specified application name, and if not, reopen it. * @param client * @param appName * @return */ protected static Client checkDebuggerPortForAppName(Client client, String appName) { IDebugPortProvider provider = DebugPortManager.getProvider(); if (provider != null) { Device device = client.getDeviceImpl(); int newPort = provider.getPort(device, appName); if (newPort != IDebugPortProvider.NO_STATIC_PORT && newPort != client.getDebuggerListenPort()) { AndroidDebugBridge bridge = AndroidDebugBridge.getBridge(); if (bridge != null) { DeviceMonitor deviceMonitor = bridge.getDeviceMonitor(); if (deviceMonitor != null) { deviceMonitor.addClientToDropAndReopen(client, newPort); client = null; } } } } return client; }
/** * Processes an incoming device message from the socket * @param socket * @param length * @throws IOException */ private void processIncomingDeviceData(int length) throws IOException { ArrayList<Device> list = new ArrayList<Device>(); if (length > 0) { byte[] buffer = new byte[length]; String result = read(mMainAdbConnection, buffer); String[] devices = result.split("\n"); //$NON-NLS-1$ for (String d : devices) { String[] param = d.split("\t"); //$NON-NLS-1$ if (param.length == 2) { // new adb uses only serial numbers to identify devices Device device = new Device(this, param[0] /*serialnumber*/, DeviceState.getState(param[1])); //add the device to the list list.add(device); } } } // now merge the new devices with the old ones. updateDevices(list); }
for (int n = mDevices.size() - 1; n >= 0; n--) { Device device = mDevices.get(0); removeDevice(device); mServer.deviceDisconnected(device);
/** * Opens and creates a new client. * @return */ private void openClient(Device device, int pid, int port, MonitorThread monitorThread) { SocketChannel clientSocket; try { clientSocket = AdbHelper.createPassThroughConnection( AndroidDebugBridge.getSocketAddress(), device, pid); // required for Selector clientSocket.configureBlocking(false); } catch (UnknownHostException uhe) { Log.d("DeviceMonitor", "Unknown Jdwp pid: " + pid); return; } catch (TimeoutException e) { Log.w("DeviceMonitor", "Failed to connect to client '" + pid + "': timeout"); return; } catch (AdbCommandRejectedException e) { Log.w("DeviceMonitor", "Adb rejected connection to client '" + pid + "': " + e.getMessage()); return; } catch (IOException ioe) { Log.w("DeviceMonitor", "Failed to connect to client '" + pid + "': " + ioe.getMessage()); return ; } createClient(device, pid, clientSocket, port, monitorThread); }
/** * Removes a {@link Client} from the list. * @param client the client to remove. * @param notify Whether or not to notify the listeners of a change. */ void removeClient(Client client, boolean notify) { mMonitor.addPortToAvailableList(client.getDebuggerListenPort()); synchronized (mClients) { mClients.remove(client); } if (notify) { AndroidDebugBridge.deviceChanged(this, CHANGE_CLIENT_LIST); } removeClientInfo(client); }
String result = read(monitorSocket, buffer); openClient(device, newPid, getNextDebuggerPort(), monitorThread); changed = true;
/** * Kills the debug bridge, and the adb host server. * @return true if success */ boolean stop() { // if we haven't started we return false; if (mStarted == false) { return false; } // kill the monitoring services mDeviceMonitor.stop(); mDeviceMonitor = null; if (stopAdb() == false) { return false; } mStarted = false; return true; }
/** * Reads the length of the next message from a socket. * @param socket The {@link SocketChannel} to read from. * @return the length, or 0 (zero) if no data is available from the socket. * @throws IOException if the connection failed. */ private static int readLength(@NonNull SocketChannel socket, @NonNull byte[] buffer) throws IOException { String msg = read(socket, buffer); if (msg != null) { try { return Integer.parseInt(msg, 16); } catch (NumberFormatException nfe) { // we'll throw an exception below. } } // we receive something we can't read. It's better to reset the connection at this point. throw new IOException("Unable to read length"); }
DeviceMonitor deviceMonitor = bridge.getDeviceMonitor(); if (deviceMonitor != null) { deviceMonitor.addClientToDropAndReopen(client, newPort); client = null;
/** * Updates the device list with the new items received from the monitoring service. */ private void updateDevices(@NonNull List<Device> newList) { DeviceListComparisonResult result = DeviceListComparisonResult.compare(mDevices, newList); for (Device device : result.removed) { removeDevice(device); AndroidDebugBridge.deviceDisconnected(device); } List<Device> newlyOnline = new ArrayList<>(mDevices.size()); for (Map.Entry<Device, DeviceState> entry : result.updated.entrySet()) { Device device = entry.getKey(); device.setState(entry.getValue()); if (device.isOnline()) { newlyOnline.add(device); } } for (Device device : result.added) { mDevices.add(device); AndroidDebugBridge.deviceConnected(device); if (device.isOnline()) { newlyOnline.add(device); } } for (Device device : newlyOnline) { // Initiate a property fetch so that future requests can be served out of this cache. // This is necessary for backwards compatibility device.getSystemProperty(Device.PROP_BUILD_API_LEVEL); } }