Exemple #1
0
        /// <inheritdoc/>
        protected void Root(string request, DeviceData device)
        {
            this.EnsureDevice(device);

            using (IAdbSocket socket = this.adbSocketFactory(this.EndPoint))
            {
                socket.SetDevice(device);
                socket.SendAdbRequest(request);
                var response = socket.ReadAdbResponse();

                // ADB will send some additional data
                byte[] buffer = new byte[1024];
                int    read   = socket.Read(buffer);

                var responseMessage = Encoding.UTF8.GetString(buffer, 0, read);

                // See https://android.googlesource.com/platform/system/core/+/master/adb/commandline.cpp#1026 (adb_root)
                // for more information on how upstream does this.
                if (!string.Equals(responseMessage, "restarting", StringComparison.OrdinalIgnoreCase))
                {
                    throw new AdbException(responseMessage);
                }
                else
                {
                    // Give adbd some time to kill itself and come back up.
                    // We can't use wait-for-device because devices (e.g. adb over network) might not come back.
                    Task.Delay(3000).GetAwaiter().GetResult();
                }
            }
        }
Exemple #2
0
        /// <inheritdoc/>
        public void Install(DeviceData device, Stream apk, params string[] arguments)
        {
            this.EnsureDevice(device);

            if (apk == null)
            {
                throw new ArgumentNullException(nameof(apk));
            }

            if (!apk.CanRead || !apk.CanSeek)
            {
                throw new ArgumentOutOfRangeException(nameof(apk), "The apk stream must be a readable and seekable stream");
            }

            StringBuilder requestBuilder = new StringBuilder();

            requestBuilder.Append("exec:cmd package 'install' ");

            if (arguments != null)
            {
                foreach (var argument in arguments)
                {
                    requestBuilder.Append(" ");
                    requestBuilder.Append(argument);
                }
            }

            // add size parameter [required for streaming installs]
            // do last to override any user specified value
            requestBuilder.Append($" -S {apk.Length}");

            using (IAdbSocket socket = this.adbSocketFactory(this.EndPoint))
            {
                socket.SetDevice(device);

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

                byte[] buffer = new byte[32 * 1024];
                int    read   = 0;

                while ((read = apk.Read(buffer, 0, buffer.Length)) > 0)
                {
                    socket.Send(buffer, read);
                }

                read = socket.Read(buffer);
                var value = Encoding.UTF8.GetString(buffer, 0, read);

                if (!string.Equals(value, "Success\n"))
                {
                    throw new AdbException(value);
                }
            }
        }
Exemple #3
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 = this.adbSocketFactory(this.EndPoint))
            {
                socket.SetDevice(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;
                        }
                    }
                }
            }
        }
Exemple #4
0
        /// <inheritdoc/>
        public async Task ExecuteRemoteCommandAsync(string command, DeviceData device, IShellOutputReceiver receiver, Encoding encoding, CancellationToken cancellationToken)
        {
            this.EnsureDevice(device);

            using (IAdbSocket socket = this.adbSocketFactory(this.EndPoint))
            {
                cancellationToken.Register(() => socket.Dispose());

                socket.SetDevice(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 = await reader.ReadLineAsync().ConfigureAwait(false);

                            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 #5
0
        public void RemoveAllReverseForwards(DeviceData device)
        {
            this.EnsureDevice(device);

            using (IAdbSocket socket = this.adbSocketFactory(this.EndPoint))
            {
                socket.SetDevice(device);

                socket.SendAdbRequest($"reverse:killforward-all");
                var response = socket.ReadAdbResponse();
            }
        }
Exemple #6
0
        /// <inheritdoc/>
        public void Reboot(string into, DeviceData device)
        {
            this.EnsureDevice(device);

            var request = $"reboot:{into}";

            using (IAdbSocket socket = this.adbSocketFactory(this.EndPoint))
            {
                socket.SetDevice(device);
                socket.SendAdbRequest(request);
                var response = socket.ReadAdbResponse();
            }
        }
Exemple #7
0
        public IEnumerable <ForwardData> ListReverseForward(DeviceData device)
        {
            this.EnsureDevice(device);

            using (IAdbSocket socket = this.adbSocketFactory(this.EndPoint))
            {
                socket.SetDevice(device);

                socket.SendAdbRequest($"reverse: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)));
            }
        }
Exemple #8
0
        /// <inheritdoc/>
        public int CreateReverseForward(DeviceData device, string remote, string local, bool allowRebind)
        {
            this.EnsureDevice(device);

            using (IAdbSocket socket = this.adbSocketFactory(this.EndPoint))
            {
                socket.SetDevice(device);

                string rebind = allowRebind ? string.Empty : "norebind:";

                socket.SendAdbRequest($"reverse:forward:{rebind}{remote};{local}");
                var response = socket.ReadAdbResponse();
                response = socket.ReadAdbResponse();
                var portString = socket.ReadString();

                if (portString != null && int.TryParse(portString, out int port))
                {
                    return(port);
                }

                return(0);
            }
        }