mirror of
https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation.git
synced 2026-08-09 15:19:11 +02:00
refactor: rm all regex, and properly parse pm list users
This commit is contained in:
parent
ca0cfd400d
commit
c5799702e2
4 changed files with 63 additions and 62 deletions
39
Cargo.lock
generated
39
Cargo.lock
generated
|
|
@ -37,15 +37,6 @@ dependencies = [
|
|||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "allocator-api2"
|
||||
version = "0.2.21"
|
||||
|
|
@ -3100,35 +3091,6 @@ dependencies = [
|
|||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||
|
||||
[[package]]
|
||||
name = "renderdoc-sys"
|
||||
version = "1.1.0"
|
||||
|
|
@ -3934,7 +3896,6 @@ dependencies = [
|
|||
"flate2",
|
||||
"iced",
|
||||
"log",
|
||||
"regex",
|
||||
"retry",
|
||||
"rfd",
|
||||
"serde",
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ chrono = { version = "^0.4", default-features = false, features = [
|
|||
"clock",
|
||||
] }
|
||||
log = "^0.4"
|
||||
regex = "^1.10.2"
|
||||
toml = "^0"
|
||||
dirs = "^6"
|
||||
ureq = { version = "3", features = ["json"] }
|
||||
|
|
|
|||
|
|
@ -356,15 +356,66 @@ impl PmCommand {
|
|||
})
|
||||
}
|
||||
|
||||
/// `list users` sub-command.
|
||||
/// Output isn't parsed, because
|
||||
/// we don't know if the format is stable across Android versions.
|
||||
/// `list users` sub-command, deserialized/parsed.
|
||||
///
|
||||
/// - <https://source.android.com/docs/devices/admin/multi-user-testing>
|
||||
/// - <https://stackoverflow.com/questions/37495126/android-get-list-of-users-and-profile-name>
|
||||
pub fn list_users(mut self) -> Result<String, String> {
|
||||
pub fn list_users(mut self) -> Result<Box<[UserInfo]>, String> {
|
||||
self.0.0.0.args(["list", "users"]);
|
||||
self.0.0.run()
|
||||
Ok(self
|
||||
.0
|
||||
.0
|
||||
.run()?
|
||||
.lines()
|
||||
.skip(1) // omit header
|
||||
.map(|ln| {
|
||||
// this could be optimized by making more API-stability assumptions
|
||||
let ln = ln.trim_ascii_start();
|
||||
let ln = ln.strip_prefix("UserInfo").unwrap_or(ln).trim_ascii_start();
|
||||
let ln = ln.strip_prefix('{').unwrap_or(ln).trim_ascii();
|
||||
let ln = ln.strip_suffix('}').unwrap_or(ln).trim_ascii_end();
|
||||
// https://android.googlesource.com/platform/frameworks/base/+/refs/heads/main/core/java/android/content/pm/UserInfo.java
|
||||
// the format seems to be stable across Android versions:
|
||||
// "\tUserInfo{<id>:<name>:<flags>}"
|
||||
|
||||
let mut comps = ln.split(':');
|
||||
|
||||
let id = comps
|
||||
.next()
|
||||
.expect("There must be at least 1 ':'-separated component")
|
||||
.parse()
|
||||
.expect("string assumed to be UID numeral");
|
||||
//let name = comps
|
||||
// .next()
|
||||
// .expect("There must be at least 2 ':'-separated components. 2nd is user-name");
|
||||
//let flags = u32::from_str_radix(
|
||||
// comps.next().expect(
|
||||
// "There must be at least 3 ':'-separated components. 3rd is user bit-flags",
|
||||
// ),
|
||||
// 16,
|
||||
//)
|
||||
//.expect("string assumed to be hexadecimal bit-flags");
|
||||
UserInfo {
|
||||
id,
|
||||
//name: name.into(),
|
||||
//flags,
|
||||
}
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
}
|
||||
|
||||
/// Mirror of AOSP `UserInfo` Java Class
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct UserInfo {
|
||||
id: u16,
|
||||
//name: Box<str>,
|
||||
//flags: u32,
|
||||
}
|
||||
impl UserInfo {
|
||||
#[must_use]
|
||||
pub const fn get_id(&self) -> u16 {
|
||||
self.id
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,11 +3,9 @@ use crate::core::{
|
|||
uad_lists::PackageState,
|
||||
};
|
||||
use crate::gui::{views::list::PackageInfo, widgets::package_row::PackageRow};
|
||||
use regex::Regex;
|
||||
use retry::{OperationResult, delay::Fixed, retry};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::process::Command;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
use std::os::windows::process::CommandExt;
|
||||
|
|
@ -43,6 +41,7 @@ impl std::fmt::Display for Phone {
|
|||
}
|
||||
}
|
||||
|
||||
/// `UserInfo` but relevant to UAD
|
||||
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct User {
|
||||
pub id: u16,
|
||||
|
|
@ -292,29 +291,20 @@ pub fn is_protected_user<S: AsRef<str>>(user_id: u16, device_serial: S) -> bool
|
|||
.is_err()
|
||||
}
|
||||
|
||||
/// `pm list users` parsed into a vector with extra info
|
||||
pub fn list_users_parsed(device_serial: &str) -> Vec<User> {
|
||||
// this could be thread-local (no lock overhead),
|
||||
// but then each thread would compile its own clone of the regex,
|
||||
// I guess?
|
||||
static RE: LazyLock<Regex> =
|
||||
LazyLock::new(|| Regex::new(r"\{([0-9]+)").unwrap_or_else(|_| unreachable!()));
|
||||
|
||||
pub fn list_users_idx_prot(device_serial: &str) -> Vec<User> {
|
||||
AdbCommand::new()
|
||||
.shell(device_serial)
|
||||
.pm()
|
||||
.list_users()
|
||||
.map(|out| {
|
||||
RE.find_iter(&out)
|
||||
out.into_iter()
|
||||
.enumerate()
|
||||
.map(|(i, user)| {
|
||||
let u = user.as_str()[1..]
|
||||
.parse()
|
||||
.unwrap_or_else(|_| unreachable!("User ID must always be a valid `u16`"));
|
||||
let id = user.get_id();
|
||||
User {
|
||||
id: u,
|
||||
id,
|
||||
index: i,
|
||||
protected: is_protected_user(u, device_serial),
|
||||
protected: is_protected_user(id, device_serial),
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
|
|
@ -338,7 +328,7 @@ pub async fn get_devices_list() -> Vec<Phone> {
|
|||
device_list.push(Phone {
|
||||
model: format!("{} {}", get_device_brand(serial), get_device_model(serial)),
|
||||
android_sdk: get_android_sdk(serial),
|
||||
user_list: list_users_parsed(serial),
|
||||
user_list: list_users_idx_prot(serial),
|
||||
adb_id: serial.to_string(),
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue