@@ -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