Last active
March 26, 2024 14:45
-
-
Save RikkaW/be3fe4178903702c54ec73b2fc1187fe to your computer and use it in GitHub Desktop.
show window in app_process (impossible to work from Android 14 QPR 3 or Android 15, as addView requires the calling process an Android app process)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
token = new Binder(); | |
try { | |
Context _context = android.app.ActivityThread.systemMain().getSystemContext(); | |
final Context context = new ContextWrapper(_context) { | |
@Override | |
public Object getSystemService(String name) { | |
if (Context.WINDOW_SERVICE.equals(name)) { | |
WindowManager wm = (WindowManager) super.getSystemService(name); | |
if (wm != null) { | |
((android.view.WindowManagerImpl) wm).setDefaultToken(token); | |
} | |
return wm; | |
} | |
return super.getSystemService(name); | |
} | |
}; | |
context.setTheme(android.R.style.Theme_Material_Light); | |
CharSequence label = context.getPackageManager().getApplicationLabel(context.getPackageManager().getApplicationInfo("com.android.settings", 0)); | |
LogUtils.i("label " + label); | |
android.widget.Toast.makeText(context, "test", Toast.LENGTH_LONG).show(); | |
LogUtils.i("toast"); | |
android.view.WindowManager wm = context.getSystemService(WindowManager.class); | |
LogUtils.i("class: " + wm.getClass().getName()); | |
//((android.view.WindowManagerImpl) wm).setDefaultToken(token); | |
LinearLayout root = new LinearLayout(context); | |
root.setBackground(new ColorDrawable(0xffffffff)); | |
TextView textView = new TextView(context); | |
textView.setText("test"); | |
root.addView(textView); | |
Button button = new Button(context); | |
button.setSoundEffectsEnabled(false); | |
button.setText("test"); | |
button.setOnClickListener(new View.OnClickListener() { | |
@Override | |
public void onClick(View v) { | |
Toast.makeText(context, "?!", Toast.LENGTH_LONG).show(); | |
} | |
}); | |
root.addView(button); | |
WindowManager.LayoutParams params = new WindowManager.LayoutParams( | |
WindowManager.LayoutParams.WRAP_CONTENT, | |
WindowManager.LayoutParams.WRAP_CONTENT, | |
WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG, | |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, | |
PixelFormat.TRANSLUCENT); | |
params.gravity = Gravity.CENTER; | |
params.x = 0; | |
params.y = 0; | |
wm.addView(root, params); | |
} catch (Throwable tr) { | |
LogUtils.e(tr.getMessage(), tr); | |
} |
Ok, I figured it out.
public void windowManager(IBinder binder) {
try {
Field sCache = Class.forName("android.os.ServiceManager").getDeclaredField("sCache");
sCache.setAccessible(true);
Method m = sCache.getType().getDeclaredMethod("put", Object.class, Object.class);
m.invoke(sCache.get(null), "window", binder);
handler.post(() -> {
Context context = android.app.ActivityThread.systemMain().getSystemContext();
WindowManager wm = context.getSystemService(WindowManager.class);
Binder token = new Binder();
context = new ContextWrapper(context) {
@Override
public Object getSystemService(String name) {
if (Context.WINDOW_SERVICE.equals(name)) {
WindowManager wm = (WindowManager) super.getSystemService(name);
if (wm != null)
((android.view.WindowManagerImpl) wm).setDefaultToken(token);
return wm;
}
return super.getSystemService(name);
}
@Override
public Looper getMainLooper() {
return Looper.myLooper();
}
};
View view = new View(context) {
final Paint paint = new Paint();
@Override
protected void onDraw(@NonNull Canvas canvas) {
super.onDraw(canvas);
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.RED);
canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
}
};
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
100, 100, WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
PixelFormat.OPAQUE);
params.gravity = Gravity.CENTER;
params.x = 0;
params.y = 0;
params.packageName = "com.termux";
wm.addView(view, params);
});
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
And it works on Android 11.
Thanks @RikkaW.
And unfortunately I am getting this on Android 12.
java.lang.NullPointerException
at android.os.Parcel.createExceptionOrNull(Parcel.java:2431)
at android.os.Parcel.createException(Parcel.java:2409)
at android.os.Parcel.readException(Parcel.java:2392)
at android.os.Parcel.readException(Parcel.java:2334)
at com.android.internal.app.IAppOpsService$Stub$Proxy.reportRuntimeAppOpAccessMessageAndGetConfig(IAppOpsService.java:1666)
at android.app.AppOpsManager$1.reportStackTraceIfNeeded(AppOpsManager.java:290)
at android.app.AppOpsManager$1.onNoted(AppOpsManager.java:265)
at android.app.AppOpsManager.readAndLogNotedAppops(AppOpsManager.java:9359)
at android.os.Parcel.readExceptionCode(Parcel.java:2356)
at android.os.Parcel.readException(Parcel.java:2331)
at android.view.IWindowSession$Stub$Proxy.addToDisplayAsUser(IWindowSession.java:1374)
at android.view.ViewRootImpl.setView(ViewRootImpl.java:1119)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:399)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:133)
at com.termux.x11.CmdEntryPoint.lambda$windowManager$3(CmdEntryPoint.java:286)
at com.termux.x11.CmdEntryPoint.$r8$lambda$MIV7qHiVNsG1buhNHJnI7A8pV3A(CmdEntryPoint.java:0)
at com.termux.x11.CmdEntryPoint$$ExternalSyntheticLambda1.run(R8$$SyntheticClass:0)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at com.termux.x11.CmdEntryPoint.main(CmdEntryPoint.java:71)
at java.lang.reflect.Method.invoke(Native Method)
at com.termux.x11.Loader.main(Loader.java:26)
at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:355)
Caused by: android.os.RemoteException: Remote stack trace:
at com.android.internal.util.AnnotationValidations.validate(AnnotationValidations.java:129)
at android.app.SyncNotedAppOp.<init>(SyncNotedAppOp.java:227)
at android.app.SyncNotedAppOp$1.createFromParcel(SyncNotedAppOp.java:243)
at android.app.SyncNotedAppOp$1.createFromParcel(SyncNotedAppOp.java:235)
at com.android.internal.app.IAppOpsService$Stub.onTransact(IAppOpsService.java:728)
Any suggestions?
Change opPackageName? I don't remember:(
Btw, this will never work starting from Android 14 QPR 3 or Android 15, as addView now checks if the calling process is a valid Android app process.
Maybe there is some workaround for this? The most important thing I need is to draw something as an overlay from background process.
I am not writing viruses. Simply some oems put code to limit GPU performance of background apps.
Maybe SurfaceControl.Transactions?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@RikkaW I have some problems with creating some overlay from process started with
app_process
in application sandbox of other app.I know "window" service is inaccessible from processes started this way, but I am sending IBinder of that service from Activity via AIDL and injecting it to ServiceManager's
sCache
manually, so WindowManagerGlobal can access it.I am trying to create overlay with this code:
But I am getting only this unclear exception
Both activity I am sending IBinder from and application where I want to start this snippet have "Draw over apps" permission but it does not help.
I tried to make a proxy for IBinder to make my snippet inherit Uid of another application (which owns Activity) with adding this code to ContextWrapper
and wrapping "window"'s IBinder with
But it does not seem to work, I am getting the same exception.
Seems like I found a reason in system-wide logcat.