Skip to content

Commit e199dfa

Browse files
committed
fix(topapp-parser): 尝试适配a16的新dumpsys window输出
注意这还没有在真机测试
1 parent a597de8 commit e199dfa

File tree

1 file changed

+79
-6
lines changed

1 file changed

+79
-6
lines changed

src/framework/scheduler/topapp.rs

Lines changed: 79 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,85 @@ impl WindowsInfo {
4141
}
4242

4343
fn parse_top_app(dump: &str) -> Vec<i32> {
44-
dump.lines()
45-
.filter(|l| l.contains("Session{"))
46-
.filter_map(|l| l.split_whitespace().nth(3))
47-
.filter_map(|s| s.split(':').next())
48-
.map(|p| p.trim().parse().unwrap())
49-
.collect()
44+
let focused_app_line = match dump
45+
.lines()
46+
.find(|line| line.trim().starts_with("mFocusedApp="))
47+
{
48+
Some(line) => line,
49+
None => return Vec::new(),
50+
};
51+
52+
let package_name = match Self::extract_package_name(focused_app_line) {
53+
Some(name) => name,
54+
None => return Vec::new(),
55+
};
56+
57+
// Try modern parser, if it fails, fall back to legacy parser.
58+
let pid = Self::parse_a16_format(dump, &package_name)
59+
.or_else(|| Self::parse_a15_format(dump, &package_name));
60+
61+
pid.map_or_else(Vec::new, |p| vec![p])
62+
}
63+
64+
fn extract_package_name(line: &str) -> Option<&str> {
65+
line.split_whitespace()
66+
.find(|p| p.contains('/'))?
67+
.split('/')
68+
.next()
69+
}
70+
71+
// Modern Parser (Android 16+)
72+
// Parses the PID from the `WINDOW MANAGER WINDOWS` section.
73+
fn parse_a16_format(dump: &str, package_name: &str) -> Option<i32> {
74+
let mut in_target_window_section = false;
75+
for line in dump.lines() {
76+
if !in_target_window_section {
77+
if line.contains("Window #") && line.contains(package_name) {
78+
in_target_window_section = true;
79+
}
80+
} else {
81+
if line.contains("mSession=") {
82+
let session_part = line.split("mSession=").nth(1)?;
83+
let content_start = session_part.find('{')? + 1;
84+
let content_end = session_part.find('}')?;
85+
let content = &session_part[content_start..content_end];
86+
let pid_part = content.split_whitespace().nth(1)?;
87+
let pid_str = pid_part.split(':').next()?;
88+
return pid_str.parse::<i32>().ok();
89+
}
90+
91+
if line.contains("Window #") {
92+
return None;
93+
}
94+
}
95+
}
96+
None
97+
}
98+
99+
// Legacy Parser (Android 15 and older)
100+
// Parses the PID from the `WINDOW MANAGER SESSIONS` section.
101+
fn parse_a15_format(dump: &str, package_name: &str) -> Option<i32> {
102+
let mut last_pid_found: Option<i32> = None;
103+
for line in dump.lines() {
104+
if line.starts_with(" Session Session{") {
105+
let content_start = line.find('{')? + 1;
106+
let content_end = line.find('}')?;
107+
let content = &line[content_start..content_end];
108+
let pid_part = content.split_whitespace().nth(1)?;
109+
let pid_str = pid_part.split(':').next()?;
110+
last_pid_found = pid_str.parse::<i32>().ok();
111+
}
112+
113+
let trimmed_line = line.trim();
114+
if trimmed_line.starts_with("mPackageName=") {
115+
if let Some(pkg) = trimmed_line.split('=').nth(1) {
116+
if pkg == package_name {
117+
return last_pid_found;
118+
}
119+
}
120+
}
121+
}
122+
None
50123
}
51124
}
52125

0 commit comments

Comments
 (0)