/// <summary> /// Create and connect a new pass-through socket, from the host to a port on /// the device. /// </summary> /// <param name="adbSockAddr"> </param> /// <param name="device"> the device to connect to. Can be null in which case the connection will be /// to the first available device. </param> /// <param name="devicePort"> the port we're opening </param> /// <exception cref="TimeoutException"> in case of timeout on the connection. </exception> /// <exception cref="IOException"> in case of I/O error on the connection. </exception> /// <exception cref="AdbCommandRejectedException"> if adb rejects the command </exception> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: public static java.nio.channels.SocketChannel open(java.net.InetSocketAddress adbSockAddr, Device device, int devicePort) throws java.io.IOException, TimeoutException, AdbCommandRejectedException public static SocketChannel open(EndPoint adbSockAddr, Device device, int devicePort) { SocketChannel adbChan = SocketChannel.open(adbSockAddr); try { adbChan.socket().NoDelay = true; adbChan.configureBlocking(false); // if the device is not -1, then we first tell adb we're looking to // talk to a specific device setDevice(adbChan, device); var req = createAdbForwardRequest(null, devicePort); // Log.hexDump(req); write(adbChan, req); AdbResponse resp = readAdbResponse(adbChan, false); if (resp.okay == false) { throw new AdbCommandRejectedException(resp.message); } adbChan.configureBlocking(true); } catch (TimeoutException e) { adbChan.close(); throw e; } catch (IOException e) { adbChan.close(); throw e; } return adbChan; }
/// <summary> /// Reboot the device. /// </summary> /// <param name="into"> what to reboot into (recovery, bootloader). Or null to just reboot. </param> /// <exception cref="TimeoutException"> in case of timeout on the connection. </exception> /// <exception cref="AdbCommandRejectedException"> if adb rejects the command </exception> /// <exception cref="IOException"> in case of I/O error on the connection. </exception> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: public static void reboot(String into, java.net.InetSocketAddress adbSockAddr, Device device) throws TimeoutException, AdbCommandRejectedException, java.io.IOException public static void reboot(string into, EndPoint adbSockAddr, Device device) { byte[] request; if (into == null) { request = formAdbRequest("reboot:"); //$NON-NLS-1$ } else { request = formAdbRequest("reboot:" + into); //$NON-NLS-1$ } SocketChannel adbChan = null; try { adbChan = SocketChannel.open(adbSockAddr); adbChan.configureBlocking(false); // if the device is not -1, then we first tell adb we're looking to talk // to a specific device setDevice(adbChan, device); write(adbChan, request); } finally { if (adbChan != null) { adbChan.close(); } } }
/// <summary> /// Remove a port forwarding between a local and a remote port. </summary> /// <param name="adbSockAddr"> the socket address to connect to adb </param> /// <param name="device"> the device on which to remove the port fowarding </param> /// <param name="localPort"> the local port of the forward </param> /// <param name="remotePort"> the remote port. </param> /// <exception cref="TimeoutException"> in case of timeout on the connection. </exception> /// <exception cref="AdbCommandRejectedException"> if adb rejects the command </exception> /// <exception cref="IOException"> in case of I/O error on the connection. </exception> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: public static void removeForward(java.net.InetSocketAddress adbSockAddr, Device device, int localPort, int remotePort) throws TimeoutException, AdbCommandRejectedException, java.io.IOException public static void removeForward(EndPoint adbSockAddr, Device device, int localPort, int remotePort) { SocketChannel adbChan = null; try { adbChan = SocketChannel.open(adbSockAddr); adbChan.configureBlocking(false); var request = formAdbRequest(string.Format("host-serial:{0}:killforward:tcp:{1:D};tcp:{2:D}", device.serialNumber, localPort, remotePort)); //$NON-NLS-1$ write(adbChan, request); AdbResponse resp = readAdbResponse(adbChan, false); // readDiagString if (resp.okay == false) { Log.w("remove-forward", "Error creating forward: " + resp.message); throw new AdbCommandRejectedException(resp.message); } } finally { if (adbChan != null) { adbChan.close(); } } }
/// <summary> /// Runs the Event log service on the <seealso cref="Device"/>, and provides its output to the /// <seealso cref="LogReceiver"/>. /// <p/>This call is blocking until <seealso cref="LogReceiver#isCancelled()"/> returns true. </summary> /// <param name="adbSockAddr"> the socket address to connect to adb </param> /// <param name="device"> the Device on which to run the service </param> /// <param name="rcvr"> the <seealso cref="LogReceiver"/> to receive the log output </param> /// <exception cref="TimeoutException"> in case of timeout on the connection. </exception> /// <exception cref="AdbCommandRejectedException"> if adb rejects the command </exception> /// <exception cref="IOException"> in case of I/O error on the connection. </exception> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: public static void runEventLogService(java.net.InetSocketAddress adbSockAddr, Device device, com.android.ddmlib.log.LogReceiver rcvr) throws TimeoutException, AdbCommandRejectedException, java.io.IOException public static void runEventLogService(EndPoint adbSockAddr, Device device, LogReceiver rcvr) { runLogService(adbSockAddr, device, "events", rcvr); //$NON-NLS-1$ }
/// <summary> /// Runs a log service on the <seealso cref="Device"/>, and provides its output to the <seealso cref="LogReceiver"/>. /// <p/>This call is blocking until <seealso cref="LogReceiver#isCancelled()"/> returns true. </summary> /// <param name="adbSockAddr"> the socket address to connect to adb </param> /// <param name="device"> the Device on which to run the service </param> /// <param name="logName"> the name of the log file to output </param> /// <param name="rcvr"> the <seealso cref="LogReceiver"/> to receive the log output </param> /// <exception cref="TimeoutException"> in case of timeout on the connection. </exception> /// <exception cref="AdbCommandRejectedException"> if adb rejects the command </exception> /// <exception cref="IOException"> in case of I/O error on the connection. </exception> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: public static void runLogService(java.net.InetSocketAddress adbSockAddr, Device device, String logName, com.android.ddmlib.log.LogReceiver rcvr) throws TimeoutException, AdbCommandRejectedException, java.io.IOException public static void runLogService(EndPoint adbSockAddr, Device device, string logName, LogReceiver rcvr) { SocketChannel adbChan = null; try { adbChan = SocketChannel.open(adbSockAddr); adbChan.configureBlocking(false); // if the device is not -1, then we first tell adb we're looking to talk // to a specific device setDevice(adbChan, device); var request = formAdbRequest("log:" + logName); write(adbChan, request); AdbResponse resp = readAdbResponse(adbChan, false); // readDiagString if (resp.okay == false) { throw new AdbCommandRejectedException(resp.message); } var data = new byte[16384]; ByteBuffer buf = ByteBuffer.wrap(data); while (true) { int count; if (rcvr != null && rcvr.cancelled) { break; } count = adbChan.read(buf); if (count < 0) { break; } else if (count == 0) { Thread.Sleep(WAIT_TIME*5); } else { if (rcvr != null) { rcvr.parseNewData(buf.array(), buf.arrayOffset(), buf.position); } buf.rewind(); } } } finally { if (adbChan != null) { adbChan.close(); } } }
private void removeDevice(Device device) { device.clearClientList(); mDevices.Remove(device); SocketChannel channel = device.clientMonitoringSocket; if (channel != null) { try { channel.close(); } catch (IOException) { // doesn't really matter if the close fails. } } }
/// <summary> /// Retrieve the frame buffer from the device. </summary> /// <exception cref="TimeoutException"> in case of timeout on the connection. </exception> /// <exception cref="AdbCommandRejectedException"> if adb rejects the command </exception> /// <exception cref="IOException"> in case of I/O error on the connection. </exception> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: static RawImage getFrameBuffer(java.net.InetSocketAddress adbSockAddr, Device device) throws TimeoutException, AdbCommandRejectedException, java.io.IOException internal static RawImage getFrameBuffer(EndPoint adbSockAddr, Device device) { RawImage imageParams = new RawImage(); var request = formAdbRequest("framebuffer:"); //$NON-NLS-1$ byte[] nudge = {0}; byte[] reply; SocketChannel adbChan = null; try { adbChan = SocketChannel.open(adbSockAddr); adbChan.configureBlocking(false); // if the device is not -1, then we first tell adb we're looking to talk // to a specific device setDevice(adbChan, device); write(adbChan, request); AdbResponse resp = readAdbResponse(adbChan, false); // readDiagString if (resp.okay == false) { throw new AdbCommandRejectedException(resp.message); } // first the protocol version. reply = new byte[4]; read(adbChan, reply); ByteBuffer buf = ByteBuffer.wrap(reply); buf.order = ByteOrder.LITTLE_ENDIAN; int version = buf.getInt(); // get the header size (this is a count of int) int headerSize = RawImage.getHeaderSize(version); // read the header reply = new byte[headerSize * 4]; read(adbChan, reply); buf = ByteBuffer.wrap(reply); buf.order = ByteOrder.LITTLE_ENDIAN; // fill the RawImage with the header if (imageParams.readHeader(version, buf) == false) { Log.e("Screenshot", "Unsupported protocol: " + version); return null; } Log.d("ddms", "image params: bpp=" + imageParams.bpp + ", size=" + imageParams.size + ", width=" + imageParams.width + ", height=" + imageParams.height); write(adbChan, nudge); reply = new byte[imageParams.size]; read(adbChan, reply); imageParams.data = reply; } finally { if (adbChan != null) { adbChan.close(); } } return imageParams; }
/// <summary> /// Opens and creates a new client. /// @return /// </summary> private void openClient(Device device, int pid, int port, MonitorThread monitorThread) { SocketChannel clientSocket; try { clientSocket = AdbHelper.createPassThroughConnection(AndroidDebugBridge.socketAddress, device, pid); // required for Selector clientSocket.configureBlocking(false); } catch (ArgumentException) { Log.d("DeviceMonitor", "Unknown Jdwp pid: " + pid); return; } catch (TimeoutException) { Log.w("DeviceMonitor", "Failed to connect to client '" + pid + "': timeout"); return; } catch (AdbCommandRejectedException e) { Log.w("DeviceMonitor", "Adb rejected connection to client '" + pid + "': " + e.Message); return; } catch (Exception ioe) { Log.w("DeviceMonitor", "Failed to connect to client '" + pid + "': " + ioe.Message); return; } createClient(device, pid, clientSocket, port, monitorThread); }
/// <summary> /// Creates a client and register it to the monitor thread </summary> /// <param name="device"> </param> /// <param name="pid"> </param> /// <param name="socket"> </param> /// <param name="debuggerPort"> the debugger port. </param> /// <param name="monitorThread"> the <seealso cref="MonitorThread"/> object. </param> private void createClient(Device device, int pid, SocketChannel socket, int debuggerPort, MonitorThread monitorThread) { /* * Successfully connected to something. Create a Client object, add * it to the list, and initiate the JDWP handshake. */ Client client = new Client(device, socket, pid); if (client.sendHandshake()) { try { if (AndroidDebugBridge.clientSupport) { client.listenForDebugger(debuggerPort); } } catch (IOException) { client.clientData.debuggerConnectionStatus = ClientData.DebuggerStatus.ERROR; Log.e("ddms", "Can't bind to local " + debuggerPort + " for debugger"); // oh well } client.requestAllocationStatus(); } else { Log.e("ddms", "Handshake with " + client + " failed!"); /* * The handshake send failed. We could remove it now, but if the * failure is "permanent" we'll just keep banging on it and * getting the same result. Keep it in the list with its "error" * state so we don't try to reopen it. */ } if (client.valid) { device.addClient(client); monitorThread.addClient(client); } else { client = null; } }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: private boolean sendDeviceMonitoringRequest(java.nio.channels.SocketChannel socket, Device device) throws TimeoutException, AdbCommandRejectedException, java.io.IOException private bool sendDeviceMonitoringRequest(SocketChannel socket, Device device) { try { AdbHelper.setDevice(socket, device); var request = AdbHelper.formAdbRequest("track-jdwp"); //$NON-NLS-1$ AdbHelper.write(socket, request); AdbHelper.AdbResponse resp = AdbHelper.readAdbResponse(socket, false); // readDiagString if (resp.okay == false) { // request was refused by adb! Log.e("DeviceMonitor", "adb refused request: " + resp.message); } return resp.okay; } catch (TimeoutException e) { Log.e("DeviceMonitor", "Sending jdwp tracking request timed out!"); throw e; } catch (IOException e) { Log.e("DeviceMonitor", "Sending jdwp tracking request failed!"); throw e; } }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: private void processIncomingJdwpData(Device device, java.nio.channels.SocketChannel monitorSocket, int length) throws java.io.IOException private void processIncomingJdwpData(Device device, SocketChannel monitorSocket, int length) { if (length >= 0) { // array for the current pids. List<int?> pidList = new List<int?>(); // get the string data if there are any if (length > 0) { var buffer = new byte[length]; string result = read(monitorSocket, buffer); // split each line in its own list and create an array of integer pid string[] pids = StringHelperClass.StringSplit(result, "\n", true); //$NON-NLS-1$ foreach (string pid in pids) { try { pidList.Add(Convert.ToInt32(pid)); } catch (SystemException) { // looks like this pid is not really a number. Lets ignore it. continue; } } } MonitorThread monitorThread = MonitorThread.instance; // Now we merge the current list with the old one. // this is the same mechanism as the merging of the device list. // For each client in the current list, we look for a matching the pid in the new list. // * if we find it, we do nothing, except removing the pid from its list, // to mark it as "processed" // * if we do not find any match, we remove the client from the current list. // Once this is done, the new list contains pids for which we don't have clients yet, // so we create clients for them, add them to the list, and start monitoring them. IList<Client> clients = device.clientList; bool changed = false; // because MonitorThread#dropClient acquires first the monitorThread lock and then the // Device client list lock (when removing the Client from the list), we have to make // sure we acquire the locks in the same order, since another thread (MonitorThread), // could call dropClient itself. lock (monitorThread) { lock (clients) { for (int c = 0; c < clients.Count; ) { Client client = clients[c]; int pid = client.clientData.pid; // look for a matching pid int? match = null; foreach (int? matchingPid in pidList) { if (pid == (int)matchingPid) { match = matchingPid; break; } } if (match != null) { pidList.Remove(match); c++; // move on to the next client. } else { // we need to drop the client. the client will remove itself from the // list of its device which is 'clients', so there's no need to // increment c. // We ask the monitor thread to not send notification, as we'll do // it once at the end. monitorThread.dropClient(client, false); // notify changed = true; } } } } // at this point whatever pid is left in the list needs to be converted into Clients. foreach (int newPid in pidList) { openClient(device, newPid, nextDebuggerPort, monitorThread); changed = true; } if (changed) { mServer.deviceChanged(device, DeviceConstants.CHANGE_CLIENT_LIST); } } }
/// <summary> /// Starts a monitoring service for a device. </summary> /// <param name="device"> the device to monitor. </param> /// <returns> true if success. </returns> private bool startMonitoringDevice(Device device) { SocketChannel socketChannel = openAdbConnection(); if (socketChannel != null) { try { bool result = sendDeviceMonitoringRequest(socketChannel, device); if (result) { if (mSelector == null) { startDeviceMonitorThread(); } device.clientMonitoringSocket = socketChannel; lock (mDevices) { // always wakeup before doing the register. The synchronized block // ensure that the selector won't select() before the end of this block. // @see deviceClientMonitorLoop mSelector.wakeup(); socketChannel.configureBlocking(false); socketChannel.register(mSelector, SelectionKey.OP_READ, device); } return true; } } catch (TimeoutException) { try { // attempt to close the socket if needed. socketChannel.close(); } catch (IOException) { // we can ignore that one. It may already have been closed. } Log.d("DeviceMonitor", "Connection Failure when starting to monitor device '" + device + "' : timeout"); } catch (AdbCommandRejectedException e) { try { // attempt to close the socket if needed. socketChannel.close(); } catch (IOException) { // we can ignore that one. It may already have been closed. } Log.d("DeviceMonitor", "Adb refused to start monitoring device '" + device + "' : " + e.Message); } catch (IOException e) { try { // attempt to close the socket if needed. socketChannel.close(); } catch (IOException) { // we can ignore that one. It may already have been closed. } Log.d("DeviceMonitor", "Connection Failure when starting to monitor device '" + device + "' : " + e.Message); } } return false; }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: private void queryNewDeviceForMountingPoint(final Device device, final String name) throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException, java.io.IOException //JAVA TO C# CONVERTER WARNING: 'final' parameters are not allowed in .NET: private void queryNewDeviceForMountingPoint(Device device, string name) { var tempVar = new MultiLineReceiverAnonymousInnerClassHelper(); /*tempVar.isCancelledDelegateInstance = () => { return false; };*/ tempVar.processNewLinesDelegateInstance = (string[] lines) => { foreach (string line in lines) { if (line.Length > 0) { // this should be the only one. device.setMountingPoint(name, line); } } }; device.executeShellCommand("echo $" + name, tempVar); }
/// <summary> /// Queries a device for its build info. </summary> /// <param name="device"> the device to query. </param> private void queryNewDeviceForInfo(Device device) { // TODO: do this in a separate thread. try { // first get the list of properties. device.executeShellCommand(GetPropReceiver.GETPROP_COMMAND, new GetPropReceiver(device)); queryNewDeviceForMountingPoint(device, DeviceConstants.MNT_EXTERNAL_STORAGE); queryNewDeviceForMountingPoint(device, DeviceConstants.MNT_DATA); queryNewDeviceForMountingPoint(device, DeviceConstants.MNT_ROOT); // now get the emulator Virtual Device name (if applicable). if (device.emulator) { EmulatorConsole console = EmulatorConsole.getConsole(device); if (console != null) { device.avdName = console.avdName; } } } catch (TimeoutException) { Log.w("DeviceMonitor", string.Format("Connection timeout getting info for device {0}", device.serialNumber)); } catch (AdbCommandRejectedException e) { // This should never happen as we only do this once the device is online. Log.w("DeviceMonitor", string.Format("Adb rejected command to get device {0} info: {1}", device.serialNumber, e.Message)); } catch (ShellCommandUnresponsiveException) { Log.w("DeviceMonitor", string.Format("Adb shell command took too long returning info for device {0}", device.serialNumber)); } catch (IOException) { Log.w("DeviceMonitor", string.Format("IO Error getting info for device {0}", device.serialNumber)); } }
/// <summary> /// Creates the receiver with the device the receiver will modify. </summary> /// <param name="device"> The device to modify </param> public GetPropReceiver(Device device) { mDevice = device; }
/// <summary> /// Create an object for a new client connection. /// </summary> /// <param name="device"> the device this client belongs to </param> /// <param name="chan"> the connected <seealso cref="SocketChannel"/>. </param> /// <param name="pid"> the client pid. </param> internal Client(Device device, SocketChannel chan, int pid) { mDevice = device; mChan = chan; mReadBuffer = ByteBuffer.allocate(INITIAL_BUF_SIZE); mWriteBuffer = ByteBuffer.allocate(WRITE_BUF_SIZE); mOutstandingReqs = new Dictionary<int?, ChunkHandler>(); mConnState = ST_INIT; mClientData = new ClientData(pid); mThreadUpdateEnabled = DdmPreferences.initialThreadUpdate; mHeapUpdateEnabled = DdmPreferences.initialHeapUpdate; }
/// <summary> /// Creates a Sync service object. </summary> /// <param name="address"> The address to connect to </param> /// <param name="device"> the <seealso cref="Device"/> that the service connects to. </param> internal SyncService(EndPoint address, Device device) { mAddress = address; mDevice = device; }
/// <summary> /// Processes an incoming device message from the socket </summary> /// <param name="socket"> </param> /// <param name="length"> </param> /// <exception cref="IOException"> </exception> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: private void processIncomingDeviceData(int length) throws java.io.IOException private void processIncomingDeviceData(int length) { List<Device> list = new List<Device>(); if (length > 0) { var buffer = new byte[length]; string result = read(mMainAdbConnection, buffer); string[] devices = StringHelperClass.StringSplit(result, "\n", true); //$NON-NLS-1$ foreach (string d in devices) { string[] param = StringHelperClass.StringSplit(d, "\t", true); //$NON-NLS-1$ if (param.Length == 2) { // new adb uses only serial numbers to identify devices Device device = new Device(this, param[0], DeviceState.getState(param[1])); //serialnumber //add the device to the list list.Add(device); } } } // now merge the new devices with the old ones. updateDevices(list); }