@@ -4,10 +4,10 @@ use std::{
44 io:: { Read , Write } ,
55 os:: unix:: net:: UnixStream ,
66 thread,
7- time:: Duration ,
7+ time:: { Duration , Instant } ,
88} ;
99
10- use log:: { error, warn} ;
10+ use log:: { error, info , warn} ;
1111use serde:: { Deserialize , Serialize } ;
1212use zygisk_api:: api:: { V4 , ZygiskApi } ;
1313
@@ -213,7 +213,13 @@ fn apply_resetprop_session(
213213 resetprop_delete ( & resetprop_path, key) ?;
214214 }
215215
216- spawn_restore_watcher ( request. pid , backups, resetprop_path) ?;
216+ spawn_restore_watcher (
217+ request. pid ,
218+ request. props ,
219+ request. delete_props ,
220+ backups,
221+ resetprop_path,
222+ ) ?;
217223
218224 Ok ( backups_for_response)
219225}
@@ -269,6 +275,8 @@ fn resetprop_delete(path: &str, key: &str) -> anyhow::Result<()> {
269275
270276fn spawn_restore_watcher (
271277 pid : u32 ,
278+ props : HashMap < String , String > ,
279+ delete_props : Vec < String > ,
272280 backups : Vec < PropBackup > ,
273281 resetprop_path : String ,
274282) -> anyhow:: Result < ( ) > {
@@ -279,16 +287,14 @@ fn spawn_restore_watcher(
279287 if libc:: setsid ( ) == -1 {
280288 libc:: _exit ( 1 ) ;
281289 }
282- wait_for_process_inactive ( pid) ;
283- for entry in backups {
284- if let Err ( e) =
285- apply_resetprop ( & resetprop_path, & entry. key , & entry. original_value )
286- {
287- error ! (
288- "Failed to restore property {} for pid {}: {}" ,
289- entry. key, pid, e
290- ) ;
291- }
290+ if let Err ( e) = watch_process_state_and_sync_props (
291+ pid,
292+ & props,
293+ & delete_props,
294+ & backups,
295+ & resetprop_path,
296+ ) {
297+ error ! ( "Watcher failed for pid {}: {}" , pid, e) ;
292298 }
293299 libc:: _exit ( 0 ) ;
294300 }
@@ -297,19 +303,72 @@ fn spawn_restore_watcher(
297303 }
298304}
299305
300- fn wait_for_process_inactive ( pid : u32 ) {
306+ fn watch_process_state_and_sync_props (
307+ pid : u32 ,
308+ props : & HashMap < String , String > ,
309+ delete_props : & [ String ] ,
310+ backups : & [ PropBackup ] ,
311+ resetprop_path : & str ,
312+ ) -> anyhow:: Result < ( ) > {
313+ const POLL_INTERVAL : Duration = Duration :: from_millis ( 200 ) ;
314+ const BACKGROUND_DEBOUNCE : Duration = Duration :: from_secs ( 2 ) ;
315+
301316 let proc_path = format ! ( "/proc/{pid}" ) ;
317+ let mut is_spoof_applied = true ;
318+ let mut background_since: Option < Instant > = None ;
319+
302320 loop {
303321 if !std:: path:: Path :: new ( & proc_path) . exists ( ) {
322+ if is_spoof_applied {
323+ restore_props_batch ( resetprop_path, backups) ?;
324+ }
304325 break ;
305326 }
306327
307- if !is_process_in_top_app ( pid) {
308- break ;
328+ if is_process_in_top_app ( pid) {
329+ background_since = None ;
330+ if !is_spoof_applied {
331+ apply_props_batch ( resetprop_path, props, delete_props) ?;
332+ is_spoof_applied = true ;
333+ info ! ( "restore watcher re-applied spoof props for pid {}" , pid) ;
334+ }
335+ } else {
336+ let bg_start = background_since. get_or_insert_with ( Instant :: now) ;
337+ if is_spoof_applied && bg_start. elapsed ( ) >= BACKGROUND_DEBOUNCE {
338+ restore_props_batch ( resetprop_path, backups) ?;
339+ is_spoof_applied = false ;
340+ info ! ( "restore watcher restored props for pid {}" , pid) ;
341+ }
309342 }
310343
311- thread:: sleep ( Duration :: from_millis ( 500 ) ) ;
344+ thread:: sleep ( POLL_INTERVAL ) ;
312345 }
346+
347+ Ok ( ( ) )
348+ }
349+
350+ fn apply_props_batch (
351+ resetprop_path : & str ,
352+ props : & HashMap < String , String > ,
353+ delete_props : & [ String ] ,
354+ ) -> anyhow:: Result < ( ) > {
355+ for ( key, value) in props {
356+ apply_resetprop ( resetprop_path, key, value) ?;
357+ }
358+
359+ for key in delete_props {
360+ resetprop_delete ( resetprop_path, key) ?;
361+ }
362+
363+ Ok ( ( ) )
364+ }
365+
366+ fn restore_props_batch ( resetprop_path : & str , backups : & [ PropBackup ] ) -> anyhow:: Result < ( ) > {
367+ for entry in backups {
368+ apply_resetprop ( resetprop_path, & entry. key , & entry. original_value ) ?;
369+ }
370+
371+ Ok ( ( ) )
313372}
314373
315374fn is_process_in_top_app ( pid : u32 ) -> bool {
0 commit comments