diff --git a/adb_cli/src/commands/mod.rs b/adb_cli/src/commands/mod.rs index ec6b1d7..5de234f 100644 --- a/adb_cli/src/commands/mod.rs +++ b/adb_cli/src/commands/mod.rs @@ -7,5 +7,5 @@ mod usb; pub use emu::EmuCommand; pub use host::{HostCommand, MdnsCommand}; pub use local::LocalCommand; -pub use tcp::{TcpCommand, TcpCommands}; -pub use usb::{UsbCommand, UsbCommands}; +pub use tcp::TcpCommand; +pub use usb::{DeviceCommands, UsbCommand}; diff --git a/adb_cli/src/commands/tcp.rs b/adb_cli/src/commands/tcp.rs index 4eb5ac1..7411773 100644 --- a/adb_cli/src/commands/tcp.rs +++ b/adb_cli/src/commands/tcp.rs @@ -1,44 +1,11 @@ -use std::net::SocketAddr; -use std::path::PathBuf; - use clap::Parser; +use std::net::SocketAddr; -use crate::models::RebootTypeCommand; +use super::DeviceCommands; #[derive(Parser, Debug)] pub struct TcpCommand { pub address: SocketAddr, #[clap(subcommand)] - pub commands: TcpCommands, -} - -#[derive(Parser, Debug)] -pub enum TcpCommands { - /// Spawn an interactive shell or run a list of commands on the device - Shell { commands: Vec }, - /// Pull a file from device - Pull { source: String, destination: String }, - /// Push a file on device - Push { filename: String, path: String }, - /// Stat a file on device - Stat { path: String }, - /// Run an activity on device specified by the intent - Run { - /// The package whose activity is to be invoked - #[clap(short = 'p', long = "package")] - package: String, - /// The activity to be invoked itself, Usually it is MainActivity - #[clap(short = 'a', long = "activity")] - activity: String, - }, - /// Reboot the device - Reboot { - #[clap(subcommand)] - reboot_type: RebootTypeCommand, - }, - /// Install an APK on device - Install { - /// Path to APK file. Extension must be ".apk" - path: PathBuf, - }, + pub commands: DeviceCommands, } diff --git a/adb_cli/src/commands/usb.rs b/adb_cli/src/commands/usb.rs index cb21461..0be4304 100644 --- a/adb_cli/src/commands/usb.rs +++ b/adb_cli/src/commands/usb.rs @@ -21,11 +21,11 @@ pub struct UsbCommand { #[clap(short = 'k', long = "private-key")] pub path_to_private_key: Option, #[clap(subcommand)] - pub commands: UsbCommands, + pub commands: DeviceCommands, } #[derive(Parser, Debug)] -pub enum UsbCommands { +pub enum DeviceCommands { /// Spawn an interactive shell or run a list of commands on the device Shell { commands: Vec }, /// Pull a file from device @@ -53,4 +53,9 @@ pub enum UsbCommands { /// Path to APK file. Extension must be ".apk" path: PathBuf, }, + /// Dump framebuffer of device + Framebuffer { + /// Framebuffer image destination path + path: String, + }, } diff --git a/adb_cli/src/main.rs b/adb_cli/src/main.rs index 9e19249..8674856 100644 --- a/adb_cli/src/main.rs +++ b/adb_cli/src/main.rs @@ -12,7 +12,7 @@ use adb_client::{ }; use anyhow::{anyhow, Result}; use clap::Parser; -use commands::{EmuCommand, HostCommand, LocalCommand, MdnsCommand, TcpCommands, UsbCommands}; +use commands::{DeviceCommands, EmuCommand, HostCommand, LocalCommand, MdnsCommand}; use models::{Command, Opts}; use std::fs::File; use std::io::Write; @@ -226,7 +226,7 @@ fn main() -> Result<()> { }; match usb.commands { - UsbCommands::Shell { commands } => { + DeviceCommands::Shell { commands } => { if commands.is_empty() { // Need to duplicate some code here as ADBTermios [Drop] implementation resets terminal state. // Using a scope here would call drop() too early.. @@ -245,7 +245,7 @@ fn main() -> Result<()> { device.shell_command(commands, std::io::stdout())?; } } - UsbCommands::Pull { + DeviceCommands::Pull { source, destination, } => { @@ -253,34 +253,35 @@ fn main() -> Result<()> { device.pull(&source, &mut output)?; log::info!("Downloaded {source} as {destination}"); } - UsbCommands::Stat { path } => { + DeviceCommands::Stat { path } => { let stat_response = device.stat(&path)?; println!("{}", stat_response); } - UsbCommands::Reboot { reboot_type } => { + DeviceCommands::Reboot { reboot_type } => { log::info!("Reboots device in mode {:?}", reboot_type); device.reboot(reboot_type.into())? } - UsbCommands::Push { filename, path } => { + DeviceCommands::Push { filename, path } => { let mut input = File::open(Path::new(&filename))?; device.push(&mut input, &path)?; log::info!("Uploaded {filename} to {path}"); } - UsbCommands::Run { package, activity } => { + DeviceCommands::Run { package, activity } => { let output = device.run_activity(&package, &activity)?; std::io::stdout().write_all(&output)?; } - UsbCommands::Install { path } => { + DeviceCommands::Install { path } => { log::info!("Starting installation of APK {}...", path.display()); device.install(path)?; } + DeviceCommands::Framebuffer { path } => device.framebuffer(path)?, } } Command::Tcp(tcp) => { let mut device = ADBTcpDevice::new(tcp.address)?; match tcp.commands { - TcpCommands::Shell { commands } => { + DeviceCommands::Shell { commands } => { if commands.is_empty() { // Need to duplicate some code here as ADBTermios [Drop] implementation resets terminal state. // Using a scope here would call drop() too early.. @@ -299,7 +300,7 @@ fn main() -> Result<()> { device.shell_command(commands, std::io::stdout())?; } } - TcpCommands::Pull { + DeviceCommands::Pull { source, destination, } => { @@ -307,27 +308,28 @@ fn main() -> Result<()> { device.pull(&source, &mut output)?; log::info!("Downloaded {source} as {destination}"); } - TcpCommands::Stat { path } => { + DeviceCommands::Stat { path } => { let stat_response = device.stat(&path)?; println!("{}", stat_response); } - TcpCommands::Reboot { reboot_type } => { + DeviceCommands::Reboot { reboot_type } => { log::info!("Reboots device in mode {:?}", reboot_type); device.reboot(reboot_type.into())? } - TcpCommands::Push { filename, path } => { + DeviceCommands::Push { filename, path } => { let mut input = File::open(Path::new(&filename))?; device.push(&mut input, &path)?; log::info!("Uploaded {filename} to {path}"); } - TcpCommands::Run { package, activity } => { + DeviceCommands::Run { package, activity } => { let output = device.run_activity(&package, &activity)?; std::io::stdout().write_all(&output)?; } - TcpCommands::Install { path } => { + DeviceCommands::Install { path } => { log::info!("Starting installation of APK {}...", path.display()); device.install(path)?; } + DeviceCommands::Framebuffer { path } => device.framebuffer(path)?, } } Command::MdnsDiscovery => { diff --git a/adb_client/README.md b/adb_client/README.md index 6595ec1..f22ed46 100644 --- a/adb_client/README.md +++ b/adb_client/README.md @@ -15,6 +15,20 @@ Add `adb_client` crate as a dependency by simply adding it to your `Cargo.toml`: adb_client = "*" ``` +## Benchmarks + +Benchmarks run on `v2.0.6`, on a **Samsung S10 SM-G973F** device and an **Intel i7-1265U** CPU laptop + +### `ADBServerDevice` push vs `adb push` + +`ADBServerDevice` performs all operations by using adb server as a bridge. + +|File size|Sample size|`ADBServerDevice`|`adb`|Difference| +|:-------:|:---------:|:----------:|:---:|:-----:| +|10 MB|100|350,79 ms|356,30 ms|
-1,57 %
| +|500 MB|50|15,60 s|15,64 s|
-0,25 %
| +|1 GB|20|31,09 s|31,12 s|
-0,10 %
| + ## Examples ### Get available ADB devices @@ -84,7 +98,7 @@ let mut input = File::open(Path::new("/tmp/f")).expect("Cannot open file"); device.push(&mut input, "/data/local/tmp"); ``` -### (TCP) Get a shell from device +#### (TCP) Get a shell from device ```rust no_run use std::net::{SocketAddr, IpAddr, Ipv4Addr}; diff --git a/adb_client/src/adb_device_ext.rs b/adb_client/src/adb_device_ext.rs index 2d48fb1..220af3f 100644 --- a/adb_client/src/adb_device_ext.rs +++ b/adb_client/src/adb_device_ext.rs @@ -1,4 +1,4 @@ -use std::io::{Read, Write}; +use std::io::{Read, Seek, Write}; use std::path::Path; use crate::models::AdbStatResponse; @@ -43,4 +43,12 @@ pub trait ADBDeviceExt { /// Install an APK pointed to by `apk_path` on device. fn install>(&mut self, apk_path: P) -> Result<()>; + + /// Dump framebuffer of this device into given path + fn framebuffer>(&mut self, path: P) -> Result<()>; + + /// Dump framebuffer of this device and return corresponding bytes. + /// + /// Output data format is currently only `PNG`. + fn framebuffer_bytes(&mut self, writer: W) -> Result<()>; } diff --git a/adb_client/src/device/adb_message_device.rs b/adb_client/src/device/adb_message_device.rs index 4df5f5f..ef7b3ce 100644 --- a/adb_client/src/device/adb_message_device.rs +++ b/adb_client/src/device/adb_message_device.rs @@ -11,12 +11,18 @@ use super::{models::MessageSubcommand, ADBTransportMessage, MessageCommand}; #[derive(Debug)] pub struct ADBMessageDevice { transport: T, + local_id: Option, + remote_id: Option, } impl ADBMessageDevice { /// Instantiate a new [`ADBMessageTransport`] pub fn new(transport: T) -> Self { - Self { transport } + Self { + transport, + local_id: None, + remote_id: None, + } } pub(crate) fn get_transport(&mut self) -> &T { @@ -28,17 +34,13 @@ impl ADBMessageDevice { } /// Receive a message and acknowledge it by replying with an `OKAY` command - pub(crate) fn recv_and_reply_okay( - &mut self, - local_id: u32, - remote_id: u32, - ) -> Result { + pub(crate) fn recv_and_reply_okay(&mut self) -> Result { let message = self.transport.read_message()?; self.transport.write_message(ADBTransportMessage::new( MessageCommand::Okay, - local_id, - remote_id, - "".into(), + self.get_local_id()?, + self.get_remote_id()?, + &[], ))?; Ok(message) } @@ -62,15 +64,11 @@ impl ADBMessageDevice { pub(crate) fn recv_file( &mut self, - local_id: u32, - remote_id: u32, mut output: W, ) -> std::result::Result<(), RustADBError> { let mut len: Option = None; loop { - let payload = self - .recv_and_reply_okay(local_id, remote_id)? - .into_payload(); + let payload = self.recv_and_reply_okay()?.into_payload(); let mut rdr = Cursor::new(&payload); while rdr.position() != payload.len() as u64 { match len.take() { @@ -119,7 +117,7 @@ impl ADBMessageDevice { MessageCommand::Write, local_id, remote_id, - serialized_message, + &serialized_message, ); self.send_and_expect_okay(message)?; @@ -139,7 +137,7 @@ impl ADBMessageDevice { MessageCommand::Write, local_id, remote_id, - serialized_message, + &serialized_message, ); self.send_and_expect_okay(message)?; @@ -167,7 +165,7 @@ impl ADBMessageDevice { MessageCommand::Write, local_id, remote_id, - serialized_message, + &serialized_message, ); self.send_and_expect_okay(message)?; @@ -179,41 +177,25 @@ impl ADBMessageDevice { } } - pub(crate) fn begin_synchronization(&mut self) -> Result<(u32, u32)> { - let sync_directive = "sync:\0"; - - let mut rng = rand::thread_rng(); - let message = ADBTransportMessage::new( - MessageCommand::Open, - rng.gen(), /* Our 'local-id' */ - 0, - sync_directive.into(), - ); - let message = self.send_and_expect_okay(message)?; - let local_id = message.header().arg1(); - let remote_id = message.header().arg0(); - Ok((local_id, remote_id)) + pub(crate) fn begin_synchronization(&mut self) -> Result<()> { + self.open_session(b"sync:\0")?; + Ok(()) } - pub(crate) fn stat_with_explicit_ids( - &mut self, - remote_path: &str, - local_id: u32, - remote_id: u32, - ) -> Result { + pub(crate) fn stat_with_explicit_ids(&mut self, remote_path: &str) -> Result { let stat_buffer = MessageSubcommand::Stat.with_arg(remote_path.len() as u32); let message = ADBTransportMessage::new( MessageCommand::Write, - local_id, - remote_id, - bincode::serialize(&stat_buffer).map_err(|_e| RustADBError::ConversionError)?, + self.get_local_id()?, + self.get_remote_id()?, + &bincode::serialize(&stat_buffer).map_err(|_e| RustADBError::ConversionError)?, ); self.send_and_expect_okay(message)?; self.send_and_expect_okay(ADBTransportMessage::new( MessageCommand::Write, - local_id, - remote_id, - remote_path.into(), + self.get_local_id()?, + self.get_remote_id()?, + remote_path.as_bytes(), ))?; let response = self.transport.read_message()?; // Skip first 4 bytes as this is the literal "STAT". @@ -222,15 +204,46 @@ impl ADBMessageDevice { .map_err(|_e| RustADBError::ConversionError) } - pub(crate) fn end_transaction(&mut self, local_id: u32, remote_id: u32) -> Result<()> { + pub(crate) fn end_transaction(&mut self) -> Result<()> { let quit_buffer = MessageSubcommand::Quit.with_arg(0u32); self.send_and_expect_okay(ADBTransportMessage::new( MessageCommand::Write, - local_id, - remote_id, - bincode::serialize(&quit_buffer).map_err(|_e| RustADBError::ConversionError)?, + self.get_local_id()?, + self.get_remote_id()?, + &bincode::serialize(&quit_buffer).map_err(|_e| RustADBError::ConversionError)?, ))?; let _discard_close = self.transport.read_message()?; Ok(()) } + + pub(crate) fn open_session(&mut self, data: &[u8]) -> Result { + let mut rng = rand::thread_rng(); + + let message = ADBTransportMessage::new( + MessageCommand::Open, + rng.gen(), // Our 'local-id' + 0, + data, + ); + self.get_transport_mut().write_message(message)?; + + let response = self.get_transport_mut().read_message()?; + + self.local_id = Some(response.header().arg1()); + self.remote_id = Some(response.header().arg0()); + + Ok(response) + } + + pub(crate) fn get_local_id(&self) -> Result { + self.local_id.ok_or(RustADBError::ADBRequestFailed( + "connection not opened, no local_id".into(), + )) + } + + pub(crate) fn get_remote_id(&self) -> Result { + self.remote_id.ok_or(RustADBError::ADBRequestFailed( + "connection not opened, no remote_id".into(), + )) + } } diff --git a/adb_client/src/device/adb_message_device_commands.rs b/adb_client/src/device/adb_message_device_commands.rs index 3008e3c..7bcf472 100644 --- a/adb_client/src/device/adb_message_device_commands.rs +++ b/adb_client/src/device/adb_message_device_commands.rs @@ -35,4 +35,12 @@ impl ADBDeviceExt for ADBMessageDevice { fn install>(&mut self, apk_path: P) -> Result<()> { self.install(apk_path) } + + fn framebuffer>(&mut self, path: P) -> Result<()> { + self.framebuffer(path) + } + + fn framebuffer_bytes(&mut self, writer: W) -> Result<()> { + self.framebuffer_bytes(writer) + } } diff --git a/adb_client/src/device/adb_tcp_device.rs b/adb_client/src/device/adb_tcp_device.rs index 4932221..577c23b 100644 --- a/adb_client/src/device/adb_tcp_device.rs +++ b/adb_client/src/device/adb_tcp_device.rs @@ -32,9 +32,7 @@ impl ADBTcpDevice { MessageCommand::Cnxn, 0x01000000, 1048576, - format!("host::{}\0", env!("CARGO_PKG_NAME")) - .as_bytes() - .to_vec(), + format!("host::{}\0", env!("CARGO_PKG_NAME")).as_bytes(), ); self.get_transport_mut().write_message(message)?; @@ -49,7 +47,7 @@ impl ADBTcpDevice { ))); }; - let message = ADBTransportMessage::new(MessageCommand::Stls, 1, 0, vec![]); + let message = ADBTransportMessage::new(MessageCommand::Stls, 1, 0, &[]); self.get_transport_mut().write_message(message)?; @@ -61,12 +59,14 @@ impl ADBTcpDevice { Ok(()) } + #[inline] fn get_transport_mut(&mut self) -> &mut TcpTransport { self.inner.get_transport_mut() } } impl ADBDeviceExt for ADBTcpDevice { + #[inline] fn shell_command( &mut self, command: impl IntoIterator, @@ -75,6 +75,7 @@ impl ADBDeviceExt for ADBTcpDevice { self.inner.shell_command(command, output) } + #[inline] fn shell( &mut self, reader: R, @@ -83,25 +84,40 @@ impl ADBDeviceExt for ADBTcpDevice { self.inner.shell(reader, writer) } + #[inline] fn stat(&mut self, remote_path: &str) -> Result { self.inner.stat(remote_path) } + #[inline] fn pull, W: std::io::Write>(&mut self, source: A, output: W) -> Result<()> { self.inner.pull(source, output) } + #[inline] fn push>(&mut self, stream: R, path: A) -> Result<()> { self.inner.push(stream, path) } + #[inline] fn reboot(&mut self, reboot_type: crate::RebootType) -> Result<()> { self.inner.reboot(reboot_type) } + #[inline] fn install>(&mut self, apk_path: P) -> Result<()> { self.inner.install(apk_path) } + + #[inline] + fn framebuffer>(&mut self, path: P) -> Result<()> { + self.inner.framebuffer(path) + } + + #[inline] + fn framebuffer_bytes(&mut self, writer: W) -> Result<()> { + self.inner.framebuffer_bytes(writer) + } } impl Drop for ADBTcpDevice { diff --git a/adb_client/src/device/adb_transport_message.rs b/adb_client/src/device/adb_transport_message.rs index 921f939..006a3cd 100644 --- a/adb_client/src/device/adb_transport_message.rs +++ b/adb_client/src/device/adb_transport_message.rs @@ -72,10 +72,10 @@ impl ADBTransportMessageHeader { } impl ADBTransportMessage { - pub fn new(command: MessageCommand, arg0: u32, arg1: u32, data: Vec) -> Self { + pub fn new(command: MessageCommand, arg0: u32, arg1: u32, data: &[u8]) -> Self { Self { - header: ADBTransportMessageHeader::new(command, arg0, arg1, &data), - payload: data, + header: ADBTransportMessageHeader::new(command, arg0, arg1, data), + payload: data.to_vec(), } } diff --git a/adb_client/src/device/adb_usb_device.rs b/adb_client/src/device/adb_usb_device.rs index 2376e0b..c2319b9 100644 --- a/adb_client/src/device/adb_usb_device.rs +++ b/adb_client/src/device/adb_usb_device.rs @@ -173,9 +173,7 @@ impl ADBUSBDevice { MessageCommand::Cnxn, 0x01000000, 1048576, - format!("host::{}\0", env!("CARGO_PKG_NAME")) - .as_bytes() - .to_vec(), + format!("host::{}\0", env!("CARGO_PKG_NAME")).as_bytes(), ); self.get_transport_mut().write_message(message)?; @@ -202,7 +200,7 @@ impl ADBUSBDevice { let sign = self.private_key.sign(auth_message.into_payload())?; - let message = ADBTransportMessage::new(MessageCommand::Auth, AUTH_SIGNATURE, 0, sign); + let message = ADBTransportMessage::new(MessageCommand::Auth, AUTH_SIGNATURE, 0, &sign); self.get_transport_mut().write_message(message)?; @@ -219,7 +217,7 @@ impl ADBUSBDevice { let mut pubkey = self.private_key.android_pubkey_encode()?.into_bytes(); pubkey.push(b'\0'); - let message = ADBTransportMessage::new(MessageCommand::Auth, AUTH_RSAPUBLICKEY, 0, pubkey); + let message = ADBTransportMessage::new(MessageCommand::Auth, AUTH_RSAPUBLICKEY, 0, &pubkey); self.get_transport_mut().write_message(message)?; @@ -243,12 +241,14 @@ impl ADBUSBDevice { Ok(()) } + #[inline] fn get_transport_mut(&mut self) -> &mut USBTransport { self.inner.get_transport_mut() } } impl ADBDeviceExt for ADBUSBDevice { + #[inline] fn shell_command( &mut self, command: impl IntoIterator, @@ -257,6 +257,7 @@ impl ADBDeviceExt for ADBUSBDevice { self.inner.shell_command(command, output) } + #[inline] fn shell( &mut self, reader: R, @@ -265,25 +266,40 @@ impl ADBDeviceExt for ADBUSBDevice { self.inner.shell(reader, writer) } + #[inline] fn stat(&mut self, remote_path: &str) -> Result { self.inner.stat(remote_path) } + #[inline] fn pull, W: std::io::Write>(&mut self, source: A, output: W) -> Result<()> { self.inner.pull(source, output) } + #[inline] fn push>(&mut self, stream: R, path: A) -> Result<()> { self.inner.push(stream, path) } + #[inline] fn reboot(&mut self, reboot_type: crate::RebootType) -> Result<()> { self.inner.reboot(reboot_type) } + #[inline] fn install>(&mut self, apk_path: P) -> Result<()> { self.inner.install(apk_path) } + + #[inline] + fn framebuffer>(&mut self, path: P) -> Result<()> { + self.inner.framebuffer(path) + } + + #[inline] + fn framebuffer_bytes(&mut self, writer: W) -> Result<()> { + self.inner.framebuffer_bytes(writer) + } } impl Drop for ADBUSBDevice { diff --git a/adb_client/src/device/commands/framebuffer.rs b/adb_client/src/device/commands/framebuffer.rs new file mode 100644 index 0000000..bbf4ce8 --- /dev/null +++ b/adb_client/src/device/commands/framebuffer.rs @@ -0,0 +1,111 @@ +use std::io::{Cursor, Read, Write}; + +use byteorder::{LittleEndian, ReadBytesExt}; +use image::{ImageBuffer, ImageFormat, Rgba}; + +use crate::{ + device::{adb_message_device::ADBMessageDevice, MessageCommand}, + models::{FrameBufferInfoV1, FrameBufferInfoV2}, + ADBMessageTransport, Result, RustADBError, +}; + +impl ADBMessageDevice { + pub fn framebuffer>(&mut self, path: P) -> Result<()> { + let img = self.framebuffer_inner()?; + Ok(img.save(path.as_ref())?) + } + + pub fn framebuffer_bytes(&mut self, mut writer: W) -> Result<()> { + let img = self.framebuffer_inner()?; + Ok(img.write_to(&mut writer, ImageFormat::Png)?) + } + + fn framebuffer_inner(&mut self) -> Result, Vec>> { + self.open_session(b"framebuffer:\0")?; + + let response = self.recv_and_reply_okay()?; + + let mut payload_cursor = Cursor::new(response.payload()); + + let version = payload_cursor.read_u32::()?; + + let img = match version { + // RGBA_8888 + 1 => { + let mut buf = [0u8; std::mem::size_of::()]; + + payload_cursor.read_exact(&mut buf)?; + + let framebuffer_info: FrameBufferInfoV1 = buf.try_into()?; + + let mut framebuffer_data = Vec::new(); + payload_cursor.read_to_end(&mut framebuffer_data)?; + + loop { + if framebuffer_data.len() as u32 == framebuffer_info.size { + break; + } + + let response = self.recv_and_reply_okay()?; + + framebuffer_data.extend_from_slice(&response.into_payload()); + + log::debug!( + "received framebuffer data. new size {}", + framebuffer_data.len() + ); + } + + ImageBuffer::, Vec>::from_vec( + framebuffer_info.width, + framebuffer_info.height, + framebuffer_data, + ) + .ok_or_else(|| RustADBError::FramebufferConversionError)? + } + // RGBX_8888 + 2 => { + let mut buf = [0u8; std::mem::size_of::()]; + + payload_cursor.read_exact(&mut buf)?; + + let framebuffer_info: FrameBufferInfoV2 = buf.try_into()?; + + let mut framebuffer_data = Vec::new(); + payload_cursor.read_to_end(&mut framebuffer_data)?; + + loop { + if framebuffer_data.len() as u32 == framebuffer_info.size { + break; + } + + let response = self.recv_and_reply_okay()?; + + framebuffer_data.extend_from_slice(&response.into_payload()); + + log::debug!( + "received framebuffer data. new size {}", + framebuffer_data.len() + ); + } + + ImageBuffer::, Vec>::from_vec( + framebuffer_info.width, + framebuffer_info.height, + framebuffer_data, + ) + .ok_or_else(|| RustADBError::FramebufferConversionError)? + } + v => return Err(RustADBError::UnimplementedFramebufferImageVersion(v)), + }; + + let message = self.get_transport_mut().read_message()?; + match message.header().command() { + MessageCommand::Clse => Ok(img), + c => Err(RustADBError::ADBRequestFailed(format!( + "Wrong command received {}", + c + ))), + } + } +} diff --git a/adb_client/src/device/commands/install.rs b/adb_client/src/device/commands/install.rs index 592dea7..b2b53d1 100644 --- a/adb_client/src/device/commands/install.rs +++ b/adb_client/src/device/commands/install.rs @@ -3,9 +3,7 @@ use std::fs::File; use rand::Rng; use crate::{ - device::{ - adb_message_device::ADBMessageDevice, ADBTransportMessage, MessageCommand, MessageWriter, - }, + device::{adb_message_device::ADBMessageDevice, MessageWriter}, utils::check_extension_is_apk, ADBMessageTransport, Result, }; @@ -22,22 +20,11 @@ impl ADBMessageDevice { let local_id = rng.gen(); - let message = ADBTransportMessage::new( - MessageCommand::Open, - local_id, - 0, - format!("exec:cmd package 'install' -S {}\0", file_size) - .as_bytes() - .to_vec(), - ); - self.get_transport_mut().write_message(message)?; - - let response = self.get_transport_mut().read_message()?; - let remote_id = response.header().arg0(); + self.open_session(format!("exec:cmd package 'install' -S {}\0", file_size).as_bytes())?; let transport = self.get_transport().clone(); - let mut writer = MessageWriter::new(transport, local_id, remote_id); + let mut writer = MessageWriter::new(transport, local_id, self.get_remote_id()?); std::io::copy(&mut apk_file, &mut writer)?; diff --git a/adb_client/src/device/commands/mod.rs b/adb_client/src/device/commands/mod.rs index d474563..875f710 100644 --- a/adb_client/src/device/commands/mod.rs +++ b/adb_client/src/device/commands/mod.rs @@ -1,3 +1,4 @@ +mod framebuffer; mod install; mod pull; mod push; diff --git a/adb_client/src/device/commands/pull.rs b/adb_client/src/device/commands/pull.rs index 68c0c7c..7f672db 100644 --- a/adb_client/src/device/commands/pull.rs +++ b/adb_client/src/device/commands/pull.rs @@ -10,10 +10,10 @@ use crate::{ impl ADBMessageDevice { pub(crate) fn pull, W: Write>(&mut self, source: A, output: W) -> Result<()> { - let (local_id, remote_id) = self.begin_synchronization()?; + self.begin_synchronization()?; let source = source.as_ref(); - let adb_stat_response = self.stat_with_explicit_ids(source, local_id, remote_id)?; + let adb_stat_response = self.stat_with_explicit_ids(source)?; if adb_stat_response.file_perm == 0 { return Err(RustADBError::UnknownResponseType( @@ -21,8 +21,11 @@ impl ADBMessageDevice { )); } + let local_id = self.get_local_id()?; + let remote_id = self.get_remote_id()?; + self.get_transport_mut().write_message_with_timeout( - ADBTransportMessage::new(MessageCommand::Okay, local_id, remote_id, "".into()), + ADBTransportMessage::new(MessageCommand::Okay, local_id, remote_id, &[]), std::time::Duration::from_secs(4), )?; @@ -31,19 +34,19 @@ impl ADBMessageDevice { bincode::serialize(&recv_buffer).map_err(|_e| RustADBError::ConversionError)?; self.send_and_expect_okay(ADBTransportMessage::new( MessageCommand::Write, - local_id, - remote_id, - recv_buffer, + self.get_local_id()?, + self.get_remote_id()?, + &recv_buffer, ))?; self.send_and_expect_okay(ADBTransportMessage::new( MessageCommand::Write, - local_id, - remote_id, - source.into(), + self.get_local_id()?, + self.get_remote_id()?, + source.as_bytes(), ))?; - self.recv_file(local_id, remote_id, output)?; - self.end_transaction(local_id, remote_id)?; + self.recv_file(output)?; + self.end_transaction()?; Ok(()) } } diff --git a/adb_client/src/device/commands/push.rs b/adb_client/src/device/commands/push.rs index fd6337f..5019f9c 100644 --- a/adb_client/src/device/commands/push.rs +++ b/adb_client/src/device/commands/push.rs @@ -10,7 +10,7 @@ use crate::{ impl ADBMessageDevice { pub(crate) fn push>(&mut self, stream: R, path: A) -> Result<()> { - let (local_id, remote_id) = self.begin_synchronization()?; + self.begin_synchronization()?; let path_header = format!("{},0777", path.as_ref()); @@ -21,14 +21,14 @@ impl ADBMessageDevice { self.send_and_expect_okay(ADBTransportMessage::new( MessageCommand::Write, - local_id, - remote_id, - send_buffer, + self.get_local_id()?, + self.get_remote_id()?, + &send_buffer, ))?; - self.push_file(local_id, remote_id, stream)?; + self.push_file(self.get_local_id()?, self.get_remote_id()?, stream)?; - self.end_transaction(local_id, remote_id)?; + self.end_transaction()?; Ok(()) } diff --git a/adb_client/src/device/commands/reboot.rs b/adb_client/src/device/commands/reboot.rs index 0d2d3ec..4bab219 100644 --- a/adb_client/src/device/commands/reboot.rs +++ b/adb_client/src/device/commands/reboot.rs @@ -1,21 +1,11 @@ -use rand::Rng; - use crate::{ - device::{adb_message_device::ADBMessageDevice, ADBTransportMessage, MessageCommand}, + device::{adb_message_device::ADBMessageDevice, MessageCommand}, ADBMessageTransport, RebootType, Result, RustADBError, }; impl ADBMessageDevice { pub(crate) fn reboot(&mut self, reboot_type: RebootType) -> Result<()> { - let mut rng = rand::thread_rng(); - - let message = ADBTransportMessage::new( - MessageCommand::Open, - rng.gen(), // Our 'local-id' - 0, - format!("reboot:{}\0", reboot_type).as_bytes().to_vec(), - ); - self.get_transport_mut().write_message(message)?; + self.open_session(format!("reboot:{}\0", reboot_type).as_bytes())?; let message = self.get_transport_mut().read_message()?; diff --git a/adb_client/src/device/commands/shell.rs b/adb_client/src/device/commands/shell.rs index 98bc40c..fce13b2 100644 --- a/adb_client/src/device/commands/shell.rs +++ b/adb_client/src/device/commands/shell.rs @@ -1,5 +1,4 @@ -use rand::Rng; -use std::io::{Read, Write}; +use std::io::{ErrorKind, Read, Write}; use crate::device::ShellMessageWriter; use crate::Result; @@ -9,16 +8,13 @@ use crate::{ }; impl ADBMessageDevice { - /// Runs 'command' in a shell on the device, and write its output and error streams into [`output`]. + /// Runs 'command' in a shell on the device, and write its output and error streams into output. pub(crate) fn shell_command( &mut self, command: impl IntoIterator, mut output: W, ) -> Result<()> { - let message = ADBTransportMessage::new( - MessageCommand::Open, - 1, - 0, + let response = self.open_session( format!( "shell:{}\0", command @@ -27,12 +23,9 @@ impl ADBMessageDevice { .collect::>() .join(" "), ) - .as_bytes() - .to_vec(), - ); - self.get_transport_mut().write_message(message)?; + .as_bytes(), + )?; - let response = self.get_transport_mut().read_message()?; if response.header().command() != MessageCommand::Okay { return Err(RustADBError::ADBRequestFailed(format!( "wrong command {}", @@ -60,21 +53,13 @@ impl ADBMessageDevice { mut reader: R, mut writer: W, ) -> Result<()> { - let sync_directive = "shell:\0"; - - let mut rng = rand::thread_rng(); - let message = ADBTransportMessage::new( - MessageCommand::Open, - rng.gen(), /* Our 'local-id' */ - 0, - sync_directive.into(), - ); - let message = self.send_and_expect_okay(message)?; - let local_id = message.header().arg1(); - let remote_id = message.header().arg0(); + self.open_session(b"shell:\0")?; let mut transport = self.get_transport().clone(); + let local_id = self.get_local_id()?; + let remote_id = self.get_remote_id()?; + // Reading thread, reads response from adbd std::thread::spawn(move || -> Result<()> { loop { @@ -82,17 +67,17 @@ impl ADBMessageDevice { // Acknowledge for more data let response = - ADBTransportMessage::new(MessageCommand::Okay, local_id, remote_id, vec![]); + ADBTransportMessage::new(MessageCommand::Okay, local_id, remote_id, &[]); transport.write_message(response)?; match message.header().command() { - MessageCommand::Write => {} + MessageCommand::Write => { + writer.write_all(&message.into_payload())?; + writer.flush()?; + } MessageCommand::Okay => continue, _ => return Err(RustADBError::ADBShellNotSupported), } - - writer.write_all(&message.into_payload())?; - writer.flush()?; } }); @@ -102,7 +87,7 @@ impl ADBMessageDevice { // Read from given reader (that could be stdin e.g), and write content to device adbd if let Err(e) = std::io::copy(&mut reader, &mut shell_writer) { match e.kind() { - std::io::ErrorKind::BrokenPipe => return Ok(()), + ErrorKind::BrokenPipe => return Ok(()), _ => return Err(RustADBError::IOError(e)), } } diff --git a/adb_client/src/device/commands/stat.rs b/adb_client/src/device/commands/stat.rs index 0cd6a57..c7a45ec 100644 --- a/adb_client/src/device/commands/stat.rs +++ b/adb_client/src/device/commands/stat.rs @@ -4,9 +4,9 @@ use crate::{ impl ADBMessageDevice { pub(crate) fn stat(&mut self, remote_path: &str) -> Result { - let (local_id, remote_id) = self.begin_synchronization()?; - let adb_stat_response = self.stat_with_explicit_ids(remote_path, local_id, remote_id)?; - self.end_transaction(local_id, remote_id)?; + self.begin_synchronization()?; + let adb_stat_response = self.stat_with_explicit_ids(remote_path)?; + self.end_transaction()?; Ok(adb_stat_response) } } diff --git a/adb_client/src/device/message_writer.rs b/adb_client/src/device/message_writer.rs index f7a554b..b17b9b4 100644 --- a/adb_client/src/device/message_writer.rs +++ b/adb_client/src/device/message_writer.rs @@ -25,12 +25,8 @@ impl MessageWriter { impl Write for MessageWriter { fn write(&mut self, buf: &[u8]) -> std::io::Result { - let message = ADBTransportMessage::new( - MessageCommand::Write, - self.local_id, - self.remote_id, - buf.to_vec(), - ); + let message = + ADBTransportMessage::new(MessageCommand::Write, self.local_id, self.remote_id, buf); self.transport .write_message(message) .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?; diff --git a/adb_client/src/device/models/message_commands.rs b/adb_client/src/device/models/message_commands.rs index de3ad94..ff3918c 100644 --- a/adb_client/src/device/models/message_commands.rs +++ b/adb_client/src/device/models/message_commands.rs @@ -6,18 +6,17 @@ use std::fmt::Display; #[repr(u32)] pub enum MessageCommand { /// Connect to a device - Cnxn = 0x4e584e43, + Cnxn = 0x4E584E43, /// Close connection to a device - Clse = 0x45534c43, + Clse = 0x45534C43, /// Device ask for authentication Auth = 0x48545541, /// Open a data connection - Open = 0x4e45504f, + Open = 0x4E45504F, /// Write data to connection Write = 0x45545257, /// Server understood the message - Okay = 0x59414b4f, - // Sync 0x434e5953 + Okay = 0x59414B4F, /// Start a connection using TLS Stls = 0x534C5453, } @@ -29,10 +28,10 @@ pub enum MessageSubcommand { Send = 0x444E4553, Recv = 0x56434552, Quit = 0x54495551, - Fail = 0x4c494146, - Done = 0x454e4f44, + Fail = 0x4C494146, + Done = 0x454E4F44, Data = 0x41544144, - List = 0x5453494c, + List = 0x5453494C, } #[derive(Debug, Serialize, Deserialize)] diff --git a/adb_client/src/device/shell_message_writer.rs b/adb_client/src/device/shell_message_writer.rs index 07a9358..e387624 100644 --- a/adb_client/src/device/shell_message_writer.rs +++ b/adb_client/src/device/shell_message_writer.rs @@ -23,12 +23,8 @@ impl ShellMessageWriter { impl Write for ShellMessageWriter { fn write(&mut self, buf: &[u8]) -> std::io::Result { - let message = ADBTransportMessage::new( - MessageCommand::Write, - self.local_id, - self.remote_id, - buf.to_vec(), - ); + let message = + ADBTransportMessage::new(MessageCommand::Write, self.local_id, self.remote_id, buf); self.transport .write_message(message) .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?; diff --git a/adb_client/src/models/framebuffer_info.rs b/adb_client/src/models/framebuffer_info.rs new file mode 100644 index 0000000..6fb0aef --- /dev/null +++ b/adb_client/src/models/framebuffer_info.rs @@ -0,0 +1,97 @@ +use std::{iter::Map, slice::ChunksExact}; + +use byteorder::{ByteOrder, LittleEndian}; + +use crate::{Result, RustADBError}; + +type U32ChunkIter<'a> = Map, fn(&[u8]) -> Result>; + +fn read_next(chunks: &mut U32ChunkIter) -> Result { + chunks + .next() + .ok_or(RustADBError::FramebufferConversionError)? +} + +#[derive(Debug)] +pub(crate) struct FrameBufferInfoV1 { + pub _bpp: u32, + pub size: u32, + pub width: u32, + pub height: u32, + pub _red_offset: u32, + pub _red_length: u32, + pub _blue_offset: u32, + pub _blue_length: u32, + pub _green_offset: u32, + pub _green_length: u32, + pub _alpha_offset: u32, + pub _alpha_length: u32, +} + +impl TryFrom<[u8; std::mem::size_of::()]> for FrameBufferInfoV1 { + type Error = RustADBError; + + fn try_from( + value: [u8; std::mem::size_of::()], + ) -> std::result::Result { + let mut chunks: U32ChunkIter = value.chunks_exact(4).map(|v| Ok(LittleEndian::read_u32(v))); + + Ok(Self { + _bpp: read_next(&mut chunks)?, + size: read_next(&mut chunks)?, + width: read_next(&mut chunks)?, + height: read_next(&mut chunks)?, + _red_offset: read_next(&mut chunks)?, + _red_length: read_next(&mut chunks)?, + _blue_offset: read_next(&mut chunks)?, + _blue_length: read_next(&mut chunks)?, + _green_offset: read_next(&mut chunks)?, + _green_length: read_next(&mut chunks)?, + _alpha_offset: read_next(&mut chunks)?, + _alpha_length: read_next(&mut chunks)?, + }) + } +} + +#[derive(Debug)] +pub(crate) struct FrameBufferInfoV2 { + pub _bpp: u32, + pub _color_space: u32, + pub size: u32, + pub width: u32, + pub height: u32, + pub _red_offset: u32, + pub _red_length: u32, + pub _blue_offset: u32, + pub _blue_length: u32, + pub _green_offset: u32, + pub _green_length: u32, + pub _alpha_offset: u32, + pub _alpha_length: u32, +} + +impl TryFrom<[u8; std::mem::size_of::()]> for FrameBufferInfoV2 { + type Error = RustADBError; + + fn try_from( + value: [u8; std::mem::size_of::()], + ) -> std::result::Result { + let mut chunks: U32ChunkIter = value.chunks_exact(4).map(|v| Ok(LittleEndian::read_u32(v))); + + Ok(Self { + _bpp: read_next(&mut chunks)?, + _color_space: read_next(&mut chunks)?, + size: read_next(&mut chunks)?, + width: read_next(&mut chunks)?, + height: read_next(&mut chunks)?, + _red_offset: read_next(&mut chunks)?, + _red_length: read_next(&mut chunks)?, + _blue_offset: read_next(&mut chunks)?, + _blue_length: read_next(&mut chunks)?, + _green_offset: read_next(&mut chunks)?, + _green_length: read_next(&mut chunks)?, + _alpha_offset: read_next(&mut chunks)?, + _alpha_length: read_next(&mut chunks)?, + }) + } +} diff --git a/adb_client/src/models/mod.rs b/adb_client/src/models/mod.rs index 305ea87..be0ca74 100644 --- a/adb_client/src/models/mod.rs +++ b/adb_client/src/models/mod.rs @@ -6,6 +6,7 @@ mod adb_version; mod device_long; mod device_short; mod device_state; +mod framebuffer_info; mod host_features; mod mdns_services; mod reboot_type; @@ -20,6 +21,7 @@ pub use adb_version::AdbVersion; pub use device_long::DeviceLong; pub use device_short::DeviceShort; pub use device_state::DeviceState; +pub(crate) use framebuffer_info::{FrameBufferInfoV1, FrameBufferInfoV2}; pub use host_features::HostFeatures; pub use mdns_services::MDNSServices; pub use reboot_type::RebootType; diff --git a/adb_client/src/server_device/adb_server_device_commands.rs b/adb_client/src/server_device/adb_server_device_commands.rs index 3882cbc..1edc60e 100644 --- a/adb_client/src/server_device/adb_server_device_commands.rs +++ b/adb_client/src/server_device/adb_server_device_commands.rs @@ -130,4 +130,12 @@ impl ADBDeviceExt for ADBServerDevice { fn install>(&mut self, apk_path: P) -> Result<()> { self.install(apk_path) } + + fn framebuffer>(&mut self, path: P) -> Result<()> { + self.framebuffer(path) + } + + fn framebuffer_bytes(&mut self, writer: W) -> Result<()> { + self.framebuffer_bytes(writer) + } } diff --git a/adb_client/src/server_device/commands/framebuffer.rs b/adb_client/src/server_device/commands/framebuffer.rs index 706c663..d3b6035 100644 --- a/adb_client/src/server_device/commands/framebuffer.rs +++ b/adb_client/src/server_device/commands/framebuffer.rs @@ -1,111 +1,20 @@ use std::{ io::{Read, Seek, Write}, - iter::Map, path::Path, - slice::ChunksExact, }; use byteorder::{LittleEndian, ReadBytesExt}; use image::{ImageBuffer, ImageFormat, Rgba}; -use crate::{models::AdbServerCommand, utils, ADBServerDevice, Result, RustADBError}; - -type U32ChunkIter<'a> = Map, fn(&[u8]) -> Result>; - -fn read_next(chunks: &mut U32ChunkIter) -> Result { - chunks - .next() - .ok_or(RustADBError::FramebufferConversionError)? -} - -#[derive(Debug)] -struct FrameBufferInfoV1 { - pub _bpp: u32, - pub size: u32, - pub width: u32, - pub height: u32, - pub _red_offset: u32, - pub _red_length: u32, - pub _blue_offset: u32, - pub _blue_length: u32, - pub _green_offset: u32, - pub _green_length: u32, - pub _alpha_offset: u32, - pub _alpha_length: u32, -} - -impl TryFrom<[u8; std::mem::size_of::()]> for FrameBufferInfoV1 { - type Error = RustADBError; - - fn try_from( - value: [u8; std::mem::size_of::()], - ) -> std::result::Result { - let mut chunks: U32ChunkIter = value.chunks_exact(4).map(utils::u32_from_le); - - Ok(Self { - _bpp: read_next(&mut chunks)?, - size: read_next(&mut chunks)?, - width: read_next(&mut chunks)?, - height: read_next(&mut chunks)?, - _red_offset: read_next(&mut chunks)?, - _red_length: read_next(&mut chunks)?, - _blue_offset: read_next(&mut chunks)?, - _blue_length: read_next(&mut chunks)?, - _green_offset: read_next(&mut chunks)?, - _green_length: read_next(&mut chunks)?, - _alpha_offset: read_next(&mut chunks)?, - _alpha_length: read_next(&mut chunks)?, - }) - } -} - -#[derive(Debug)] -struct FrameBufferInfoV2 { - pub _bpp: u32, - pub _color_space: u32, - pub size: u32, - pub width: u32, - pub height: u32, - pub _red_offset: u32, - pub _red_length: u32, - pub _blue_offset: u32, - pub _blue_length: u32, - pub _green_offset: u32, - pub _green_length: u32, - pub _alpha_offset: u32, - pub _alpha_length: u32, -} - -impl TryFrom<[u8; std::mem::size_of::()]> for FrameBufferInfoV2 { - type Error = RustADBError; - - fn try_from( - value: [u8; std::mem::size_of::()], - ) -> std::result::Result { - let mut chunks: U32ChunkIter = value.chunks_exact(4).map(utils::u32_from_le); - - Ok(Self { - _bpp: read_next(&mut chunks)?, - _color_space: read_next(&mut chunks)?, - size: read_next(&mut chunks)?, - width: read_next(&mut chunks)?, - height: read_next(&mut chunks)?, - _red_offset: read_next(&mut chunks)?, - _red_length: read_next(&mut chunks)?, - _blue_offset: read_next(&mut chunks)?, - _blue_length: read_next(&mut chunks)?, - _green_offset: read_next(&mut chunks)?, - _green_length: read_next(&mut chunks)?, - _alpha_offset: read_next(&mut chunks)?, - _alpha_length: read_next(&mut chunks)?, - }) - } -} +use crate::{ + models::{AdbServerCommand, FrameBufferInfoV1, FrameBufferInfoV2}, + ADBServerDevice, Result, RustADBError, +}; impl ADBServerDevice { /// Dump framebuffer of this device into given ['path'] /// Big help from source code () - pub fn framebuffer>(&mut self, path: P) -> Result<()> { + pub(crate) fn framebuffer>(&mut self, path: P) -> Result<()> { let img = self.framebuffer_inner()?; Ok(img.save(path.as_ref())?) } @@ -113,7 +22,7 @@ impl ADBServerDevice { /// Dump framebuffer of this device and return corresponding bytes. /// /// Output data format is currently only `PNG`. - pub fn framebuffer_bytes(&mut self, mut writer: W) -> Result<()> { + pub(crate) fn framebuffer_bytes(&mut self, mut writer: W) -> Result<()> { let img = self.framebuffer_inner()?; Ok(img.write_to(&mut writer, ImageFormat::Png)?) } @@ -141,11 +50,12 @@ impl ADBServerDevice { .get_raw_connection()? .read_exact(&mut buf)?; - let h: FrameBufferInfoV1 = buf.try_into()?; + let framebuffer_info: FrameBufferInfoV1 = buf.try_into()?; let mut data = vec![ 0_u8; - h.size + framebuffer_info + .size .try_into() .map_err(|_| RustADBError::ConversionError)? ]; @@ -153,10 +63,12 @@ impl ADBServerDevice { .get_raw_connection()? .read_exact(&mut data)?; - Ok( - ImageBuffer::, Vec>::from_vec(h.width, h.height, data) - .ok_or_else(|| RustADBError::FramebufferConversionError)?, + Ok(ImageBuffer::, Vec>::from_vec( + framebuffer_info.width, + framebuffer_info.height, + data, ) + .ok_or_else(|| RustADBError::FramebufferConversionError)?) } // RGBX_8888 2 => { @@ -166,11 +78,12 @@ impl ADBServerDevice { .get_raw_connection()? .read_exact(&mut buf)?; - let h: FrameBufferInfoV2 = buf.try_into()?; + let framebuffer_info: FrameBufferInfoV2 = buf.try_into()?; let mut data = vec![ 0_u8; - h.size + framebuffer_info + .size .try_into() .map_err(|_| RustADBError::ConversionError)? ]; @@ -178,10 +91,12 @@ impl ADBServerDevice { .get_raw_connection()? .read_exact(&mut data)?; - Ok( - ImageBuffer::, Vec>::from_vec(h.width, h.height, data) - .ok_or_else(|| RustADBError::FramebufferConversionError)?, + Ok(ImageBuffer::, Vec>::from_vec( + framebuffer_info.width, + framebuffer_info.height, + data, ) + .ok_or_else(|| RustADBError::FramebufferConversionError)?) } v => Err(RustADBError::UnimplementedFramebufferImageVersion(v)), } diff --git a/adb_client/src/transports/tcp_transport.rs b/adb_client/src/transports/tcp_transport.rs index 9094325..3024cce 100644 --- a/adb_client/src/transports/tcp_transport.rs +++ b/adb_client/src/transports/tcp_transport.rs @@ -151,8 +151,8 @@ impl TcpTransport { client_config.key_log = Arc::new(KeyLogFile::new()); let rc_config = Arc::new(client_config); - let example_com = self.address.ip().into(); - let conn = ClientConnection::new(rc_config, example_com)?; + let server_name = self.address.ip().into(); + let conn = ClientConnection::new(rc_config, server_name)?; let owned = tcp_stream.try_clone()?; let client = StreamOwned::new(conn, owned); diff --git a/adb_client/src/transports/usb_transport.rs b/adb_client/src/transports/usb_transport.rs index d28e85a..9436eff 100644 --- a/adb_client/src/transports/usb_transport.rs +++ b/adb_client/src/transports/usb_transport.rs @@ -135,7 +135,7 @@ impl ADBTransport for USBTransport { } fn disconnect(&mut self) -> crate::Result<()> { - let message = ADBTransportMessage::new(MessageCommand::Clse, 0, 0, "".into()); + let message = ADBTransportMessage::new(MessageCommand::Clse, 0, 0, &[]); self.write_message(message) } } diff --git a/adb_client/src/utils.rs b/adb_client/src/utils.rs index 051ea57..9960544 100644 --- a/adb_client/src/utils.rs +++ b/adb_client/src/utils.rs @@ -2,14 +2,6 @@ use std::{ffi::OsStr, path::Path}; use crate::{Result, RustADBError}; -pub fn u32_from_le(value: &[u8]) -> Result { - Ok(u32::from_le_bytes( - value - .try_into() - .map_err(|_| RustADBError::ConversionError)?, - )) -} - pub fn check_extension_is_apk>(path: P) -> Result<()> { if let Some(extension) = path.as_ref().extension() { if ![OsStr::new("apk")].contains(&extension) { diff --git a/benches/benchmark_adb_push.rs b/benches/benchmark_adb_push.rs index a860ac9..c1cbfd2 100644 --- a/benches/benchmark_adb_push.rs +++ b/benches/benchmark_adb_push.rs @@ -1,4 +1,4 @@ -use adb_client::{ADBDeviceExt, ADBServer, ADBUSBDevice}; +use adb_client::ADBServer; use anyhow::Result; use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; use rand::{thread_rng, Rng}; @@ -38,14 +38,6 @@ fn bench_adb_client_push() -> Result<()> { Ok(device.push(f, REMOTE_TEST_FILE_PATH)?) } -/// Use `adb_client` crate to push a file on device using an USB device. -/// Only one android device must be connected when launching this benchmark as we're using `autodetect()` method. -fn bench_adb_client_push_over_usb() -> Result<()> { - let mut device = ADBUSBDevice::autodetect()?; - let f = File::open(LOCAL_TEST_FILE_PATH)?; - Ok(device.push(f, REMOTE_TEST_FILE_PATH)?) -} - /// Use standard `adb` command ti push a file on device fn bench_adb_push_command() -> Result<()> { let output = Command::new("adb") @@ -93,43 +85,9 @@ fn benchmark_adb_push(c: &mut Criterion) { } } -/// benchmarking `adb push INPUT DEST` and adb_client `ADBUSBDevice.push(INPUT, DEST)` -fn benchmark_adb_push_over_usb(c: &mut Criterion) { - for (file_size, sample_size) in [ - // (10 * 1024 * 1024, 100), // 10MB -> 100 iterations - // (500 * 1024 * 1024, 50), // 500MB -> 50 iterations - (1000 * 1024 * 1024, 20), // 1GB -> 20 iterations - ] { - eprintln!( - "Benchmarking file_size={} and sample_size={}", - file_size, sample_size - ); - - generate_test_file(file_size).expect("Cannot generate test file"); - - let mut group = c.benchmark_group("ADB Push Benchmark"); - group.sample_size(sample_size); - - group.bench_function(BenchmarkId::new("adb_client", "push"), |b| { - b.iter(|| { - bench_adb_client_push_over_usb() - .expect("Error while benchmarking adb_client push over USB"); - }); - }); - - group.bench_function(BenchmarkId::new("adb", "push"), |b| { - b.iter(|| { - bench_adb_push_command().expect("Error while benchmarking adb push command"); - }); - }); - - group.finish(); - } -} - criterion_group!( name = benches; config = Criterion::default().measurement_time(Duration::from_secs(1000)); - targets = benchmark_adb_push, benchmark_adb_push_over_usb + targets = benchmark_adb_push ); criterion_main!(benches);