1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use std::io::{Cursor, Read, Write};
use std::path::Path;
use image::{ImageBuffer, ImageFormat, Rgba};
use crate::models::{ADBListItemType, AdbStatResponse, RemountInfo};
use crate::{RebootType, Result};
/// Trait representing all features available on ADB devices.
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: &dyn AsRef<str>,
stdout: Option<&mut dyn Write>,
stderr: Option<&mut dyn Write>,
) -> Result<Option<u8>>;
/// 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<()>;
/// Runs command on the device.
/// Input data is read from reader and write to writer.
fn exec(
&mut self,
command: &str,
reader: &mut dyn Read,
writer: Box<dyn Write + Send>,
) -> Result<()>;
/// Display the stat information for a remote file
fn stat(&mut self, remote_path: &dyn AsRef<str>) -> Result<AdbStatResponse>;
/// Pull the remote file pointed to by `source` and write its contents into `output`
fn pull(&mut self, source: &dyn AsRef<str>, output: &mut dyn Write) -> Result<()>;
/// Push `stream` to `path` on the device.
fn push(&mut self, stream: &mut dyn Read, path: &dyn AsRef<str>) -> Result<()>;
/// List the items in a directory on the device
fn list(&mut self, path: &dyn AsRef<str>) -> Result<Vec<ADBListItemType>>;
/// Reboot the device using given reboot type
fn reboot(&mut self, reboot_type: RebootType) -> Result<()>;
/// 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,
package: &dyn AsRef<str>,
activity: &dyn AsRef<str>,
) -> Result<Vec<u8>> {
let mut output = Vec::new();
let _status = self.shell_command(
&format!(
"am start {}/{}.{}",
package.as_ref(),
package.as_ref(),
activity.as_ref()
),
Some(&mut output),
None,
)?;
Ok(output)
}
/// Install an APK pointed to by `apk_path` on device.
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>, user: Option<&str>) -> Result<()>;
/// Enable dm-verity on the device
fn enable_verity(&mut self) -> Result<()>;
/// Disable dm-verity on the device
fn disable_verity(&mut self) -> Result<()>;
/// Inner method requesting framebuffer from an Android device
fn framebuffer_inner(&mut self) -> Result<ImageBuffer<Rgba<u8>, Vec<u8>>>;
/// Dump framebuffer of this device into given path.
///
/// Output data format is currently only `PNG`.
fn framebuffer(&mut self, path: &dyn AsRef<Path>) -> Result<()> {
// Big help from AOSP source code (<https://android.googlesource.com/platform/system/adb/+/refs/heads/main/framebuffer_service.cpp>)
let img = self.framebuffer_inner()?;
Ok(img.save(path.as_ref())?)
}
/// Dump framebuffer of this device and return corresponding bytes.
///
/// Output data format is currently only `PNG`.
fn framebuffer_bytes(&mut self) -> Result<Vec<u8>> {
let img = self.framebuffer_inner()?;
let mut vec = Cursor::new(Vec::new());
img.write_to(&mut vec, ImageFormat::Png)?;
Ok(vec.into_inner())
}
/// Return a boxed instance representing this trait
fn boxed(self) -> Box<dyn ADBDeviceExt>
where
Self: Sized + 'static,
{
Box::new(self)
}
}