Provides factory methods used by the various SharpAdbClient classes.
        /// <inheritdoc/>
        public void RemoveForward(DeviceData device, int localPort)
        {
            this.EnsureDevice(device);

            using (IAdbSocket socket = Factories.AdbSocketFactory(this.EndPoint))
            {
                socket.SendAdbRequest($"host-serial:{device.Serial}:killforward:tcp:{localPort}");
                var response = socket.ReadAdbResponse();
            }
        }
        /// <inheritdoc/>
        public void RemoveAllForwards(DeviceData device)
        {
            this.EnsureDevice(device);

            using (IAdbSocket socket = Factories.AdbSocketFactory(this.EndPoint))
            {
                socket.SendAdbRequest($"host-serial:{device.Serial}:killforward-all");
                var response = socket.ReadAdbResponse();
            }
        }
        /// <inheritdoc/>
        public void KillAdb()
        {
            using (IAdbSocket socket = Factories.AdbSocketFactory(this.EndPoint))
            {
                socket.SendAdbRequest("host:kill");

                // The host will immediately close the connection after the kill
                // command has been sent; no need to read the response.
            }
        }
Exemple #4
0
        /// <include file='IAdbClient.xml' path='/IAdbClient/CreateForward/*'/>
        public void CreateForward(DeviceData device, string local, string remote, bool allowRebind)
        {
            using (IAdbSocket socket = Factories.AdbSocketFactory(this.EndPoint))
            {
                string rebind = allowRebind ? string.Empty : "norebind:";

                socket.SendAdbRequest($"host-serial:{device.Serial}:forward:{rebind}{local};{remote}");
                var response = socket.ReadAdbResponse();
            }
        }
        /// <inheritdoc/>
        public void ExecuteRemoteCommand(string command, DeviceData device, IShellOutputReceiver receiver, CancellationToken cancellationToken, int maxTimeToOutputResponse)
        {
            this.EnsureDevice(device);

            using (IAdbSocket socket = Factories.AdbSocketFactory(this.EndPoint))
            {
                cancellationToken.Register(() => socket.Close());

                this.SetDevice(socket, device);
                socket.SendAdbRequest($"shell:{command}");
                var response = socket.ReadAdbResponse();

                try
                {
                    using (StreamReader reader = new StreamReader(socket.GetShellStream(), Encoding))
                    {
                        // Previously, we would loop while reader.Peek() >= 0. Turns out that this would
                        // break too soon in certain cases (about every 10 loops, so it appears to be a timing
                        // issue). Checking for reader.ReadLine() to return null appears to be much more robust
                        // -- one of the integration test fetches output 1000 times and found no truncations.
                        while (!cancellationToken.IsCancellationRequested)
                        {
                            var line = reader.ReadLine();

                            if (line == null)
                            {
                                break;
                            }

                            if (receiver != null)
                            {
                                receiver.AddOutput(line);
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    // If a cancellation was requested, this main loop is interrupted with an exception
                    // because the socket is closed. In that case, we don't need to throw a ShellCommandUnresponsiveException.
                    // In all other cases, something went wrong, and we want to report it to the user.
                    if (!cancellationToken.IsCancellationRequested)
                    {
                        throw new ShellCommandUnresponsiveException(e);
                    }
                }
                finally
                {
                    if (receiver != null)
                    {
                        receiver.Flush();
                    }
                }
            }
        }
Exemple #6
0
        /// <inheritdoc/>
        public async Task RunLogServiceAsync(DeviceData device, Action <LogEntry> messageSink, CancellationToken cancellationToken, params LogId[] logNames)
        {
            if (messageSink == null)
            {
                throw new ArgumentException(nameof(messageSink));
            }

            this.EnsureDevice(device);

            // The 'log' service has been deprecated, see
            // https://android.googlesource.com/platform/system/core/+/7aa39a7b199bb9803d3fd47246ee9530b4a96177
            using (IAdbSocket socket = Factories.AdbSocketFactory(this.EndPoint))
            {
                this.SetDevice(socket, device);

                StringBuilder request = new StringBuilder();
                request.Append("shell:logcat -B");

                foreach (var logName in logNames)
                {
                    request.Append($" -b {logName.ToString().ToLowerInvariant()}");
                }

                socket.SendAdbRequest(request.ToString());
                var response = socket.ReadAdbResponse();

                using (Stream stream = socket.GetShellStream())
                {
                    LogReader reader = new LogReader(stream);

                    while (!cancellationToken.IsCancellationRequested)
                    {
                        LogEntry entry = null;

                        try
                        {
                            entry = await reader.ReadEntry(cancellationToken).ConfigureAwait(false);
                        }
                        catch (EndOfStreamException)
                        {
                            // This indicates the end of the stream; the entry will remain null.
                        }

                        if (entry != null)
                        {
                            messageSink(entry);
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            }
        }
        /// <inheritdoc/>
        public int GetAdbVersion()
        {
            using (var socket = Factories.AdbSocketFactory(this.EndPoint))
            {
                socket.SendAdbRequest("host:version");
                var response = socket.ReadAdbResponse();
                var version  = socket.ReadString();

                return(int.Parse(version, NumberStyles.HexNumber));
            }
        }
Exemple #8
0
        /// <include file='IAdbClient.xml' path='/IAdbClient/Reboot/*'/>
        public void Reboot(string into, DeviceData device)
        {
            var request = $"reboot:{into}";

            using (IAdbSocket socket = Factories.AdbSocketFactory(this.EndPoint))
            {
                this.SetDevice(socket, device);
                socket.SendAdbRequest(request);
                var response = socket.ReadAdbResponse();
            }
        }
        /// <inheritdoc/>
        public List <DeviceData> GetDevices()
        {
            using (IAdbSocket socket = Factories.AdbSocketFactory(this.EndPoint))
            {
                socket.SendAdbRequest("host:devices-l");
                socket.ReadAdbResponse();
                var reply = socket.ReadString();

                string[] data = reply.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);

                return(data.Select(d => DeviceData.CreateFromAdbData(d)).ToList());
            }
        }
Exemple #10
0
        /// <inheritdoc/>
        public void Connect(DnsEndPoint endpoint)
        {
            if (endpoint == null)
            {
                throw new ArgumentNullException(nameof(endpoint));
            }

            using (IAdbSocket socket = Factories.AdbSocketFactory(this.EndPoint))
            {
                socket.SendAdbRequest($"host:connect:{endpoint.Host}:{endpoint.Port}");
                var response = socket.ReadAdbResponse();
            }
        }
Exemple #11
0
        /// <include file='IAdbClient.xml' path='/IAdbClient/ListForward/*'/>
        public IEnumerable <ForwardData> ListForward(DeviceData device)
        {
            using (IAdbSocket socket = Factories.AdbSocketFactory(this.EndPoint))
            {
                socket.SendAdbRequest($"host-serial:{device.Serial}:list-forward");
                var response = socket.ReadAdbResponse();

                var data = socket.ReadString();

                var parts = data.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);

                return(parts.Select(p => ForwardData.FromString(p)));
            }
        }
        /// <inheritdoc/>
        public IEnumerable <LogEntry> RunLogService(DeviceData device, params LogId[] logNames)
        {
            this.EnsureDevice(device);

            // The 'log' service has been deprecated, see
            // https://android.googlesource.com/platform/system/core/+/7aa39a7b199bb9803d3fd47246ee9530b4a96177
            using (IAdbSocket socket = Factories.AdbSocketFactory(this.EndPoint))
            {
                this.SetDevice(socket, device);

                StringBuilder request = new StringBuilder();
                request.Append("shell:logcat -B");

                foreach (var logName in logNames)
                {
                    request.Append($" -b {logName.ToString().ToLower()}");
                }

                socket.SendAdbRequest(request.ToString());
                var response = socket.ReadAdbResponse();

                using (Stream stream = socket.GetShellStream())
                    using (LogReader reader = new LogReader(stream))
                    {
                        while (true)
                        {
                            LogEntry entry = null;

                            try
                            {
                                entry = reader.ReadEntry();
                            }
                            catch (EndOfStreamException)
                            {
                                // This indicates the end of the stream; the entry will remain null.
                            }

                            if (entry != null)
                            {
                                yield return(entry);
                            }
                            else
                            {
                                break;
                            }
                        }
                    }
            }
        }
Exemple #13
0
        /// <summary>
        /// Asynchronously refreshes the framebuffer: fetches the latest framebuffer data from the device. Access the <see cref="Header"/>
        /// and <see cref="Data"/> properties to get the updated framebuffer data.
        /// </summary>
        /// <param name="cancellationToken">
        /// A <see cref="CancellationToken"/> which can be used to cancel the asynchronous task.
        /// </param>
        /// <returns>
        /// A <see cref="Task"/> which represents the asynchronous operation.
        /// </returns>
        public async Task RefreshAsync(CancellationToken cancellationToken)
        {
            this.EnsureNotDisposed();

            using (var socket = Factories.AdbSocketFactory(this.client.EndPoint))
            {
                // Select the target device
                this.client.SetDevice(socket, this.Device);

                // Send the framebuffer command
                socket.SendAdbRequest("framebuffer:");
                socket.ReadAdbResponse();

                // The result first is a FramebufferHeader object,
                await socket.ReadAsync(this.headerData, cancellationToken).ConfigureAwait(false);

                if (!this.headerInitialized)
                {
                    this.Header            = FramebufferHeader.Read(this.headerData);
                    this.headerInitialized = true;
                }

                if (this.Data == null || this.Data.Length < this.Header.Size)
                {
#if !NETFX
                    // Optimization on .NET Core: Use the BufferPool to rent buffers
                    if (this.Data != null)
                    {
                        ArrayPool <byte> .Shared.Return(this.Data, clearArray : false);
                    }

                    this.Data = ArrayPool <byte> .Shared.Rent((int)this.Header.Size);
#else
                    this.Data = new byte[(int)this.Header.Size];
#endif
                }

                // followed by the actual framebuffer content
                await socket.ReadAsync(this.Data, (int)this.Header.Size, cancellationToken).ConfigureAwait(false);
            }
        }
Exemple #14
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SyncService"/> class.
 /// </summary>
 /// <param name="client">
 /// A connection to an adb server.
 /// </param>
 /// <param name="device">
 /// The device on which to interact with the files.
 /// </param>
 public SyncService(IAdbClient client, DeviceData device)
     : this(Factories.AdbSocketFactory(client.EndPoint), device)
 {
 }
Exemple #15
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SyncService"/> class.
 /// </summary>
 /// <param name="device">
 /// The device on which to interact with the files.
 /// </param>
 public SyncService(DeviceData device)
     : this(Factories.AdbSocketFactory(AdbServer.Instance.EndPoint), device)
 {
 }
        /// <inheritdoc/>
        public StartServerResult StartServer(string adbPath, bool restartServerIfNewer)
        {
            var     serverStatus       = this.GetStatus();
            Version commandLineVersion = null;

            var commandLineClient = Factories.AdbCommandLineClientFactory(adbPath);

            if (commandLineClient.IsValidAdbFile(adbPath))
            {
                cachedAdbPath      = adbPath;
                commandLineVersion = commandLineClient.GetVersion();
            }

            // If the server is running, and no adb path is provided, check if we have the minimum
            // version
            if (adbPath == null)
            {
                if (!serverStatus.IsRunning)
                {
                    throw new AdbException("The adb server is not running, but no valid path to the adb.exe executable was provided. The adb server cannot be started.");
                }

                if (serverStatus.Version >= RequiredAdbVersion)
                {
                    return(StartServerResult.AlreadyRunning);
                }
                else
                {
                    throw new AdbException($"The adb deamon is running an outdated version ${commandLineVersion}, but not valid path to the adb.exe executable was provided. A more recent version of the adb server cannot be started.");
                }
            }

            if (serverStatus.IsRunning &&
                ((serverStatus.Version < RequiredAdbVersion) ||
                 ((serverStatus.Version < commandLineVersion) && restartServerIfNewer)))
            {
                if (adbPath == null)
                {
                    throw new ArgumentNullException(nameof(adbPath));
                }

                AdbClient.Instance.KillAdb();
                serverStatus.IsRunning = false;
                serverStatus.Version   = null;

                commandLineClient.StartServer();
                return(StartServerResult.RestartedOutdatedDaemon);
            }
            else if (!serverStatus.IsRunning)
            {
                if (adbPath == null)
                {
                    throw new ArgumentNullException(nameof(adbPath));
                }

                commandLineClient.StartServer();
                return(StartServerResult.Started);
            }
            else
            {
                return(StartServerResult.AlreadyRunning);
            }
        }