Move ActivityThread instance

An ActivityThread instance will be needed from several classes.
This commit is contained in:
Romain Vimont
2023-06-16 23:36:40 +02:00
parent 48a00fb481
commit 95e61e2a0b
2 changed files with 46 additions and 8 deletions

View File

@@ -1,5 +1,7 @@
package com.genymobile.scrcpy; package com.genymobile.scrcpy;
import com.genymobile.scrcpy.wrappers.ActivityThread;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.app.Application; import android.app.Application;
@@ -20,8 +22,7 @@ import java.lang.reflect.Method;
public final class Workarounds { public final class Workarounds {
private static Class<?> activityThreadClass; private static boolean activityThreadFilled;
private static Object activityThread;
private Workarounds() { private Workarounds() {
// not instantiable // not instantiable
@@ -42,17 +43,16 @@ public final class Workarounds {
@SuppressLint("PrivateApi,DiscouragedPrivateApi") @SuppressLint("PrivateApi,DiscouragedPrivateApi")
private static void fillActivityThread() throws Exception { private static void fillActivityThread() throws Exception {
if (activityThread == null) { if (!activityThreadFilled) {
// ActivityThread activityThread = new ActivityThread(); Class<?> activityThreadClass = ActivityThread.getActivityThreadClass();
activityThreadClass = Class.forName("android.app.ActivityThread"); Object activityThread = ActivityThread.getActivityThread();
Constructor<?> activityThreadConstructor = activityThreadClass.getDeclaredConstructor();
activityThreadConstructor.setAccessible(true);
activityThread = activityThreadConstructor.newInstance();
// ActivityThread.sCurrentActivityThread = activityThread; // ActivityThread.sCurrentActivityThread = activityThread;
Field sCurrentActivityThreadField = activityThreadClass.getDeclaredField("sCurrentActivityThread"); Field sCurrentActivityThreadField = activityThreadClass.getDeclaredField("sCurrentActivityThread");
sCurrentActivityThreadField.setAccessible(true); sCurrentActivityThreadField.setAccessible(true);
sCurrentActivityThreadField.set(null, activityThread); sCurrentActivityThreadField.set(null, activityThread);
activityThreadFilled = true;
} }
} }
@@ -75,6 +75,9 @@ public final class Workarounds {
appInfoField.setAccessible(true); appInfoField.setAccessible(true);
appInfoField.set(appBindData, applicationInfo); appInfoField.set(appBindData, applicationInfo);
Class<?> activityThreadClass = ActivityThread.getActivityThreadClass();
Object activityThread = ActivityThread.getActivityThread();
// activityThread.mBoundApplication = appBindData; // activityThread.mBoundApplication = appBindData;
Field mBoundApplicationField = activityThreadClass.getDeclaredField("mBoundApplication"); Field mBoundApplicationField = activityThreadClass.getDeclaredField("mBoundApplication");
mBoundApplicationField.setAccessible(true); mBoundApplicationField.setAccessible(true);
@@ -95,6 +98,9 @@ public final class Workarounds {
baseField.setAccessible(true); baseField.setAccessible(true);
baseField.set(app, FakeContext.get()); baseField.set(app, FakeContext.get());
Class<?> activityThreadClass = ActivityThread.getActivityThreadClass();
Object activityThread = ActivityThread.getActivityThread();
// activityThread.mInitialApplication = app; // activityThread.mInitialApplication = app;
Field mInitialApplicationField = activityThreadClass.getDeclaredField("mInitialApplication"); Field mInitialApplicationField = activityThreadClass.getDeclaredField("mInitialApplication");
mInitialApplicationField.setAccessible(true); mInitialApplicationField.setAccessible(true);

View File

@@ -0,0 +1,32 @@
package com.genymobile.scrcpy.wrappers;
import java.lang.reflect.Constructor;
public class ActivityThread {
private static final Class<?> activityThreadClass;
private static final Object activityThread;
static {
try {
activityThreadClass = Class.forName("android.app.ActivityThread");
Constructor<?> activityThreadConstructor = activityThreadClass.getDeclaredConstructor();
activityThreadConstructor.setAccessible(true);
activityThread = activityThreadConstructor.newInstance();
} catch (Exception e) {
throw new AssertionError(e);
}
}
private ActivityThread() {
// only static methods
}
public static Object getActivityThread() {
return activityThread;
}
public static Class<?> getActivityThreadClass() {
return activityThreadClass;
}
}