Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/python-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,4 @@ jobs:
with:
files: |
target/wheels/pyadb_client*.whl
target/wheels/pyadb_client*.tar.gz
target/wheels/pyadb_client*.tar.gz
6 changes: 3 additions & 3 deletions .github/workflows/rust-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ jobs:
os: [ubuntu-latest, windows-latest, macos-latest]

steps:
- uses: actions/checkout@v4
- name: Build project
run: cargo build --release --all-features
- uses: actions/checkout@v4
- name: Build project
run: cargo build --release --all-features
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ target
/.vscode
venv
/.mypy_cache
pyadb_client/pyadb_client.pyi
pyadb_client/pyadb_client.pyi
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = ["adb_cli", "adb_client", "pyadb_client"]
members = ["adb_cli", "adb_client", "examples/mdns", "pyadb_client"]
resolver = "2"

[workspace.package]
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ Provides a "real-world" usage example of this library.

Improved documentation available [here](./adb_cli/README.md).

## examples

Some examples are available in the `examples` directory:

- `examples/mdns`: mDNS device discovery example

## pyadb_client

Python wrapper using `adb_client` library to export classes usable directly from a Python environment.
Expand Down
2 changes: 1 addition & 1 deletion adb_cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ rust-version.workspace = true
version.workspace = true

[dependencies]
adb_client = { version = "^2.0.0" }
adb_client = { version = "^2.0.0", features = ["mdns", "usb"] }
anyhow = { version = "1.0.94" }
clap = { version = "4.5.23", features = ["derive"] }
env_logger = { version = "0.11.5" }
Expand Down
2 changes: 1 addition & 1 deletion adb_cli/src/handlers/emulator_commands.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use adb_client::ADBEmulatorDevice;
use adb_client::emulator::ADBEmulatorDevice;

use crate::models::{EmuCommand, EmulatorCommand};

Expand Down
5 changes: 4 additions & 1 deletion adb_cli/src/handlers/host_commands.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use adb_client::{ADBServer, DeviceShort, MDNSBackend, Result, WaitForDeviceState};
use adb_client::{
Result,
server::{ADBServer, DeviceShort, MDNSBackend, WaitForDeviceState},
};

use crate::models::{HostCommand, MdnsCommand, ServerCommand};

Expand Down
2 changes: 1 addition & 1 deletion adb_cli/src/handlers/local_commands.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{fs::File, io::Write};

use adb_client::ADBServerDevice;
use adb_client::server_device::ADBServerDevice;
use anyhow::{Result, anyhow};

use crate::models::LocalDeviceCommand;
Expand Down
9 changes: 6 additions & 3 deletions adb_cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ mod handlers;
mod models;
mod utils;

use adb_client::{
ADBDeviceExt, ADBServer, ADBServerDevice, ADBTcpDevice, ADBUSBDevice, MDNSDiscoveryService,
};
use adb_client::ADBDeviceExt;
use adb_client::mdns::MDNSDiscoveryService;
use adb_client::server::ADBServer;
use adb_client::server_device::ADBServerDevice;
use adb_client::tcp::ADBTcpDevice;
use adb_client::usb::ADBUSBDevice;

#[cfg(any(target_os = "linux", target_os = "macos"))]
use adb_termios::ADBTermios;
Expand Down
2 changes: 1 addition & 1 deletion adb_cli/src/models/host.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::net::SocketAddrV4;

use adb_client::{RustADBError, WaitForDeviceTransport};
use adb_client::{RustADBError, server::WaitForDeviceTransport};
use clap::Parser;

fn parse_wait_for_device_device_transport(
Expand Down
26 changes: 21 additions & 5 deletions adb_client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ repository.workspace = true
rust-version.workspace = true
version.workspace = true

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[features]
default = []
mdns = ["dep:mdns-sd"]
usb = ["dep:rsa", "dep:rusb"]

[dependencies]
base64 = { version = "0.22.1" }
bincode = { version = "1.3.3" }
Expand All @@ -18,9 +27,6 @@ chrono = { version = "0.4.40", default-features = false, features = ["std"] }
homedir = { version = "= 0.3.4" }
image = { version = "0.25.5", default-features = false }
log = { version = "0.4.26" }
mdns-sd = { version = "0.13.9", default-features = false, features = [
"logging",
] }
num-bigint = { version = "0.8.4", package = "num-bigint-dig" }
num-traits = { version = "0.2.19" }
quick-protobuf = { version = "0.8.1" }
Expand All @@ -30,15 +36,25 @@ rcgen = { version = "0.13.1", default-features = false, features = [
"pem",
] }
regex = { version = "1.11.1", features = ["perf", "std", "unicode"] }
rsa = { version = "0.9.7" }
rusb = { version = "0.9.4", features = ["vendored"] }
rustls = { version = "0.23.27" }
rustls-pki-types = { version = "1.11.0" }
serde = { version = "1.0.216", features = ["derive"] }
serde_repr = { version = "0.1.19" }
sha1 = { version = "0.10.6", features = ["oid"] }
thiserror = { version = "2.0.7" }

#########
# MDNS-only dependencies
mdns-sd = { version = "0.13.9", default-features = false, features = [
"logging",
], optional = true }
#########
#########
# USB-only dependencies
rsa = { version = "0.9.7", optional = true }
rusb = { version = "0.9.4", features = ["vendored"], optional = true }
#########

[dev-dependencies]
anyhow = { version = "1.0.93" }
criterion = { version = "0.6.0" } # Used for benchmarks
Expand Down
103 changes: 21 additions & 82 deletions adb_client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,97 +16,36 @@ 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|<div style="color:green">-1,57 %</div>|
|500 MB|50|15,60 s|15,64 s|<div style="color:green">-0,25 %</div>|
|1 GB|20|31,09 s|31,12 s|<div style="color:green">-0,10 %</div>|

## Examples

### Get available ADB devices

```rust no_run
use adb_client::ADBServer;
use std::net::{SocketAddrV4, Ipv4Addr};

// A custom server address can be provided
let server_ip = Ipv4Addr::new(127, 0, 0, 1);
let server_port = 5037;

let mut server = ADBServer::new(SocketAddrV4::new(server_ip, server_port));
server.devices();
```

### Using ADB server as bridge
## Crate features

#### Launch a command on device
| Feature | Description | Default? |
| :-----: | :---------------------------------------------: | :------: |
| `mdns` | Enables mDNS device discovery on local network. | No |
| `usb` | Enables interactions with USB devices. | No |

```rust no_run
use adb_client::{ADBServer, ADBDeviceExt};
To deactivate some features you can use the `default-features = false` option in your `Cargo.toml` file and manually specify the features you want to activate:

let mut server = ADBServer::default();
let mut device = server.get_device().expect("cannot get device");
device.shell_command(&["df", "-h"], &mut std::io::stdout());
```

#### Push a file to the device

```rust no_run
use adb_client::ADBServer;
use std::net::Ipv4Addr;
use std::fs::File;
use std::path::Path;

let mut server = ADBServer::default();
let mut device = server.get_device().expect("cannot get device");
let mut input = File::open(Path::new("/tmp/f")).expect("Cannot open file");
device.push(&mut input, "/data/local/tmp");
```toml
[dependencies]
adb_client = { version = "*" }
```

### Interact directly with end devices

#### (USB) Launch a command on device

```rust no_run
use adb_client::{ADBUSBDevice, ADBDeviceExt};
## Examples

let vendor_id = 0x04e8;
let product_id = 0x6860;
let mut device = ADBUSBDevice::new(vendor_id, product_id).expect("cannot find device");
device.shell_command(&["df", "-h"], &mut std::io::stdout());
```
Usage examples can be found in the `examples/` directory of this repository.

#### (USB) Push a file to the device
Some example are also provided in the various `README.md` files of modules.

```rust no_run
use adb_client::{ADBUSBDevice, ADBDeviceExt};
use std::fs::File;
use std::path::Path;
## Benchmarks

let vendor_id = 0x04e8;
let product_id = 0x6860;
let mut device = ADBUSBDevice::new(vendor_id, product_id).expect("cannot find device");
let mut input = File::open(Path::new("/tmp/f")).expect("Cannot open file");
device.push(&mut input, &"/data/local/tmp");
```
Benchmarks run on `v2.0.6`, on a **Samsung S10 SM-G973F** device and an **Intel i7-1265U** CPU laptop

#### (TCP) Get a shell from device
### `ADBServerDevice` push vs `adb push`

```rust no_run
use std::net::{SocketAddr, IpAddr, Ipv4Addr};
use adb_client::{ADBTcpDevice, ADBDeviceExt};
`ADBServerDevice` performs all operations by using adb server as a bridge.

let device_ip = IpAddr::V4(Ipv4Addr::new(192, 168, 0, 10));
let device_port = 43210;
let mut device = ADBTcpDevice::new(SocketAddr::new(device_ip, device_port)).expect("cannot find device");
device.shell(&mut std::io::stdin(), Box::new(std::io::stdout()));
```
| File size | Sample size | `ADBServerDevice` | `adb` | Difference |
| :-------: | :---------: | :---------------: | :-------: | :------------------------------------: |
| 10 MB | 100 | 350,79 ms | 356,30 ms | <div style="color:green">-1,57 %</div> |
| 500 MB | 50 | 15,60 s | 15,64 s | <div style="color:green">-0,25 %</div> |
| 1 GB | 20 | 31,09 s | 31,12 s | <div style="color:green">-0,10 %</div> |
4 changes: 2 additions & 2 deletions adb_client/src/adb_device_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ use image::{ImageBuffer, ImageFormat, Rgba};
use crate::models::AdbStatResponse;
use crate::{RebootType, Result};

/// Trait representing all features available on both [`crate::ADBServerDevice`] and [`crate::ADBUSBDevice`]
/// Trait representing all features available on both [`crate::server_device::ADBServerDevice`] and [`crate::usb::ADBUSBDevice`]
pub trait ADBDeviceExt {
/// Runs command in a shell on the device, and write its output and error streams into output.
fn shell_command(&mut self, command: &[&str], output: &mut dyn Write) -> Result<()>;

/// Starts an interactive shell session on the device.
/// Input data is read from reader and write to writer.
fn shell(&mut self, reader: &mut dyn Read, writer: Box<(dyn Write + Send)>) -> Result<()>;
fn shell(&mut self, reader: &mut dyn Read, writer: Box<dyn Write + Send>) -> Result<()>;

/// Display the stat information for a remote file
fn stat(&mut self, remote_path: &str) -> Result<AdbStatResponse>;
Expand Down
1 change: 0 additions & 1 deletion adb_client/src/constants.rs

This file was deleted.

19 changes: 0 additions & 19 deletions adb_client/src/device/mod.rs

This file was deleted.

5 changes: 0 additions & 5 deletions adb_client/src/device/models/mod.rs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use std::{
sync::LazyLock,
};

use crate::{ADBServerDevice, ADBTransport, Result, RustADBError, TCPEmulatorTransport};
use crate::{
ADBTransport, Result, RustADBError, emulator::tcp_emulator_transport::TCPEmulatorTransport,
server_device::ADBServerDevice,
};
use regex::Regex;

static EMULATOR_REGEX: LazyLock<Regex> = LazyLock::new(|| {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::{ADBEmulatorDevice, Result, emulator_device::ADBEmulatorCommand};
use crate::{
Result,
emulator::{ADBEmulatorCommand, ADBEmulatorDevice},
};

impl ADBEmulatorDevice {
/// Send a SMS to this emulator with given content with given phone number
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::{ADBEmulatorDevice, Result, emulator_device::ADBEmulatorCommand};
use crate::{
Result,
emulator::{ADBEmulatorCommand, ADBEmulatorDevice},
};

impl ADBEmulatorDevice {
/// Send a SMS to this emulator with given content with given phone number
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
mod adb_emulator_device;
mod commands;
mod models;
mod tcp_emulator_transport;

pub use adb_emulator_device::ADBEmulatorDevice;
pub(crate) use models::ADBEmulatorCommand;
use models::ADBEmulatorCommand;
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ use std::{

use homedir::my_home;

use super::ADBTransport;
use crate::{Result, RustADBError, emulator_device::ADBEmulatorCommand};
use crate::{
Result, RustADBError, adb_transport::ADBTransport, emulator::models::ADBEmulatorCommand,
};

/// Emulator transport running on top on TCP.
#[derive(Debug)]
Expand Down
Loading
Loading