/// <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); } }
/// <summary> /// Creates a new <see cref="FramebufferHeader"/> object based on a byte arra which contains the data. /// </summary> /// <param name="data"> /// The data that feeds the <see cref="FramebufferHeader"/> structure. /// </param> /// <returns> /// A new <see cref="FramebufferHeader"/> object. /// </returns> public static FramebufferHeader Read(byte[] data) { // as defined in https://android.googlesource.com/platform/system/core/+/master/adb/framebuffer_service.cpp FramebufferHeader header = default(FramebufferHeader); // Read the data from a MemoryStream so we can use the BinaryReader to process the data. using (MemoryStream stream = new MemoryStream(data)) using (BinaryReader reader = new BinaryReader(stream, Encoding.ASCII, leaveOpen: true)) { header.Version = reader.ReadUInt32(); header.Bpp = reader.ReadUInt32(); header.Size = reader.ReadUInt32(); header.Width = reader.ReadUInt32(); header.Height = reader.ReadUInt32(); header.Red = new ColorData() { Offset = reader.ReadUInt32(), Length = reader.ReadUInt32() }; header.Blue = new ColorData() { Offset = reader.ReadUInt32(), Length = reader.ReadUInt32() }; header.Green = new ColorData() { Offset = reader.ReadUInt32(), Length = reader.ReadUInt32() }; header.Alpha = new ColorData() { Offset = reader.ReadUInt32(), Length = reader.ReadUInt32() }; } return(header); }