Skip to content

Commit 507b43b

Browse files
authored
adb: Use uid to limit logcat to the current application (#131)
Having never really understood how Android Studio does it, I just stumbled upon this very new [stackoverflow answer] that has a rather beatiful solution to the current problems with `pidof`, without drawbacks. Pidof has always been flaky as it relies on the app to be running, which may either take some time or never happen if the app crashed before `pidof` is first run. This results in silly workarounds such as loops that induce extra delay and need to have an upper bound. And this `pid` changes every time the app is restarted, making it a tedious process that also doesn't react to manual app restarts on the device. Retrieving the `uid` via `pm list packages -U` on the other hand, and passing that to `logcat --uid` has the following advantages: - Always available immediately after the app has been installed, no need to check it in a loop (no extra delay); - Doesn't change after the app is (re!)installed, unless the user fully deletes and installs the app again; - Is resilient against app crashes because of that, and allows the user to see any error/crash related messages straight away; - Still includes logs printed by other system components that run or are invoked within an app, as before. [stackoverflow answer]: https://stackoverflow.com/a/76551835
1 parent 0fe7e31 commit 507b43b

File tree

1 file changed

+25
-22
lines changed

1 file changed

+25
-22
lines changed

xbuild/src/devices/adb.rs

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::config::AndroidDebugConfig;
22
use crate::devices::{Backend, Device};
33
use crate::{Arch, Platform};
4-
use anyhow::Result;
4+
use anyhow::{Context, Result};
55
use apk::Apk;
66
use std::io::{BufRead, BufReader};
77
use std::path::{Path, PathBuf};
@@ -206,32 +206,35 @@ impl Adb {
206206
Ok(line[..18].to_string())
207207
}
208208

209-
fn pidof(&self, device: &str, id: &str) -> Result<u32> {
210-
loop {
211-
let output = self.shell(device, None).arg("pidof").arg(id).output()?;
212-
anyhow::ensure!(
213-
output.status.success(),
214-
"failed to get pid: {}",
215-
std::str::from_utf8(&output.stderr)?.trim()
216-
);
217-
let pid = std::str::from_utf8(&output.stdout)?.trim();
218-
// may return multiple space separated pids if the old process hasn't exited yet.
219-
if pid.is_empty() || pid.contains(' ') {
220-
std::thread::sleep(std::time::Duration::from_millis(100));
221-
continue;
222-
}
223-
println!("pid of {} is {}", id, pid);
224-
return Ok(pid.parse()?);
225-
}
209+
fn uidof(&self, device: &str, id: &str) -> Result<u32> {
210+
let output = self
211+
.shell(device, None)
212+
.arg("pm")
213+
.arg("list")
214+
.arg("package")
215+
.arg("-U")
216+
.arg(id)
217+
.output()?;
218+
anyhow::ensure!(
219+
output.status.success(),
220+
"failed to get uid: {}",
221+
std::str::from_utf8(&output.stderr)?.trim()
222+
);
223+
let output = std::str::from_utf8(&output.stdout)?;
224+
let uid = output
225+
.split_whitespace()
226+
.find_map(|kv| kv.strip_prefix("uid:"))
227+
.with_context(|| format!("Could not find `uid:`` in output `{output}`"))?;
228+
Ok(uid.parse()?)
226229
}
227230

228-
fn logcat(&self, device: &str, pid: u32, last_timestamp: &str) -> Result<Logcat> {
231+
fn logcat(&self, device: &str, uid: u32, last_timestamp: &str) -> Result<Logcat> {
229232
let child = self
230233
.shell(device, None)
231234
.arg("logcat")
232235
.arg("-T")
233236
.arg(format!("'{}'", last_timestamp))
234-
.arg(format!("--pid={}", pid))
237+
.arg(format!("--uid={}", uid))
235238
.stdin(Stdio::null())
236239
.stdout(Stdio::piped())
237240
.spawn()?;
@@ -343,8 +346,8 @@ impl Adb {
343346
self.forward_reverse(device, debug_config)?;
344347
let last_timestamp = self.logcat_last_timestamp(device)?;
345348
self.start(device, package, activity)?;
346-
let pid = self.pidof(device, package)?;
347-
let logcat = self.logcat(device, pid, &last_timestamp)?;
349+
let uid = self.uidof(device, package)?;
350+
let logcat = self.logcat(device, uid, &last_timestamp)?;
348351
for line in logcat {
349352
println!("{}", line);
350353
}

0 commit comments

Comments
 (0)