Skip to content

Commit 9029324

Browse files
act262rom1v
authored andcommitted
Fix meizu 16th NPE
Fill AppInfo to avoid NullPointerException on some devices. Fixes <#365> Signed-off-by: Romain Vimont <[email protected]>
1 parent 213c468 commit 9029324

File tree

2 files changed

+44
-0
lines changed

2 files changed

+44
-0
lines changed

server/src/main/java/com/genymobile/scrcpy/ScreenEncoder.java

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public boolean consumeRotationChange() {
5353

5454
public void streamScreen(Device device, FileDescriptor fd) throws IOException {
5555
Workarounds.prepareMainLooper();
56+
Workarounds.fillAppInfo();
5657

5758
MediaFormat format = createFormat(bitRate, maxFps, iFrameInterval);
5859
device.setRotationListener(this);

server/src/main/java/com/genymobile/scrcpy/Workarounds.java

+43
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
package com.genymobile.scrcpy;
22

3+
import android.annotation.SuppressLint;
4+
import android.content.pm.ApplicationInfo;
35
import android.os.Looper;
46

7+
import java.lang.reflect.Constructor;
8+
import java.lang.reflect.Field;
9+
510
public final class Workarounds {
611
private Workarounds() {
712
// not instantiable
@@ -18,4 +23,42 @@ public static void prepareMainLooper() {
1823
// <https://github.com/Genymobile/scrcpy/issues/921>
1924
Looper.prepareMainLooper();
2025
}
26+
27+
@SuppressLint("PrivateApi")
28+
public static void fillAppInfo() {
29+
try {
30+
// ActivityThread activityThread = new ActivityThread();
31+
Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
32+
Constructor<?> activityThreadConstructor = activityThreadClass.getDeclaredConstructor();
33+
activityThreadConstructor.setAccessible(true);
34+
Object activityThread = activityThreadConstructor.newInstance();
35+
36+
// ActivityThread.sCurrentActivityThread = activityThread;
37+
Field sCurrentActivityThreadField = activityThreadClass.getDeclaredField("sCurrentActivityThread");
38+
sCurrentActivityThreadField.setAccessible(true);
39+
sCurrentActivityThreadField.set(null, activityThread);
40+
41+
// ActivityThread.AppBindData appBindData = new ActivityThread.AppBindData();
42+
Class<?> appBindDataClass = Class.forName("android.app.ActivityThread$AppBindData");
43+
Constructor<?> appBindDataConstructor = appBindDataClass.getDeclaredConstructor();
44+
appBindDataConstructor.setAccessible(true);
45+
Object appBindData = appBindDataConstructor.newInstance();
46+
47+
ApplicationInfo applicationInfo = new ApplicationInfo();
48+
applicationInfo.packageName = "com.genymobile.scrcpy";
49+
50+
// appBindData.appInfo = applicationInfo;
51+
Field appInfo = appBindDataClass.getDeclaredField("appInfo");
52+
appInfo.setAccessible(true);
53+
appInfo.set(appBindData, applicationInfo);
54+
55+
// activityThread.mBoundApplication = appBindData;
56+
Field mBoundApplicationField = activityThreadClass.getDeclaredField("mBoundApplication");
57+
mBoundApplicationField.setAccessible(true);
58+
mBoundApplicationField.set(activityThread, appBindData);
59+
} catch (Throwable throwable) {
60+
// this is a workaround, so failing is not an error
61+
Ln.w("Could not fill app info: " + throwable.getMessage());
62+
}
63+
}
2164
}

0 commit comments

Comments
 (0)