Skip to content

Commit

Permalink
Fix meizu 16th NPE
Browse files Browse the repository at this point in the history
Fill AppInfo to avoid NullPointerException on some devices.

Fixes <#365>

Signed-off-by: Romain Vimont <rom@rom1v.com>
  • Loading branch information
act262 authored and rom1v committed Nov 19, 2019
1 parent 213c468 commit 9029324
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 0 deletions.
Expand Up @@ -53,6 +53,7 @@ public boolean consumeRotationChange() {

public void streamScreen(Device device, FileDescriptor fd) throws IOException {
Workarounds.prepareMainLooper();
Workarounds.fillAppInfo();

MediaFormat format = createFormat(bitRate, maxFps, iFrameInterval);
device.setRotationListener(this);
Expand Down
43 changes: 43 additions & 0 deletions server/src/main/java/com/genymobile/scrcpy/Workarounds.java
@@ -1,7 +1,12 @@
package com.genymobile.scrcpy;

import android.annotation.SuppressLint;
import android.content.pm.ApplicationInfo;
import android.os.Looper;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

public final class Workarounds {
private Workarounds() {
// not instantiable
Expand All @@ -18,4 +23,42 @@ public static void prepareMainLooper() {
// <https://github.com/Genymobile/scrcpy/issues/921>
Looper.prepareMainLooper();
}

@SuppressLint("PrivateApi")
public static void fillAppInfo() {
try {
// ActivityThread activityThread = new ActivityThread();
Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
Constructor<?> activityThreadConstructor = activityThreadClass.getDeclaredConstructor();
activityThreadConstructor.setAccessible(true);
Object activityThread = activityThreadConstructor.newInstance();

// ActivityThread.sCurrentActivityThread = activityThread;
Field sCurrentActivityThreadField = activityThreadClass.getDeclaredField("sCurrentActivityThread");
sCurrentActivityThreadField.setAccessible(true);
sCurrentActivityThreadField.set(null, activityThread);

// ActivityThread.AppBindData appBindData = new ActivityThread.AppBindData();
Class<?> appBindDataClass = Class.forName("android.app.ActivityThread$AppBindData");
Constructor<?> appBindDataConstructor = appBindDataClass.getDeclaredConstructor();
appBindDataConstructor.setAccessible(true);
Object appBindData = appBindDataConstructor.newInstance();

ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.packageName = "com.genymobile.scrcpy";

// appBindData.appInfo = applicationInfo;
Field appInfo = appBindDataClass.getDeclaredField("appInfo");
appInfo.setAccessible(true);
appInfo.set(appBindData, applicationInfo);

// activityThread.mBoundApplication = appBindData;
Field mBoundApplicationField = activityThreadClass.getDeclaredField("mBoundApplication");
mBoundApplicationField.setAccessible(true);
mBoundApplicationField.set(activityThread, appBindData);
} catch (Throwable throwable) {
// this is a workaround, so failing is not an error
Ln.w("Could not fill app info: " + throwable.getMessage());
}
}
}

0 comments on commit 9029324

Please sign in to comment.