@@ -224,7 +224,27 @@ private void deoptimizeMethods(Class<?> clazz, String... names) {
224224 private void hookWindowState (ClassLoader classLoader ) throws ClassNotFoundException , NoSuchMethodException {
225225 var windowStateClazz = classLoader .loadClass ("com.android.server.wm.WindowState" );
226226 var isSecureLockedMethod = windowStateClazz .getDeclaredMethod ("isSecureLocked" );
227- hook (isSecureLockedMethod ).intercept (new SecureLockedHooker ());
227+ hook (isSecureLockedMethod ).intercept (chain -> {
228+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .UPSIDE_DOWN_CAKE ) {
229+ var walker = StackWalker .getInstance ();
230+ var match = walker .walk (frames -> frames
231+ .map (StackWalker .StackFrame ::getMethodName )
232+ .limit (6 )
233+ .skip (2 )
234+ .anyMatch (s -> s .equals ("setInitialSurfaceControlProperties" ) || s .equals ("createSurfaceLocked" )));
235+ if (match ) return chain .proceed ();
236+ } else {
237+ var stackTrace = new Throwable ().getStackTrace ();
238+ for (int i = 4 ; i < stackTrace .length && i < 8 ; i ++) {
239+ var name = stackTrace [i ].getMethodName ();
240+ if (name .equals ("setInitialSurfaceControlProperties" ) ||
241+ name .equals ("createSurfaceLocked" )) {
242+ return chain .proceed ();
243+ }
244+ }
245+ }
246+ return false ;
247+ });
228248 }
229249
230250 private static Field captureSecureLayersField ;
@@ -257,12 +277,42 @@ private void hookDisplayControl(ClassLoader classLoader) throws ClassNotFoundExc
257277 Build .VERSION .SDK_INT >= Build .VERSION_CODES .VANILLA_ICE_CREAM ?
258278 "createVirtualDisplay" :
259279 "createDisplay" , String .class , boolean .class );
260- hook (method ).intercept (new CreateDisplayHooker ());
280+ hook (method ).intercept (chain -> {
281+ if (Build .VERSION .SDK_INT < Build .VERSION_CODES .UPSIDE_DOWN_CAKE ) {
282+ var stackTrace = new Throwable ().getStackTrace ();
283+ for (int i = 4 ; i < stackTrace .length && i < 8 ; i ++) {
284+ var name = stackTrace [i ].getMethodName ();
285+ if (name .equals ("createVirtualDisplayLocked" )) {
286+ return chain .proceed ();
287+ }
288+ }
289+ }
290+ var args = chain .getArgs ().toArray ();
291+ args [1 ] = true ;
292+ return chain .proceed (args );
293+ });
261294 }
262295
263296 private void hookVirtualDisplayAdapter (ClassLoader classLoader ) throws ClassNotFoundException {
264297 var displayControlClazz = classLoader .loadClass ("com.android.server.display.VirtualDisplayAdapter" );
265- hookMethods (displayControlClazz , new CreateVirtualDisplayLockedHooker (), "createVirtualDisplayLocked" );
298+ hookMethods (displayControlClazz , chain -> {
299+ var caller = (int ) chain .getArg (2 );
300+ if (caller >= 10000 && chain .getArg (1 ) == null ) {
301+ // not os and not media projection
302+ return chain .proceed ();
303+ }
304+ for (int i = 3 ; i < chain .getArgs ().size (); i ++) {
305+ var arg = chain .getArg (i );
306+ if (arg instanceof Integer flags ) {
307+ flags |= DisplayManager .VIRTUAL_DISPLAY_FLAG_SECURE ;
308+ var args = chain .getArgs ().toArray ();
309+ args [i ] = flags ;
310+ return chain .proceed (args );
311+ }
312+ }
313+ module .log (Log .WARN , TAG , "flag not found in CreateVirtualDisplayLockedHooker" );
314+ return chain .proceed ();
315+ }, "createVirtualDisplayLocked" );
266316 }
267317
268318 @ RequiresApi (Build .VERSION_CODES .UPSIDE_DOWN_CAKE )
@@ -271,27 +321,35 @@ private void hookActivityTaskManagerService(ClassLoader classLoader) throws Clas
271321 var iBinderClazz = classLoader .loadClass ("android.os.IBinder" );
272322 var iScreenCaptureObserverClazz = classLoader .loadClass ("android.app.IScreenCaptureObserver" );
273323 var method = activityTaskManagerServiceClazz .getDeclaredMethod ("registerScreenCaptureObserver" , iBinderClazz , iScreenCaptureObserverClazz );
274- hook (method ).intercept (new ReturnNullHooker () );
324+ hook (method ).intercept (chain -> null );
275325 }
276326
277327 @ RequiresApi (Build .VERSION_CODES .VANILLA_ICE_CREAM )
278328 private void hookWindowManagerService (ClassLoader classLoader ) throws ClassNotFoundException , NoSuchMethodException {
279329 var windowManagerServiceClazz = classLoader .loadClass ("com.android.server.wm.WindowManagerService" );
280330 var iScreenRecordingCallbackClazz = classLoader .loadClass ("android.window.IScreenRecordingCallback" );
281331 var method = windowManagerServiceClazz .getDeclaredMethod ("registerScreenRecordingCallback" , iScreenRecordingCallbackClazz );
282- hook (method ).intercept (new ReturnFalseHooker () );
332+ hook (method ).intercept (chain -> false );
283333 }
284334
285335 private void hookActivityManagerService (ClassLoader classLoader ) throws ClassNotFoundException , NoSuchMethodException {
286336 var activityTaskManagerServiceClazz = classLoader .loadClass ("com.android.server.am.ActivityManagerService" );
287337 var method = activityTaskManagerServiceClazz .getDeclaredMethod ("checkPermission" , String .class , int .class , int .class );
288- hook (method ).intercept (new CheckPermissionHooker ());
338+ hook (method ).intercept (chain -> {
339+ var permission = chain .getArg (0 );
340+ if ("android.permission.CAPTURE_BLACKOUT_CONTENT" .equals (permission )) {
341+ var args = chain .getArgs ().toArray ();
342+ args [0 ] = "android.permission.READ_FRAME_BUFFER" ;
343+ return chain .proceed (args );
344+ }
345+ return chain .proceed ();
346+ });
289347 }
290348
291349 @ RequiresApi (Build .VERSION_CODES .UPSIDE_DOWN_CAKE )
292350 private void hookHyperOS (ClassLoader classLoader ) throws ClassNotFoundException {
293351 var windowManagerServiceImplClazz = classLoader .loadClass ("com.android.server.wm.WindowManagerServiceImpl" );
294- hookMethods (windowManagerServiceImplClazz , new ReturnFalseHooker () , "notAllowCaptureDisplay" );
352+ hookMethods (windowManagerServiceImplClazz , chain -> false , "notAllowCaptureDisplay" );
295353 }
296354
297355 private void hookScreenshotHardwareBuffer (ClassLoader classLoader ) throws ClassNotFoundException , NoSuchMethodException {
@@ -300,25 +358,29 @@ private void hookScreenshotHardwareBuffer(ClassLoader classLoader) throws ClassN
300358 "android.window.ScreenCapture$ScreenshotHardwareBuffer" :
301359 "android.view.SurfaceControl$ScreenshotHardwareBuffer" );
302360 var method = screenshotHardwareBufferClazz .getDeclaredMethod ("containsSecureLayers" );
303- hook (method ).intercept (new ReturnFalseHooker () );
361+ hook (method ).intercept (chain -> false );
304362 }
305363
306364 @ RequiresApi (Build .VERSION_CODES .VANILLA_ICE_CREAM )
307365 private void hookOplusScreenCapture (ClassLoader classLoader ) throws ClassNotFoundException , NoSuchMethodException {
308366 var oplusScreenCaptureClazz = classLoader .loadClass ("com.oplus.screenshot.OplusScreenCapture$CaptureArgs$Builder" );
309367 var method = oplusScreenCaptureClazz .getDeclaredMethod ("setUid" , long .class );
310- hook (method ).intercept (new OplusScreenCaptureHooker ());
368+ hook (method ).intercept (chain -> {
369+ var args = chain .getArgs ().toArray ();
370+ args [0 ] = -1 ;
371+ return chain .proceed (args );
372+ });
311373 }
312374
313375 private void hookOplus (ClassLoader classLoader ) throws ClassNotFoundException {
314376 // caller: com.android.server.wm.OplusLongshotWindowDump#dumpWindows
315377 var longshotMainClazz = classLoader .loadClass ("com.android.server.wm.OplusLongshotMainWindow" );
316- hookMethods (longshotMainClazz , new ReturnFalseHooker () , "hasSecure" );
378+ hookMethods (longshotMainClazz , chain -> false , "hasSecure" );
317379 }
318380
319381 private void hookOneUI (ClassLoader classLoader ) throws ClassNotFoundException {
320382 var wmScreenshotControllerClazz = classLoader .loadClass ("com.android.server.wm.WmScreenshotController" );
321- hookMethods (wmScreenshotControllerClazz , new ReturnTrueHooker () , "canBeScreenshotTarget" );
383+ hookMethods (wmScreenshotControllerClazz , chain -> true , "canBeScreenshotTarget" );
322384 }
323385
324386 private void hookMethods (Class <?> clazz , Hooker hooker , String ... names ) {
@@ -330,50 +392,16 @@ private void hookMethods(Class<?> clazz, Hooker hooker, String... names) {
330392
331393 private void hookOnResume () throws NoSuchMethodException {
332394 var method = Activity .class .getDeclaredMethod ("onResume" );
333- hook (method ).intercept (new ToastHooker ());
334- }
335-
336- private static class CreateDisplayHooker implements Hooker {
337-
338- @ Override
339- public Object intercept (@ NonNull Chain chain ) throws Throwable {
340- if (Build .VERSION .SDK_INT < Build .VERSION_CODES .UPSIDE_DOWN_CAKE ) {
341- var stackTrace = new Throwable ().getStackTrace ();
342- for (int i = 4 ; i < stackTrace .length && i < 8 ; i ++) {
343- var name = stackTrace [i ].getMethodName ();
344- if (name .equals ("createVirtualDisplayLocked" )) {
345- return chain .proceed ();
346- }
347- }
348- }
349- var args = chain .getArgs ().toArray ();
350- args [1 ] = true ;
351- return chain .proceed (args );
352- }
353- }
354-
355- private static class CheckPermissionHooker implements Hooker {
356-
357- @ Override
358- public Object intercept (@ NonNull Chain chain ) throws Throwable {
359- var permission = chain .getArg (0 );
360- if ("android.permission.CAPTURE_BLACKOUT_CONTENT" .equals (permission )) {
361- var args = chain .getArgs ().toArray ();
362- args [0 ] = "android.permission.READ_FRAME_BUFFER" ;
363- return chain .proceed (args );
364- }
395+ hook (method ).intercept (chain -> {
396+ var activity = (Activity ) chain .getThisObject ();
397+ new AlertDialog .Builder (activity )
398+ .setTitle ("Enable Screenshot" )
399+ .setMessage ("Incorrect module usage, remove this app from scope." )
400+ .setCancelable (false )
401+ .setPositiveButton ("OK" , (dialog , which ) -> System .exit (0 ))
402+ .show ();
365403 return chain .proceed ();
366- }
367- }
368-
369- private static class OplusScreenCaptureHooker implements Hooker {
370-
371- @ Override
372- public Object intercept (@ NonNull Chain chain ) throws Throwable {
373- var args = chain .getArgs ().toArray ();
374- args [0 ] = -1 ;
375- return chain .proceed (args );
376- }
404+ });
377405 }
378406
379407 private static class ScreenCaptureHooker implements Hooker {
@@ -394,92 +422,4 @@ public Object intercept(@NonNull Chain chain) throws Throwable {
394422 return chain .proceed ();
395423 }
396424 }
397-
398- private static class CreateVirtualDisplayLockedHooker implements Hooker {
399-
400- @ Override
401- public Object intercept (@ NonNull Chain chain ) throws Throwable {
402- var caller = (int ) chain .getArg (2 );
403- if (caller >= 10000 && chain .getArg (1 ) == null ) {
404- // not os and not media projection
405- return chain .proceed ();
406- }
407- for (int i = 3 ; i < chain .getArgs ().size (); i ++) {
408- var arg = chain .getArg (i );
409- if (arg instanceof Integer flags ) {
410- flags |= DisplayManager .VIRTUAL_DISPLAY_FLAG_SECURE ;
411- var args = chain .getArgs ().toArray ();
412- args [i ] = flags ;
413- return chain .proceed (args );
414- }
415- }
416- module .log (Log .WARN , TAG , "flag not found in CreateVirtualDisplayLockedHooker" );
417- return chain .proceed ();
418- }
419- }
420-
421- private static class SecureLockedHooker implements Hooker {
422-
423- @ Override
424- public Object intercept (@ NonNull Chain chain ) throws Throwable {
425- if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .UPSIDE_DOWN_CAKE ) {
426- var walker = StackWalker .getInstance ();
427- var match = walker .walk (frames -> frames
428- .map (StackWalker .StackFrame ::getMethodName )
429- .limit (6 )
430- .skip (2 )
431- .anyMatch (s -> s .equals ("setInitialSurfaceControlProperties" ) || s .equals ("createSurfaceLocked" )));
432- if (match ) return chain .proceed ();
433- } else {
434- var stackTrace = new Throwable ().getStackTrace ();
435- for (int i = 4 ; i < stackTrace .length && i < 8 ; i ++) {
436- var name = stackTrace [i ].getMethodName ();
437- if (name .equals ("setInitialSurfaceControlProperties" ) ||
438- name .equals ("createSurfaceLocked" )) {
439- return chain .proceed ();
440- }
441- }
442- }
443- return false ;
444- }
445- }
446-
447- private static class ReturnTrueHooker implements Hooker {
448-
449- @ Override
450- public Object intercept (@ NonNull Chain chain ) {
451- return true ;
452- }
453- }
454-
455- private static class ReturnFalseHooker implements Hooker {
456-
457- @ Override
458- public Object intercept (@ NonNull Chain chain ) {
459- return false ;
460- }
461- }
462-
463- private static class ReturnNullHooker implements Hooker {
464-
465- @ Override
466- public Object intercept (@ NonNull Chain chain ) {
467- return null ;
468- }
469- }
470-
471- private static class ToastHooker implements Hooker {
472-
473- @ Override
474- public Object intercept (@ NonNull Chain chain ) throws Throwable {
475- var activity = (Activity ) chain .getThisObject ();
476- new AlertDialog .Builder (activity )
477- .setTitle ("Enable Screenshot" )
478- .setMessage ("Incorrect module usage, remove this app from scope." )
479- .setCancelable (false )
480- .setPositiveButton ("OK" , (dialog , which ) -> System .exit (0 ))
481- .show ();
482- return chain .proceed ();
483- }
484- }
485425}
0 commit comments