Skip to content
Open
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
12 changes: 8 additions & 4 deletions adb_cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,17 +72,21 @@ fn run_command(mut device: Box<dyn ADBDeviceExt>, command: DeviceCommands) -> AD
device.push(&mut input, &path)?;
log::info!("Uploaded {filename} to {path}");
}
DeviceCommands::Root => {
device.root()?;
log::info!("Restarted adbd as root");
}
DeviceCommands::Run { package, activity } => {
let output = device.run_activity(&package, &activity)?;
std::io::stdout().write_all(&output)?;
}
DeviceCommands::Install { path } => {
DeviceCommands::Install { path, user } => {
log::info!("Starting installation of APK {}...", path.display());
device.install(&path)?;
device.install(&path, user.as_deref())?;
}
DeviceCommands::Uninstall { package } => {
DeviceCommands::Uninstall { package, user } => {
log::info!("Uninstalling the package {package}...");
device.uninstall(&package)?;
device.uninstall(&package, user.as_deref())?;
}
DeviceCommands::Framebuffer { path } => {
device.framebuffer(&path)?;
Expand Down
8 changes: 8 additions & 0 deletions adb_cli/src/models/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,17 @@ pub enum DeviceCommands {
},
/// Install an APK on device
Install {
/// User id to install the package for
#[clap(short = 'u', long = "user")]
user: Option<String>,
/// Path to APK file. Extension must be ".apk"
path: PathBuf,
},
/// Uninstall a package from the device
Uninstall {
/// User id of the package to uninstall
#[clap(short = 'u', long = "user")]
user: Option<String>,
/// Name of the package to uninstall
package: String,
},
Expand All @@ -51,4 +57,6 @@ pub enum DeviceCommands {
/// Path to list files from
path: String,
},
/// Restart adb daemon with root permissions
Root,
}
7 changes: 5 additions & 2 deletions adb_client/src/adb_device_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ pub trait ADBDeviceExt {
/// Remount the device partitions as read-write
fn remount(&mut self) -> Result<Vec<RemountInfo>>;

/// Restart adb daemon with root permissions
fn root(&mut self) -> Result<()>;

/// Run `activity` from `package` on device. Return the command output.
fn run_activity(
&mut self,
Expand All @@ -63,10 +66,10 @@ pub trait ADBDeviceExt {
}

/// Install an APK pointed to by `apk_path` on device.
fn install(&mut self, apk_path: &dyn AsRef<Path>) -> Result<()>;
fn install(&mut self, apk_path: &dyn AsRef<Path>, user: Option<&str>) -> Result<()>;

/// Uninstall the package `package` from device.
fn uninstall(&mut self, package: &dyn AsRef<str>) -> Result<()>;
fn uninstall(&mut self, package: &dyn AsRef<str>, user: Option<&str>) -> Result<()>;

/// Enable dm-verity on the device
fn enable_verity(&mut self) -> Result<()>;
Expand Down
13 changes: 9 additions & 4 deletions adb_client/src/message_devices/adb_message_device_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,18 @@ impl<T: ADBMessageTransport> ADBDeviceExt for ADBMessageDevice<T> {
}

#[inline]
fn install(&mut self, apk_path: &dyn AsRef<Path>) -> Result<()> {
self.install(apk_path)
fn root(&mut self) -> Result<()> {
self.root()
}

#[inline]
fn uninstall(&mut self, package: &dyn AsRef<str>) -> Result<()> {
self.uninstall(package)
fn install(&mut self, apk_path: &dyn AsRef<Path>, user: Option<&str>) -> Result<()> {
self.install(apk_path, user)
}

#[inline]
fn uninstall(&mut self, package: &dyn AsRef<str>, user: Option<&str>) -> Result<()> {
self.uninstall(package, user)
}

#[inline]
Expand Down
7 changes: 5 additions & 2 deletions adb_client/src/message_devices/commands/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@ use crate::{
};

impl<T: ADBMessageTransport> ADBMessageDevice<T> {
pub(crate) fn install(&mut self, apk_path: &dyn AsRef<Path>) -> Result<()> {
pub(crate) fn install(&mut self, apk_path: &dyn AsRef<Path>, user: Option<&str>) -> Result<()> {
let mut apk_file = File::open(apk_path)?;

check_extension_is_apk(apk_path)?;

let file_size = apk_file.metadata()?.len();

let mut session = self.open_session(&ADBLocalCommand::Install(file_size))?;
let mut session = self.open_session(&ADBLocalCommand::Install(
file_size,
user.map(ToString::to_string),
))?;

{
// Read data from apk_file and write it to the underlying session
Expand Down
1 change: 1 addition & 0 deletions adb_client/src/message_devices/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mod pull;
mod push;
mod reboot;
mod remount;
mod root;
mod shell;
mod stat;
mod uninstall;
Expand Down
18 changes: 18 additions & 0 deletions adb_client/src/message_devices/commands/root.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use crate::{
Result,
message_devices::{
adb_message_device::ADBMessageDevice, adb_message_transport::ADBMessageTransport,
message_commands::MessageCommand,
},
models::ADBLocalCommand,
};

impl<T: ADBMessageTransport> ADBMessageDevice<T> {
pub(crate) fn root(&mut self) -> Result<()> {
self.open_session(&ADBLocalCommand::Root)?;

self.get_transport_mut()
.read_message()
.and_then(|message| message.assert_command(MessageCommand::Okay))
}
}
7 changes: 6 additions & 1 deletion adb_client/src/message_devices/commands/uninstall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@ use crate::{
};

impl<T: ADBMessageTransport> ADBMessageDevice<T> {
pub(crate) fn uninstall(&mut self, package_name: &dyn AsRef<str>) -> Result<()> {
pub(crate) fn uninstall(
&mut self,
package_name: &dyn AsRef<str>,
user: Option<&str>,
) -> Result<()> {
self.open_session(&ADBLocalCommand::Uninstall(
package_name.as_ref().to_string(),
user.map(ToString::to_string),
))?;

let final_status = self.get_transport_mut().read_message()?;
Expand Down
13 changes: 9 additions & 4 deletions adb_client/src/message_devices/tcp/adb_tcp_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,18 @@ impl ADBDeviceExt for ADBTcpDevice {
}

#[inline]
fn install(&mut self, apk_path: &dyn AsRef<Path>) -> Result<()> {
self.inner.install(apk_path)
fn root(&mut self) -> Result<()> {
self.inner.root()
}

#[inline]
fn uninstall(&mut self, package: &dyn AsRef<str>) -> Result<()> {
self.inner.uninstall(package)
fn install(&mut self, apk_path: &dyn AsRef<Path>, user: Option<&str>) -> Result<()> {
self.inner.install(apk_path, user)
}

#[inline]
fn uninstall(&mut self, package: &dyn AsRef<str>, user: Option<&str>) -> Result<()> {
self.inner.uninstall(package, user)
}

#[inline]
Expand Down
13 changes: 9 additions & 4 deletions adb_client/src/message_devices/usb/adb_usb_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,13 +271,18 @@ impl ADBDeviceExt for ADBUSBDevice {
}

#[inline]
fn install(&mut self, apk_path: &dyn AsRef<Path>) -> Result<()> {
self.inner.install(apk_path)
fn root(&mut self) -> Result<()> {
self.inner.root()
}

#[inline]
fn uninstall(&mut self, package: &dyn AsRef<str>) -> Result<()> {
self.inner.uninstall(package)
fn install(&mut self, apk_path: &dyn AsRef<Path>, user: Option<&str>) -> Result<()> {
self.inner.install(apk_path, user)
}

#[inline]
fn uninstall(&mut self, package: &dyn AsRef<str>, user: Option<&str>) -> Result<()> {
self.inner.uninstall(package, user)
}

#[inline]
Expand Down
22 changes: 17 additions & 5 deletions adb_client/src/models/adb_local_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ pub(crate) enum ADBLocalCommand {
Remount,
DisableVerity,
EnableVerity,
Uninstall(String),
Install(u64),
Uninstall(String, Option<String>),
Install(u64, Option<String>),
TcpIp(u16),
Usb,
Root,
}

impl Display for ADBLocalCommand {
Expand All @@ -44,11 +45,21 @@ impl Display for ADBLocalCommand {
Self::Reboot(reboot_type) => {
write!(f, "reboot:{reboot_type}")
}
Self::Uninstall(package) => {
write!(f, "exec:cmd package 'uninstall' {package}")
Self::Uninstall(package, user) => {
write!(f, "exec:cmd package 'uninstall'")?;
if let Some(user) = user {
write!(f, " --user {user}")?;
}
write!(f, " {package}")
}
Self::FrameBuffer => write!(f, "framebuffer:"),
Self::Install(size) => write!(f, "exec:cmd package 'install' -S {size}"),
Self::Install(size, user) => {
write!(f, "exec:cmd package 'install'")?;
if let Some(user) = user {
write!(f, " --user {user}")?;
}
write!(f, " -S {size}")
}
Self::Forward(remote, local) => {
write!(f, "host:forward:{local};{remote}")
}
Expand All @@ -65,6 +76,7 @@ impl Display for ADBLocalCommand {
write!(f, "tcpip:{port}")
}
Self::Usb => write!(f, "usb:"),
Self::Root => write!(f, "root:"),
}
}
}
6 changes: 6 additions & 0 deletions adb_client/src/server/adb_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ impl ADBServer {
}
}

/// Get the server address
#[must_use]
pub fn socket_addr(&self) -> Option<SocketAddrV4> {
self.socket_addr
}

/// Start an instance of `adb-server`
pub fn start(envs: &HashMap<String, String>, adb_path: &Option<String>) {
// ADB Server is local, we start it if not already running
Expand Down
1 change: 1 addition & 0 deletions adb_client/src/server/commands/connect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ impl ADBServer {

match String::from_utf8(response) {
Ok(s) if s.starts_with("connected to") => Ok(()),
Ok(s) if s.starts_with("already connected to") => Ok(()),
Ok(s) => Err(RustADBError::ADBRequestFailed(s)),
Err(e) => Err(e.into()),
}
Expand Down
12 changes: 8 additions & 4 deletions adb_client/src/server_device/adb_server_device_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,20 @@ impl ADBDeviceExt for ADBServerDevice {
self.reboot(reboot_type)
}

fn root(&mut self) -> Result<()> {
self.root()
}

fn push(&mut self, stream: &mut dyn Read, path: &dyn AsRef<str>) -> Result<()> {
self.push(stream, path)
}

fn install(&mut self, apk_path: &dyn AsRef<Path>) -> Result<()> {
self.install(apk_path)
fn install(&mut self, apk_path: &dyn AsRef<Path>, user: Option<&str>) -> Result<()> {
self.install(apk_path, user)
}

fn uninstall(&mut self, package: &dyn AsRef<str>) -> Result<()> {
self.uninstall(package.as_ref())
fn uninstall(&mut self, package: &dyn AsRef<str>, user: Option<&str>) -> Result<()> {
self.uninstall(package.as_ref(), user)
}

fn framebuffer_inner(&mut self) -> Result<image::ImageBuffer<image::Rgba<u8>, Vec<u8>>> {
Expand Down
7 changes: 5 additions & 2 deletions adb_client/src/server_device/commands/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{

impl ADBServerDevice {
/// Install an APK on device
pub fn install<P: AsRef<Path>>(&mut self, apk_path: P) -> Result<()> {
pub fn install<P: AsRef<Path>>(&mut self, apk_path: P, user: Option<&str>) -> Result<()> {
let mut apk_file = File::open(&apk_path)?;

check_extension_is_apk(&apk_path)?;
Expand All @@ -19,7 +19,10 @@ impl ADBServerDevice {
self.set_serial_transport()?;

self.transport
.send_adb_request(&ADBCommand::Local(ADBLocalCommand::Install(file_size)))?;
.send_adb_request(&ADBCommand::Local(ADBLocalCommand::Install(
file_size,
user.map(ToString::to_string),
)))?;

let mut raw_connection = self.transport.get_raw_connection()?;

Expand Down
1 change: 1 addition & 0 deletions adb_client/src/server_device/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mod reconnect;
mod recv;
mod remount;
mod reverse;
mod root;
mod send;
mod stat;
mod tcpip;
Expand Down
16 changes: 16 additions & 0 deletions adb_client/src/server_device/commands/root.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use crate::{
Result,
models::{ADBCommand, ADBLocalCommand},
server_device::ADBServerDevice,
};

impl ADBServerDevice {
/// Restart adb daemon with root permissions
pub fn root(&mut self) -> Result<()> {
self.set_serial_transport()?;

self.transport
.proxy_connection(&ADBCommand::Local(ADBLocalCommand::Root), false)
.map(|_| ())
}
}
3 changes: 2 additions & 1 deletion adb_client/src/server_device/commands/uninstall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ use crate::{

impl ADBServerDevice {
/// Uninstall a package from device
pub fn uninstall(&mut self, package_name: &str) -> Result<()> {
pub fn uninstall(&mut self, package_name: &str, user: Option<&str>) -> Result<()> {
self.set_serial_transport()?;

self.transport
.send_adb_request(&ADBCommand::Local(ADBLocalCommand::Uninstall(
package_name.to_string(),
user.map(ToString::to_string),
)))?;

let mut data = [0; 1024];
Expand Down
15 changes: 15 additions & 0 deletions pyadb_client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,21 @@ device = server.get_device()
print(device, device.identifier)
```

### Connect and Disconnect with device id

```python
from pyadb_client import PyADBServer

server = PyADBServer("127.0.0.1:5037")

# Connect to a device with device id
device = server.connect_device("192.168.1.100:5555")
print(f"Connected to {device.identifier}")

# Disconnect from a device with device id
server.disconnect_device("192.168.1.100:5555")
```

### Push a file on device

```python
Expand Down
Loading