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

            using (IAdbSocket socket = this.adbSocketFactory(this.EndPoint))
            {
                this.SetDevice(socket, 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();
                }
            }
        }
Beispiel #2
0
 public VirtualDrive(DeviceData device, IAdbSocket client, char letter)
 {
     AndroidDevice = device;
     Label         = device.Serial;
     DriveLetter   = letter;
     Sync          = new SyncService(client, device);
 }
Beispiel #3
0
        /// <inheritdoc/>
        public bool CreateReverse(DeviceData device, string local, string remote, bool allowRebind)
        {
            this.EnsureDevice(device);

            using (IAdbSocket socket = this.adbSocketFactory(this.EndPoint))
            {
                string rebind = allowRebind ? string.Empty : "norebind:";

                socket.SendAdbRequest("host:transport:" + device.Serial);
                var response = socket.ReadAdbResponse();

                if (!response.Okay)
                {
                    return(false);
                }

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

                if (!response.Okay)
                {
                    return(false);
                }

                return(true);
            }
        }
Beispiel #4
0
        /// <inheritdoc/>
        public bool RemoveAllReverse(DeviceData device)
        {
            this.EnsureDevice(device);

            using (IAdbSocket socket = this.adbSocketFactory(this.EndPoint))
            {
                socket.SendAdbRequest("host:transport:" + device.Serial);
                var response = socket.ReadAdbResponse();

                if (!response.Okay)
                {
                    return(false);
                }

                socket.SendAdbRequest($"reverse:killforward-all");
                response = socket.ReadAdbResponse();

                if (!response.Okay)
                {
                    return(false);
                }
            }

            return(true);
        }
Beispiel #5
0
        /// <inheritdoc/>
        public void SetDevice(IAdbSocket socket, DeviceData device)
        {
            // if the device is not null, then we first tell adb we're looking to talk
            // to a specific device
            if (device != null)
            {
                socket.SendAdbRequest($"host:transport:{device.Serial}");

                try
                {
                    var response = socket.ReadAdbResponse();
                }
                catch (AdbException e)
                {
                    if (string.Equals("device not found", e.AdbError, StringComparison.OrdinalIgnoreCase))
                    {
                        throw new DeviceNotFoundException(device.Serial);
                    }
                    else
                    {
                        throw;
                    }
                }
            }
        }
Beispiel #6
0
        /// <include file='IAdbClient.xml' path='/IAdbClient/GetFrameBuffer/*'/>
        public async Task <Image> GetFrameBuffer(DeviceData device, CancellationToken cancellationToken)
        {
            using (IAdbSocket socket = Factories.AdbSocketFactory(this.EndPoint))
            {
                // Select the target device
                this.SetDevice(socket, device);

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

                // The result first is a FramebufferHeader object,
                var size       = Marshal.SizeOf(typeof(FramebufferHeader));
                var headerData = new byte[size];
                await socket.ReadAsync(headerData, cancellationToken).ConfigureAwait(false);

                var header = FramebufferHeader.Read(headerData);

                // followed by the actual framebuffer content
                var imageData = new byte[header.Size];
                socket.Read(imageData);

                // Convert the framebuffer to an image, and return that.
                return(header.ToImage(imageData));
            }
        }
Beispiel #7
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SyncService"/> class.
        /// </summary>
        /// <param name="socket">
        /// A <see cref="IAdbSocket"/> that enables to connection with the
        /// adb server.
        /// </param>
        /// <param name="device">
        /// The device on which to interact with the files.
        /// </param>
        public SyncService(IAdbSocket socket, DeviceData device)
        {
            this.Socket = socket;
            this.Device = device;

            this.Open();
        }
Beispiel #8
0
        /// <inheritdoc/>
        public IEnumerable <ForwardData> ListReverse(DeviceData device)
        {
            this.EnsureDevice(device);

            using (IAdbSocket socket = this.adbSocketFactory(this.EndPoint))
            {
                socket.SendAdbRequest("host:transport:" + device.Serial);
                var response = socket.ReadAdbResponse();

                if (!response.Okay)
                {
                    return(null);
                }

                socket.SendAdbRequest($"reverse:list-forward");
                response = socket.ReadAdbResponse();

                if (!response.Okay)
                {
                    return(null);
                }

                var data = socket.ReadString();

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

                return(parts.Select(p => ForwardData.FromString(p)));
            }
        }
Beispiel #9
0
 /// <include file='IAdbClient.xml' path='/IAdbClient/RemoveForward/*'/>
 public void RemoveForward(DeviceData device, int localPort)
 {
     using (IAdbSocket socket = Factories.AdbSocketFactory(this.EndPoint))
     {
         socket.SendAdbRequest($"host-serial:{device.Serial}:killforward:tcp:{localPort}");
         var response = socket.ReadAdbResponse();
     }
 }
Beispiel #10
0
 /// <include file='IAdbClient.xml' path='/IAdbClient/RemoveAllForwards/*'/>
 public void RemoveAllForwards(DeviceData device)
 {
     using (IAdbSocket socket = Factories.AdbSocketFactory(this.EndPoint))
     {
         socket.SendAdbRequest($"host-serial:{device.Serial}:killforward-all");
         var response = socket.ReadAdbResponse();
     }
 }
Beispiel #11
0
        /// <inheritdoc/>
        public void KillAdb()
        {
            using (IAdbSocket socket = this.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.
            }
        }
Beispiel #12
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();
            }
        }
Beispiel #13
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))
            {
                this.SetDevice(socket, 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);
                }
            }
        }
Beispiel #14
0
        /// <inheritdoc/>
        public async Task ExecuteRemoteCommandAsync(string command, DeviceData device, IShellOutputReceiver receiver, CancellationToken cancellationToken, int maxTimeToOutputResponse)
        {
            this.EnsureDevice(device);

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

                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 = 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();
                    }
                }
            }
        }
Beispiel #15
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))
            {
                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;
                        }
                    }
                }
            }
        }
Beispiel #16
0
        /// <summary>
        /// Initializes a new instance of the <see cref="DeviceMonitor"/> class.
        /// </summary>
        /// <param name="socket">
        /// The <see cref="IAdbSocket"/> that manages the connection with the adb server.
        /// </param>
        public DeviceMonitor(IAdbSocket socket)
        {
            if (socket == null)
            {
                throw new ArgumentNullException(nameof(socket));
            }

            this.Socket  = socket;
            this.devices = new List <DeviceData>();
            this.Devices = this.devices.AsReadOnly();
        }
Beispiel #17
0
        /// <summary>
        /// Initializes a new instance of the <see cref="DeviceMonitor"/> class.
        /// </summary>
        /// <param name="socket">
        /// The <see cref="IAdbSocket"/> that manages the connection with the adb server.
        /// </param>
        public DeviceMonitor(IAdbSocket socket)
        {
            if (socket == null)
            {
                throw new ArgumentNullException(nameof(socket));
            }

            this.Socket = socket;
            this.devices = new List<DeviceData>();
            this.Devices = this.devices.AsReadOnly();
        }
Beispiel #18
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();
            }
        }
Beispiel #19
0
        public void RemoveReverseForward(DeviceData device, string remote)
        {
            this.EnsureDevice(device);

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

                socket.SendAdbRequest($"reverse:killforward:{remote}");
                var response = socket.ReadAdbResponse();
            }
        }
Beispiel #20
0
        /// <summary>
        /// Initializes a new instance of the <see cref="DeviceMonitor"/> class.
        /// </summary>
        /// <param name="socket">
        /// The <see cref="IAdbSocket"/> that manages the connection with the adb server.
        /// </param>
        /// <param name="logger">
        /// The logger to use when logging.
        /// </param>
        public DeviceMonitor(IAdbSocket socket, ILogger <DeviceMonitor> logger = null)
        {
            if (socket == null)
            {
                throw new ArgumentNullException(nameof(socket));
            }

            this.Socket  = socket;
            this.devices = new List <DeviceData>();
            this.Devices = this.devices.AsReadOnly();
            this.logger  = logger ?? NullLogger <DeviceMonitor> .Instance;
        }
Beispiel #21
0
 public void Close()
 {
     if (Block != null)
     {
         Block.Complete();
     }
     _outputBlock.Complete();
     _inputBlock.Complete();
     LocalId  = 0;
     RemoteId = 0;
     _sock    = null;
 }
Beispiel #22
0
        public void RemoveAllReverseForwards(DeviceData device)
        {
            this.EnsureDevice(device);

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

                socket.SendAdbRequest($"reverse:killforward-all");
                var response = socket.ReadAdbResponse();
            }
        }
Beispiel #23
0
        public void Disconnect(DnsEndPoint endpoint)
        {
            if (endpoint == null)
            {
                throw new ArgumentNullException(nameof(endpoint));
            }

            using (IAdbSocket socket = this.adbSocketFactory(this.EndPoint))
            {
                socket.SendAdbRequest($"host:disconnect:{endpoint.Host}:{endpoint.Port}");
                var response = socket.ReadAdbResponse();
            }
        }
Beispiel #24
0
        /// <inheritdoc/>
        public List <DeviceData> GetDevices()
        {
            using (IAdbSocket socket = this.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());
            }
        }
Beispiel #25
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)));
            }
        }
Beispiel #26
0
 public async Task <IPropagatorBlock <byte[], byte[]> > ExecuteRemoteCommandAsyncBlock(string cmd, DeviceData d, CancellationToken ct, int maxTimeToOutputResponse, Encoding encoding)
 {
     this.EnsureDevice(d);
     using (IAdbSocket sock = this.GetSocket())
     {
         this.SetDevice(sock, d);
         uint streamId = 1;
         sock.SendAdbRequest($"shell:{cmd}");
         var ss     = sock.GetShellStream();
         var stream = new AdbLocalStream(sock, streamId, encoding, ct);
         //OpenStreams.Add(streamId, stream);
         return(stream.Block);
     }
 }
        /// <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;
                            }
                        }
                    }
            }
        }
        /// <inheritdoc/>
        public string 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();

                return(socket.ReadString());
            }
        }
Beispiel #29
0
        public override void ReadFrom(IAdbSocket socket)
        {
            this.Command = socket.ReadSyncResponse();

            var reply = new byte[4];

            socket.Read(reply);

            if (!BitConverter.IsLittleEndian)
            {
                Array.Reverse(reply);
            }

            // The first 4 bytes contain the length of the data packet
            this.Size = BitConverter.ToInt32(reply, 0);
        }
Beispiel #30
0
        public AdbStream(IAdbSocket sock, uint localId)
        {
            _sock        = sock;
            this.LocalId = localId;

            _outputBlock = new BufferBlock <byte[]>();
            _inputBlock  = new ActionBlock <byte[]>(bytes =>
            {
                var buff = Command.CreateWriteCommand(LocalId, RemoteId, bytes);
                OnWriting?.Invoke(this, EventArgs.Empty);
                if (RemoteId == 0)
                {
                    throw new Exception("Remote stream not established yet!");
                }
                _sock.Send(buff, buff.Length);
            });
            Block = DataflowBlock.Encapsulate(_inputBlock, _outputBlock);
        }
Beispiel #31
0
        public override void ReadFrom(IAdbSocket socket)
        {
            this.Command = socket.ReadSyncResponse();

            byte[] statResult = new byte[12];
            socket.Read(statResult);

            if (!BitConverter.IsLittleEndian)
            {
                Array.Reverse(statResult, 0, 4);
                Array.Reverse(statResult, 4, 4);
                Array.Reverse(statResult, 8, 4);
            }

            this.FileMode = (UnixFileMode)BitConverter.ToInt32(statResult, 0);
            this.Size     = BitConverter.ToInt32(statResult, 4);
            this.Time     = DateTimeHelper.Epoch.AddSeconds(BitConverter.ToInt32(statResult, 8)).ToLocalTime();
        }
Beispiel #32
0
 /// <summary>
 /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
 /// </summary>
 public void Dispose()
 {
     if (this.Socket != null)
     {
         this.Socket.Dispose();
         this.Socket = null;
     }
 }
Beispiel #33
0
        /// <inheritdoc/>
        public void SetDevice(IAdbSocket socket, DeviceData device)
        {
            // if the device is not null, then we first tell adb we're looking to talk
            // to a specific device
            if (device != null)
            {
                socket.SendAdbRequest($"host:transport:{device.Serial}");

                try
                {
                    var response = socket.ReadAdbResponse();
                }
                catch (AdbException e)
                {
                    if (string.Equals("device not found", e.AdbError, StringComparison.OrdinalIgnoreCase))
                    {
                        throw new DeviceNotFoundException(device.Serial);
                    }
                    else
                    {
                        throw;
                    }
                }
            }
        }
Beispiel #34
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SyncService"/> class.
        /// </summary>
        /// <param name="socket">
        /// A <see cref="IAdbSocket"/> that enables to connection with the
        /// adb server.
        /// </param>
        /// <param name="device">
        /// The device on which to interact with the files.
        /// </param>
        public SyncService(IAdbSocket socket, DeviceData device)
        {
            this.Socket = socket;
            this.Device = device;

            this.Open();
        }
Beispiel #35
0
 public void SetDevice(IAdbSocket socket, DeviceData device)
 {
     throw new NotImplementedException();
 }
Beispiel #36
0
        /// <summary>
        /// Stops the monitoring
        /// </summary>
        public void Dispose()
        {
            // Close the connection to adb.
            // This will also cause the socket to disconnect, and the
            // monitor thread to cancel out (because an ObjectDisposedException is thrown
            // on the GetString method and subsequently Socket.Connected = false and Socket = null).
            if (this.Socket != null)
            {
                this.Socket.Dispose();
                this.Socket = null;
            }

            if (this.monitorThread != null)
            {
                this.IsRunning = false;

                // Stop the thread. The tread will keep waiting for updated information from adb
                // eternally, so we need to forcefully abort it here.
                this.monitorThread.Abort();

                this.monitorThread = null;
            }
        }