1use crate::device::ADB;
2use crate::error::{ADBError, ADBResult};
3use crate::app::PackageInfo;
4use log::{debug, warn};
5use rayon::prelude::*;
6use std::collections::HashMap;
7
8impl ADB {
9 pub fn parallel_shell(&self, device_ids: &[&str], command: &str) -> HashMap<String, ADBResult<String>> {
20 device_ids
21 .par_iter() .map(|&id| {
23 (id.to_string(), self.shell(id, command))
24 })
25 .collect()
26 }
27
28 pub fn parallel_install_app(&self, device_ids: &[&str], apk_path: &str) -> HashMap<String, ADBResult<()>> {
39 device_ids
40 .par_iter()
41 .map(|&id| {
42 (id.to_string(), self.install_app(id, apk_path))
43 })
44 .collect()
45 }
46
47 pub fn parallel_uninstall_app(&self, device_ids: &[&str], package_name: &str) -> HashMap<String, ADBResult<()>> {
58 device_ids
59 .par_iter()
60 .map(|&id| {
61 (id.to_string(), self.uninstall_app(id, package_name))
62 })
63 .collect()
64 }
65
66 pub fn parallel_start_app(
78 &self,
79 device_ids: &[&str],
80 package_name: &str,
81 activity: Option<&str>,
82 ) -> HashMap<String, ADBResult<bool>> {
83 device_ids
84 .par_iter()
85 .map(|&id| {
86 (id.to_string(), self.start_app(id, package_name, activity))
87 })
88 .collect()
89 }
90
91 pub fn parallel_stop_app(&self, device_ids: &[&str], package_name: &str) -> HashMap<String, ADBResult<()>> {
102 device_ids
103 .par_iter()
104 .map(|&id| {
105 (id.to_string(), self.stop_app(id, package_name))
106 })
107 .collect()
108 }
109
110 pub fn parallel_get_package_info(
121 &self,
122 device_ids: &[&str],
123 package_name: &str,
124 ) -> HashMap<String, ADBResult<PackageInfo>> {
125 device_ids
126 .par_iter()
127 .map(|&id| {
128 (id.to_string(), self.get_package_info_enhanced(id, package_name))
129 })
130 .collect()
131 }
132
133 pub fn parallel_push(
145 &self,
146 device_ids: &[&str],
147 local_path: &str,
148 device_path: &str,
149 ) -> HashMap<String, ADBResult<()>> {
150 device_ids
151 .par_iter()
152 .map(|&id| {
153 (id.to_string(), self.push(id, local_path, device_path, None))
154 })
155 .collect()
156 }
157
158 pub fn parallel_pull(
168 &self,
169 operations: &[(String, String, String)],
170 ) -> HashMap<String, ADBResult<()>> {
171 operations
172 .par_iter()
173 .map(|(device_id, device_path, local_path)| {
174 (device_id.clone(), self.pull(device_id, device_path, local_path, None))
175 })
176 .collect()
177 }
178
179 pub fn filter_online_devices(&self, device_ids: &[&str]) -> ADBResult<Vec<String>> {
189 let results = device_ids
190 .par_iter()
191 .map(|&id| {
192 (id.to_string(), self.is_device_online(id))
193 })
194 .collect::<HashMap<String, ADBResult<bool>>>();
195
196 let mut online_devices = Vec::new();
197 for (id, result) in results {
198 match result {
199 Ok(true) => online_devices.push(id),
200 Ok(false) => debug!("设备 {} 不在线", id),
201 Err(e) => warn!("检查设备 {} 状态时出错: {}", id, e),
202 }
203 }
204
205 Ok(online_devices)
206 }
207
208 pub fn on_all_online_devices<F, T>(&self, operation: F) -> ADBResult<HashMap<String, ADBResult<T>>>
218 where
219 F: Fn(&str) -> ADBResult<T> + Send + Sync,
220 T: Send,
221 {
222 let devices = self.list_devices()?;
224
225 let online_devices: Vec<String> = devices
227 .iter()
228 .filter(|d| d.is_online())
229 .map(|d| d.id.clone())
230 .collect();
231
232 if online_devices.is_empty() {
233 return Err(ADBError::DeviceError("没有在线设备".to_string()));
234 }
235
236 let results = online_devices
238 .par_iter()
239 .map(|id| {
240 (id.clone(), operation(id))
241 })
242 .collect();
243
244 Ok(results)
245 }
246
247 pub fn parallel_commands(
249 &self,
250 device_ids: &[&str],
251 commands: &[&str],
252 ) -> HashMap<String, Vec<ADBResult<String>>> {
253 device_ids
254 .par_iter()
255 .map(|&id| {
256 let results = commands
257 .iter()
258 .map(|&cmd| self.shell(id, cmd))
259 .collect();
260
261 (id.to_string(), results)
262 })
263 .collect()
264 }
265
266 pub fn start_app_on_all_devices(
268 &self,
269 package_name: &str,
270 activity: Option<&str>,
271 ) -> ADBResult<HashMap<String, ADBResult<bool>>> {
272 self.on_all_online_devices(|device_id| {
273 self.start_app(device_id, package_name, activity)
274 })
275 }
276
277 pub fn stop_app_on_all_devices(
279 &self,
280 package_name: &str,
281 ) -> ADBResult<HashMap<String, ADBResult<()>>> {
282 self.on_all_online_devices(|device_id| {
283 self.stop_app(device_id, package_name)
284 })
285 }
286}