1use crate::device::ADB;
2use crate::error::{ADBError, ADBResult};
3use log::debug;
4use std::path::PathBuf;
5use std::thread;
6use std::time::Duration;
7
8impl ADB {
9 pub fn enable_remote_debugging(
11 &self,
12 device_id: &str,
13 port: u16,
14 ) -> ADBResult<String> {
15 let ip_cmd = "ip addr show wlan0 | grep 'inet ' | cut -d' ' -f6 | cut -d/ -f1";
17 let ip = self.shell(device_id, ip_cmd)?;
18 let ip = ip.trim();
19
20 if ip.is_empty() {
21 return Err(ADBError::DeviceError(
22 "无法获取设备 IP 地址".to_string(),
23 ));
24 }
25
26 let cmd = format!("setprop service.adb.tcp.port {}", port);
28 self.shell(device_id, &cmd)?;
29
30 self.shell(device_id, "stop adbd && start adbd")?;
32
33 let conn_addr = format!("{}:{}", ip, port);
35 debug!("远程调试已启用: {}", conn_addr);
36
37 Ok(conn_addr)
38 }
39
40 pub fn get_device_architecture(&self, device_id: &str) -> ADBResult<String> {
42 let output = self.shell(device_id, "getprop ro.product.cpu.abi")?;
43 let arch = output.trim();
44
45 let frida_arch = match arch {
47 "armeabi-v7a" | "armeabi" => "arm",
48 "arm64-v8a" => "arm64",
49 "x86" => "x86",
50 "x86_64" => "x86_64",
51 _ => {
52 return Err(ADBError::DeviceError(format!(
53 "不支持的架构: {}",
54 arch
55 )))
56 }
57 };
58
59 debug!("设备架构: {}", frida_arch);
60 Ok(frida_arch.to_string())
61 }
62
63 pub fn start_frida_server(
65 &self,
66 device_id: &str,
67 frida_server_path: &str,
68 port: u16,
69 server_name: Option<&str>,
70 use_root: Option<bool>,
71 ) -> ADBResult<()> {
72 let server_name = server_name.unwrap_or("frida-server");
74 let use_root = use_root.unwrap_or(true);
75
76 let ps_output = self
78 .shell(device_id, &format!("ps -A | grep {}", server_name))?;
79 if !ps_output.trim().is_empty() {
80 debug!("{} 已经在设备 {} 上运行", server_name, device_id);
81
82 let netstat_output = self
84 .shell(
85 device_id,
86 &format!("netstat -ano | grep LISTEN | grep :{}", port),
87 )?;
88 if !netstat_output.trim().is_empty() {
89 debug!("{} 已在端口 {} 上监听", server_name, port);
90 return Ok(());
91 } else {
92 debug!(
94 "停止现有 {} 以在正确的端口上重启",
95 server_name
96 );
97 self.stop_frida_server(device_id, Some(server_name))?;
98 }
99 }
100
101 let device_frida_path = if PathBuf::from(frida_server_path).exists() {
103 let arch = self.get_device_architecture(device_id)?;
105
106 let arch_specific_path = format!("{}-{}", frida_server_path, arch);
108 let local_frida_path = if PathBuf::from(&arch_specific_path).exists() {
109 arch_specific_path
110 } else {
111 frida_server_path.to_string()
112 };
113
114 let device_path = format!("/data/local/tmp/{}", server_name);
116 self.push(device_id, &local_frida_path, &device_path, None)?;
117
118 self.shell(device_id, &format!("chmod 755 {}", device_path))?;
120 device_path
121 } else {
122 frida_server_path.to_string()
124 };
125
126 let start_cmd = if use_root {
128 format!("su -c '{} -l 0.0.0.0:{}'", device_frida_path, port)
129 } else {
130 format!("{} -l 0.0.0.0:{}", device_frida_path, port)
131 };
132
133 debug!("使用命令启动 {}: {}", server_name, start_cmd);
134 self.shell_no_wait(device_id, &start_cmd)?;
135
136 thread::sleep(Duration::from_secs(2));
138
139 let verification_attempts = 3;
141 for attempt in 1..=verification_attempts {
142 let ps_output = self
143 .shell(device_id, &format!("ps -A | grep {}", server_name))?;
144 if !ps_output.trim().is_empty() {
145 debug!(
146 "{} 成功启动 (尝试 {})",
147 server_name, attempt
148 );
149 return Ok(());
150 }
151
152 if attempt < verification_attempts {
153 debug!(
154 "等待 {} 启动 (尝试 {}/{})",
155 server_name, attempt, verification_attempts
156 );
157 thread::sleep(Duration::from_secs(1));
158 }
159 }
160
161 Err(ADBError::CommandError(format!(
162 "无法启动 {}。请检查权限或服务器二进制文件。",
163 server_name
164 )))
165 }
166
167 pub fn stop_frida_server(
169 &self,
170 device_id: &str,
171 server_name: Option<&str>,
172 ) -> ADBResult<()> {
173 let server_name = server_name.unwrap_or("frida-server");
174
175 let output = self
177 .shell(device_id, &format!("pkill {}", server_name))?;
178
179 if output.contains("Operation not permitted") {
181 self.shell(device_id, &format!("su -c 'pkill {}'", server_name))?;
182 }
183
184 thread::sleep(Duration::from_secs(1));
186 let ps_output = self
187 .shell(device_id, &format!("ps -A | grep {}", server_name))?;
188 if !ps_output.trim().is_empty() {
189 return Err(ADBError::CommandError(format!(
190 "无法停止 {}",
191 server_name
192 )));
193 }
194
195 debug!("{} 成功停止", server_name);
196 Ok(())
197 }
198
199 pub fn reboot(&self, device_id: &str) -> ADBResult<()> {
201 self.with_retry(|| {
202 let mut cmd = std::process::Command::new(&self.config.path);
203 if !device_id.is_empty() {
204 cmd.arg("-s").arg(device_id);
205 }
206
207 let output = cmd.arg("reboot")
208 .output()
209 .map_err(|e| ADBError::CommandError(format!("无法执行重启命令: {}", e)))?;
210
211 if !output.status.success() {
212 let stderr = String::from_utf8_lossy(&output.stderr);
213 return Err(ADBError::CommandError(format!("重启命令失败: {}", stderr)));
214 }
215
216 debug!("已发送重启命令到设备 {}", device_id);
217 Ok(())
218 })
219 }
220
221 pub fn reboot_recovery(&self, device_id: &str) -> ADBResult<()> {
223 self.with_retry(|| {
224 let mut cmd = std::process::Command::new(&self.config.path);
225 if !device_id.is_empty() {
226 cmd.arg("-s").arg(device_id);
227 }
228
229 let output = cmd.arg("reboot")
230 .arg("recovery")
231 .output()
232 .map_err(|e| ADBError::CommandError(format!("无法执行重启到恢复模式命令: {}", e)))?;
233
234 if !output.status.success() {
235 let stderr = String::from_utf8_lossy(&output.stderr);
236 return Err(ADBError::CommandError(format!("重启到恢复模式命令失败: {}", stderr)));
237 }
238
239 debug!("已发送重启到恢复模式命令到设备 {}", device_id);
240 Ok(())
241 })
242 }
243
244 pub fn reboot_bootloader(&self, device_id: &str) -> ADBResult<()> {
246 self.with_retry(|| {
247 let mut cmd = std::process::Command::new(&self.config.path);
248 if !device_id.is_empty() {
249 cmd.arg("-s").arg(device_id);
250 }
251
252 let output = cmd.arg("reboot")
253 .arg("bootloader")
254 .output()
255 .map_err(|e| ADBError::CommandError(format!("无法执行重启到引导加载程序模式命令: {}", e)))?;
256
257 if !output.status.success() {
258 let stderr = String::from_utf8_lossy(&output.stderr);
259 return Err(ADBError::CommandError(format!("重启到引导加载程序模式命令失败: {}", stderr)));
260 }
261
262 debug!("已发送重启到引导加载程序模式命令到设备 {}", device_id);
263 Ok(())
264 })
265 }
266}