/** * Handle chunks not recognized by handlers. The handleChunk() method * in sub-classes should call this if the chunk type isn't recognized. */ protected void handleUnknownChunk(IClient client, int type, MemoryStream data, bool isReply, int msgId) { if (type == CHUNK_FAIL) { int errorCode, msgLen; string msg; errorCode = data.ReadByte(); msgLen = data.ReadByte(); msg = GetString(data, msgLen); Log.w("ddms", "WARNING: failure code=" + errorCode + " msg=" + msg); } else { Log.w("ddms", "WARNING: received unknown chunk " + name(type) + ": len=" + data.Length + ", reply=" + isReply + ", msgId=0x" + msgId.ToString("X8")); } Log.w("ddms", " client " + client + ", handler " + this); }
public Socket Accept(Socket listenChan) { lock ( listenChan ) { if (listenChan != null) { Socket newChan = listenChan.Accept( ); if (Channel != null) { Log.w("ddms", "debugger already talking to " + Client.ToString( ) + " on " + ListenPort.ToString( )); newChan.Close( ); return(null); } Channel = newChan; Channel.Blocking = false; ConnectionState = ConnectionStates.AwaitShake; return(Channel); } return(null); } }
/// <summary> /// Pulls a single file. /// <para>Because this method just deals with a String for the remote file instead of FileEntry, /// the size of the file being pulled is unknown and the ISyncProgressMonitor will not properly /// show the progress</para> /// </summary> /// <param name="remoteFilepath">the full path to the remote file</param> /// <param name="localFilename">The local destination.</param> /// <param name="monitor">The progress monitor. Cannot be null.</param> /// <returns> /// a SyncResult object with a code and an optional message. /// </returns> /// <exception cref="System.ArgumentNullException">monitor;Monitor cannot be null</exception> /// <exception cref="ArgumentNullException">Throws if monitor is null</exception> /// <gist id="9021e6c39ee20a6e122b" /> public SyncResult PullFile(String remoteFilepath, String localFilename, ISyncProgressMonitor monitor) { if (monitor == null) { throw new ArgumentNullException("monitor", "Monitor cannot be null"); } long totalWork = 0; try { FileListingService fls = new FileListingService(this.Device); FileEntry remoteFileEntry = fls.FindFileEntry(remoteFilepath); totalWork = remoteFileEntry.Size; } catch (FileNotFoundException ffe) { Log.w("ddms", ffe); } monitor.Start(totalWork); SyncResult result = DoPullFile(remoteFilepath, localFilename, monitor); monitor.Stop( ); return(result); }
/// <summary> /// Stops the adb host side server. /// </summary> /// <returns>true if success</returns> private bool StopAdb( ) { if (string.IsNullOrEmpty(AdbOsLocation)) { Log.e(ADB, "Cannot stop adb when AndroidDebugBridge is created without the location of adb."); return(false); } int status = -1; try { String command = "kill-server"; ProcessStartInfo psi = new ProcessStartInfo(AdbOsLocation, command); psi.CreateNoWindow = true; psi.WindowStyle = ProcessWindowStyle.Hidden; psi.UseShellExecute = false; psi.RedirectStandardError = true; psi.RedirectStandardOutput = true; using (Process proc = Process.Start(psi)) { proc.WaitForExit( ); status = proc.ExitCode; } } catch (IOException) { // we'll return false; } catch (Exception) { // we'll return false; } if (status != 0) { Log.w(DDMS, "'adb kill-server' failed -- run manually if necessary"); return(false); } Log.d(DDMS, "'adb kill-server' succeeded"); return(true); }
/// <include file='.\ISyncService.xml' path='/SyncService/Open/*'/> public bool Open() { if (this.IsOpen) { return(true); } try { this.Channel = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); this.Channel.Connect(this.Address); this.Channel.Blocking = true; // target a specific device AdbHelper.Instance.SetDevice(this.Channel, this.Device); byte[] request = AdbHelper.Instance.FormAdbRequest("sync:"); AdbHelper.Instance.Write(this.Channel, request, -1, DdmPreferences.Timeout); AdbResponse resp = AdbHelper.Instance.ReadAdbResponse(this.Channel, false /* readDiagString */); if (!resp.IOSuccess || !resp.Okay) { Log.w("ddms:syncservice", "Got timeout or unhappy response from ADB sync req: {0}", resp.Message); this.Channel.Close(); this.Channel = null; return(false); } } catch (IOException) { this.Close(); throw; } return(true); }
/// <summary> /// Queries adb for its version number and checks it against #MIN_VERSION_NUMBER and MAX_VERSION_NUMBER /// </summary> private void CheckAdbVersion( ) { // default is bad check VersionCheck = false; if (string.IsNullOrEmpty(AdbOsLocation)) { Log.w(TAG, "AdbOsLocation is Empty"); return; } try { Log.d(DDMS, String.Format("Checking '{0} version'", AdbOsLocation)); ProcessStartInfo psi = new ProcessStartInfo(AdbOsLocation, "version"); psi.WindowStyle = ProcessWindowStyle.Hidden; psi.CreateNoWindow = true; psi.UseShellExecute = false; psi.RedirectStandardError = true; psi.RedirectStandardOutput = true; List <String> errorOutput = new List <String> ( ); List <String> stdOutput = new List <String> ( ); using (Process proc = Process.Start(psi)) { int status = GrabProcessOutput(proc, errorOutput, stdOutput, true /* waitForReaders */); if (status != 0) { StringBuilder builder = new StringBuilder("'adb version' failed!"); builder.AppendLine(string.Empty); foreach (String error in errorOutput) { builder.AppendLine(error); } Log.LogAndDisplay(LogLevel.Error, TAG, builder.ToString( )); } } // check both stdout and stderr bool versionFound = false; foreach (String line in stdOutput) { versionFound = ScanVersionLine(line); if (versionFound) { break; } } if (!versionFound) { foreach (String line in errorOutput) { versionFound = ScanVersionLine(line); if (versionFound) { break; } } } if (!versionFound) { // if we get here, we failed to parse the output. Log.LogAndDisplay(LogLevel.Error, ADB, "Failed to parse the output of 'adb version'"); } } catch (IOException e) { Log.LogAndDisplay(LogLevel.Error, ADB, "Failed to get the adb version: " + e.Message); } }
/// <summary> /// Processes the new lines. /// </summary> /// <param name="lines">The lines.</param> protected override void ProcessNewLines(string[] lines) { BatteryInfo = new BatteryInfo( ); foreach (var line in lines) { var match = line.Match(BATTERY_LEVEL, REOPTIONS); if (match.Success) { try { BatteryInfo.Level = Int32.Parse(match.Groups[1].Value); } catch (FormatException) { Log.w(TAG, String.Format("Failed to parse {0} as an integer", match.Groups[1].Value)); } } match = line.Match(SCALE, REOPTIONS); if (match.Success) { try { BatteryInfo.Scale = Int32.Parse(match.Groups[1].Value); } catch (FormatException) { Log.w(TAG, String.Format("Failed to parse {0} as an integer", match.Groups[1].Value)); } } match = line.Match(AC_POWER, REOPTIONS); if (match.Success) { BatteryInfo.ACPowered = String.Compare(match.Groups[1].Value, bool.TrueString, true) == 0; } match = line.Match(USB_POWER, REOPTIONS); if (match.Success) { BatteryInfo.UsbPowered = String.Compare(match.Groups[1].Value, bool.TrueString, true) == 0; } match = line.Match(PRESENT, REOPTIONS); if (match.Success) { BatteryInfo.Present = String.Compare(match.Groups[1].Value, bool.TrueString, true) == 0; } match = line.Match(STATUS, REOPTIONS); if (match.Success) { try { var i = Int32.Parse(match.Groups[1].Value); BatteryInfo.Status = i.ToEnum <BatteryInfo.StatusTypes> ( ); } catch (FormatException) { Log.w(TAG, String.Format("Failed to parse {0} as an integer", match.Groups[1].Value)); } } match = line.Match(HEALTH, REOPTIONS); if (match.Success) { try { var i = Int32.Parse(match.Groups[1].Value); BatteryInfo.Health = i.ToEnum <BatteryInfo.HealthTypes> ( ); } catch (FormatException) { Log.w(TAG, String.Format("Failed to parse {0} as an integer", match.Groups[1].Value)); } } match = line.Match(VOLTAGE, REOPTIONS); if (match.Success) { try { BatteryInfo.Voltage = Int32.Parse(match.Groups[1].Value); } catch (FormatException) { Log.w(TAG, String.Format("Failed to parse {0} as an integer", match.Groups[1].Value)); } } match = line.Match(TYPE, REOPTIONS); if (match.Success) { BatteryInfo.Type = match.Groups[1].Value; } match = line.Match(TEMP, REOPTIONS); if (match.Success) { try { BatteryInfo.Temperature = Int32.Parse(match.Groups[1].Value); } catch (FormatException) { Log.w(TAG, String.Format("Failed to parse {0} as an integer", match.Groups[1].Value)); } } } }
/// <summary> /// Executes the remote command. /// </summary> /// <param name="endPoint">The end point.</param> /// <param name="command">The command.</param> /// <param name="device">The device.</param> /// <param name="rcvr">The RCVR.</param> /// <param name="maxTimeToOutputResponse">The max time to output response.</param> /// <exception cref="AdbException">failed submitting shell command</exception> /// <exception cref="System.OperationCanceledException"></exception> /// <exception cref="Managed.Adb.Exceptions.ShellCommandUnresponsiveException"></exception> /// <exception cref="System.IO.FileNotFoundException"></exception> /// <exception cref="UnknownOptionException"></exception> /// <exception cref="CommandAbortingException"></exception> /// <exception cref="PermissionDeniedException"></exception> public void ExecuteRemoteCommand(IPEndPoint endPoint, String command, Device device, IShellOutputReceiver rcvr, int maxTimeToOutputResponse) { Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); if (!device.IsOnline) { return; } try { socket.Connect(endPoint); socket.ReceiveTimeout = maxTimeToOutputResponse; socket.SendTimeout = maxTimeToOutputResponse; socket.Blocking = true; SetDevice(socket, device); byte[] request = FormAdbRequest("shell:" + command); if (!Write(socket, request)) { throw new AdbException("failed submitting shell command"); } AdbResponse resp = ReadAdbResponse(socket, false /* readDiagString */); if (!resp.IOSuccess || !resp.Okay) { throw new AdbException("sad result from adb: " + resp.Message); } byte[] data = new byte[16384]; int count = -1; while (count != 0) { if (rcvr != null && rcvr.IsCancelled) { Log.w(TAG, "execute: cancelled"); throw new OperationCanceledException( ); } count = socket.Receive(data); if (count == 0) { // we're at the end, we flush the output rcvr.Flush( ); Log.w(TAG, "execute '" + command + "' on '" + device + "' : EOF hit. Read: " + count); } else { string[] cmd = command.Trim( ).Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); string sdata = data.GetString(0, count, AdbHelper.DEFAULT_ENCODING); var sdataTrimmed = sdata.Trim( ); if (sdataTrimmed.EndsWith(String.Format("{0}: not found", cmd[0]))) { Log.w(TAG, "The remote execution returned: '{0}: not found'", cmd[0]); throw new FileNotFoundException(string.Format("The remote execution returned: '{0}: not found'", cmd[0])); } if (sdataTrimmed.EndsWith("No such file or directory")) { Log.w(TAG, "The remote execution returned: {0}", sdataTrimmed); throw new FileNotFoundException(String.Format("The remote execution returned: {0}", sdataTrimmed)); } // for "unknown options" if (sdataTrimmed.Contains("Unknown option")) { Log.w(TAG, "The remote execution returned: {0}", sdataTrimmed); throw new UnknownOptionException(sdataTrimmed); } // for "aborting" commands if (sdataTrimmed.IsMatch("Aborting.$")) { Log.w(TAG, "The remote execution returned: {0}", sdataTrimmed); throw new CommandAbortingException(sdataTrimmed); } // for busybox applets // cmd: applet not found if (sdataTrimmed.IsMatch("applet not found$") && cmd.Length > 1) { Log.w(TAG, "The remote execution returned: '{0}'", sdataTrimmed); throw new FileNotFoundException(string.Format("The remote execution returned: '{0}'", sdataTrimmed)); } // checks if the permission to execute the command was denied. // workitem: 16822 if (sdataTrimmed.IsMatch("(permission|access) denied$")) { Log.w(TAG, "The remote execution returned: '{0}'", sdataTrimmed); throw new PermissionDeniedException(String.Format("The remote execution returned: '{0}'", sdataTrimmed)); } // Add the data to the receiver if (rcvr != null) { rcvr.AddOutput(data, 0, count); } } } } catch (SocketException s) { throw new ShellCommandUnresponsiveException( ); } finally { if (socket != null) { socket.Close( ); } rcvr.Flush( ); } }
/// <summary> /// Gets the frame buffer from the specified end point. /// </summary> /// <param name="adbSockAddr">The adb sock addr.</param> /// <param name="device">The device.</param> /// <returns></returns> public RawImage GetFrameBuffer(IPEndPoint adbSockAddr, IDevice device) { RawImage imageParams = new RawImage( ); byte[] request = FormAdbRequest("framebuffer:"); //$NON-NLS-1$ byte[] nudge = { 0 }; byte[] reply; Socket adbChan = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { adbChan.Connect(adbSockAddr); adbChan.Blocking = true; // if the device is not -1, then we first tell adb we're looking to talk // to a specific device SetDevice(adbChan, device); if (!Write(adbChan, request)) { throw new AdbException("failed asking for frame buffer"); } AdbResponse resp = ReadAdbResponse(adbChan, false /* readDiagString */); if (!resp.IOSuccess || !resp.Okay) { Log.w(TAG, "Got timeout or unhappy response from ADB fb req: " + resp.Message); adbChan.Close( ); return(null); } // first the protocol version. reply = new byte[4]; if (!Read(adbChan, reply)) { Log.w(TAG, "got partial reply from ADB fb:"); adbChan.Close( ); return(null); } BinaryReader buf; int version = 0; using (MemoryStream ms = new MemoryStream(reply)) { buf = new BinaryReader(ms); version = buf.ReadInt16( ); } // get the header size (this is a count of int) int headerSize = RawImage.GetHeaderSize(version); // read the header reply = new byte[headerSize * 4]; if (!Read(adbChan, reply)) { Log.w(TAG, "got partial reply from ADB fb:"); adbChan.Close( ); return(null); } using (MemoryStream ms = new MemoryStream(reply)) { buf = new BinaryReader(ms); // fill the RawImage with the header if (imageParams.ReadHeader(version, buf) == false) { Log.w(TAG, "Unsupported protocol: " + version); return(null); } } Log.d(TAG, "image params: bpp=" + imageParams.Bpp + ", size=" + imageParams.Size + ", width=" + imageParams.Width + ", height=" + imageParams.Height); if (!Write(adbChan, nudge)) { throw new AdbException("failed nudging"); } reply = new byte[imageParams.Size]; if (!Read(adbChan, reply)) { Log.w(TAG, "got truncated reply from ADB fb data"); adbChan.Close( ); return(null); } imageParams.Data = reply; } finally { if (adbChan != null) { adbChan.Close( ); } } return(imageParams); }
/// <summary> /// Executes the remote command. /// </summary> /// <param name="endPoint">The end point.</param> /// <param name="command">The command.</param> /// <param name="device">The device.</param> /// <param name="rcvr">The RCVR.</param> /// <param name="maxTimeToOutputResponse">The max time to output response.</param> /// <exception cref="System.OperationCanceledException"></exception> /// <exception cref="System.IO.FileNotFoundException"> /// </exception> /// <exception cref="Managed.Adb.Exceptions.UnknownOptionException"></exception> /// <exception cref="Managed.Adb.Exceptions.CommandAbortingException"></exception> /// <exception cref="Managed.Adb.Exceptions.PermissionDeniedException"></exception> /// <exception cref="Managed.Adb.Exceptions.ShellCommandUnresponsiveException"></exception> /// <exception cref="AdbException">failed submitting shell command</exception> /// <exception cref="UnknownOptionException"></exception> /// <exception cref="CommandAbortingException"></exception> /// <exception cref="PermissionDeniedException"></exception> public void ExecuteRemoteCommand(IPEndPoint endPoint, String command, Device device, IShellOutputReceiver rcvr, int maxTimeToOutputResponse) { using (var socket = ExecuteRawSocketCommand(endPoint, device, "shell:{0}".With(command))) { socket.ReceiveTimeout = maxTimeToOutputResponse; socket.SendTimeout = maxTimeToOutputResponse; try { byte[] data = new byte[16384]; int count = -1; while (count != 0) { if (rcvr != null && rcvr.IsCancelled) { Log.w(TAG, "execute: cancelled"); throw new OperationCanceledException(); } count = socket.Receive(data); if (count == 0) { // we're at the end, we flush the output rcvr.Flush(); Log.w(TAG, "execute '" + command + "' on '" + device + "' : EOF hit. Read: " + count); } else { string[] cmd = command.Trim().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); string sdata = data.GetString(0, count, AdbHelper.DEFAULT_ENCODING); var sdataTrimmed = sdata.Trim(); if (sdataTrimmed.EndsWith(String.Format("{0}: not found", cmd[0]))) { Log.w(TAG, "The remote execution returned: '{0}: not found'", cmd[0]); throw new FileNotFoundException(string.Format("The remote execution returned: '{0}: not found'", cmd[0])); } if (sdataTrimmed.EndsWith("No such file or directory")) { Log.w(TAG, "The remote execution returned: {0}", sdataTrimmed); throw new FileNotFoundException(String.Format("The remote execution returned: {0}", sdataTrimmed)); } // for "unknown options" if (sdataTrimmed.Contains("Unknown option")) { Log.w(TAG, "The remote execution returned: {0}", sdataTrimmed); throw new UnknownOptionException(sdataTrimmed); } // for "aborting" commands if (sdataTrimmed.IsMatch("Aborting.$")) { Log.w(TAG, "The remote execution returned: {0}", sdataTrimmed); throw new CommandAbortingException(sdataTrimmed); } // for busybox applets // cmd: applet not found if (sdataTrimmed.IsMatch("applet not found$") && cmd.Length > 1) { Log.w(TAG, "The remote execution returned: '{0}'", sdataTrimmed); throw new FileNotFoundException(string.Format("The remote execution returned: '{0}'", sdataTrimmed)); } // checks if the permission to execute the command was denied. // workitem: 16822 if (sdataTrimmed.IsMatch("(permission|access) denied$")) { Log.w(TAG, "The remote execution returned: '{0}'", sdataTrimmed); throw new PermissionDeniedException(String.Format("The remote execution returned: '{0}'", sdataTrimmed)); } // Add the data to the receiver if (rcvr != null) { rcvr.AddOutput(data, 0, count); } } } } catch (SocketException) { throw new ShellCommandUnresponsiveException(); } finally { rcvr.Flush(); } } }
/// <summary> /// Monitors the devices. This connects to the Debug Bridge /// </summary> private void DeviceMonitorLoop() { this.IsRunning = true; do { try { if (this.MainAdbConnection == null) { Log.d(TAG, "Opening adb connection"); this.MainAdbConnection = this.OpenAdbConnection(); if (this.MainAdbConnection == null) { this.ConnectionAttemptCount++; Log.i(TAG, "Connection attempts: {0}", this.ConnectionAttemptCount); if (this.ConnectionAttemptCount > 10) { if (this.Server.Start() == false) { this.RestartAttemptCount++; Log.e(TAG, "adb restart attempts: {0}", this.RestartAttemptCount); } else { this.RestartAttemptCount = 0; } } this.WaitBeforeContinue(); } else { Log.d(TAG, "Connected to adb for device monitoring"); this.ConnectionAttemptCount = 0; } } if (this.MainAdbConnection != null && !this.IsMonitoring && this.MainAdbConnection.Connected) { this.IsMonitoring = this.SendDeviceListMonitoringRequest(); } if (this.IsMonitoring) { // read the length of the incoming message int length = this.ReadLength(this.MainAdbConnection, this.LengthBuffer); if (length >= 0) { // read the incoming message this.ProcessIncomingDeviceData(length); // flag the fact that we have build the list at least once. this.HasInitialDeviceList = true; } } } catch (IOException ioe) { if (!this.IsRunning) { Log.e(TAG, "Adb connection Error: ", ioe); this.IsMonitoring = false; if (this.MainAdbConnection != null) { try { this.MainAdbConnection.Close(); } catch (IOException) { // we can safely ignore that one. } this.MainAdbConnection = null; } } } catch (Exception ex) { Log.w(TAG, ex); } }while (this.IsRunning); }