Implements a pipe to render AWT screen for mod installer

This commit is contained in:
khanhduytran0 2020-11-05 09:37:45 +07:00
parent 64692e19dd
commit 0f429f09d9
6 changed files with 75 additions and 46 deletions

View File

@ -1,25 +0,0 @@
package net.kdt.pojavlaunch;
import java.net.*;
import java.io.*;
import dalvik.system.*;
public class FakeURLClassLoader extends URLClassLoader
{
private DexClassLoader m;
public FakeURLClassLoader(java.lang.String dexPath, java.lang.String optimizedDirectory, java.lang.String librarySearchPath, java.lang.ClassLoader parent) throws MalformedURLException {
super(new URL[] { new File("test.jar").toURI().toURL() }, null);
m = new DexClassLoader(dexPath, optimizedDirectory, librarySearchPath, parent);
}
@Override
public java.lang.String findLibrary(String name) {
return m.findLibrary(name);
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException
{
return m.loadClass(name);
}
}

View File

@ -8,9 +8,12 @@ import com.oracle.dalvik.*;
import java.io.*; import java.io.*;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.*; import java.util.*;
import org.lwjgl.glfw.*;
public class InstallModActivity extends LoggableActivity public class InstallModActivity extends LoggableActivity
{ {
public static volatile boolean IS_JRE_RUNNING;
private TextureView mTextureView; private TextureView mTextureView;
private LinearLayout contentLog; private LinearLayout contentLog;
private TextView textLog; private TextView textLog;
@ -32,7 +35,7 @@ public class InstallModActivity extends LoggableActivity
logFile.delete(); logFile.delete();
logFile.createNewFile(); logFile.createNewFile();
logStream = new PrintStream(logFile.getAbsolutePath()); logStream = new PrintStream(logFile.getAbsolutePath());
this.contentLog = (LinearLayout) findViewById(R.id.content_log_layout); this.contentLog = findViewById(R.id.content_log_layout);
this.contentScroll = (ScrollView) findViewById(R.id.content_log_scroll); this.contentScroll = (ScrollView) findViewById(R.id.content_log_scroll);
this.textLog = (TextView) contentScroll.getChildAt(0); this.textLog = (TextView) contentScroll.getChildAt(0);
this.toggleLog = (ToggleButton) findViewById(R.id.content_log_toggle_log); this.toggleLog = (ToggleButton) findViewById(R.id.content_log_toggle_log);
@ -55,24 +58,32 @@ public class InstallModActivity extends LoggableActivity
mTextureView = findViewById(R.id.installmod_surfaceview); mTextureView = findViewById(R.id.installmod_surfaceview);
mTextureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener(){ mTextureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener(){
private boolean isAvailableCalled = false;
@Override @Override
public void onSurfaceTextureAvailable(SurfaceTexture tex, int w, int h) { public void onSurfaceTextureAvailable(SurfaceTexture tex, final int w, final int h) {
try { if (!isAvailableCalled) {
Surface surface = new Surface(tex); isAvailableCalled = true;
Field field = surface.getClass().getDeclaredField("mNativeObject"); } else return;
field.setAccessible(true);
JREUtils.setupBridgeSurfaceAWT((long) field.get(surface)); // final Surface surface = new Surface(tex);
} catch (Throwable th) { new Thread(new Runnable(){
Tools.showError(InstallModActivity.this, th, true); @Override
} public void run() {
while (IS_JRE_RUNNING) {
Canvas canvas = mTextureView.lockCanvas();
JREUtils.renderAWTScreenFrame(canvas, w, h);
mTextureView.unlockCanvasAndPost(canvas);
}
}
}, "AWTSurfaceUpdater").start();
new Thread(new Runnable(){ new Thread(new Runnable(){
@Override @Override
public void run() { public void run() {
launchJavaRuntime(modFile, javaArgs); launchJavaRuntime(modFile, javaArgs);
// finish();
} }
}).start(); }, "JREMainThread").start();
} }
@Override @Override
@ -128,6 +139,8 @@ public class InstallModActivity extends LoggableActivity
javaArgList.add("-Xbootclasspath/a" + libStr.toString()); javaArgList.add("-Xbootclasspath/a" + libStr.toString());
} }
javaArgList.add("-Dcacio.managed.screensize=" + CallbackBridge.windowWidth + "x" + CallbackBridge.windowHeight);
File cacioArgOverrideFile = new File(cacioAwtLibPath, "overrideargs.txt"); File cacioArgOverrideFile = new File(cacioAwtLibPath, "overrideargs.txt");
if (cacioArgOverrideFile.exists()) { if (cacioArgOverrideFile.exists()) {
javaArgList.addAll(Arrays.asList(Tools.read(cacioArgOverrideFile.getAbsolutePath()).split(" "))); javaArgList.addAll(Arrays.asList(Tools.read(cacioArgOverrideFile.getAbsolutePath()).split(" ")));

View File

@ -208,7 +208,7 @@ public class JREUtils
public static native void setupBridgeWindow(Object surface); public static native void setupBridgeWindow(Object surface);
// TODO AWT Android port // TODO AWT Android port
public static native void setupBridgeSurfaceAWT(long surface); public static native void renderAWTScreenFrame(Object canvas, int width, int height);
// BEFORE Load and execute PIE binary using dlopen and dlsym("main") // BEFORE Load and execute PIE binary using dlopen and dlsym("main")
// AFTER: [Deprecated] // AFTER: [Deprecated]

View File

@ -9,6 +9,7 @@ LOCAL_MODULE := pojavexec
LOCAL_CFLAGS += -DDEBUG LOCAL_CFLAGS += -DDEBUG
# -DGLES_TEST # -DGLES_TEST
LOCAL_SRC_FILES := \ LOCAL_SRC_FILES := \
awt_bridge.c \
egl_bridge.c \ egl_bridge.c \
input_bridge_v3.c \ input_bridge_v3.c \
jre_launcher.c \ jre_launcher.c \

View File

@ -0,0 +1,44 @@
#include <jni.h>
#include "utils.h"
// jclass class_awt;
// jmethodID method_awt;
// TODO: check for memory leaks
JNIEXPORT void JNICALL Java_net_kdt_pojavlaunch_JREUtils_renderAWTScreenFrame(JNIEnv* env, jclass clazz, jobject canvas, jint width, jint height) {
if (runtimeJNIEnvPtr_ANDROID == NULL) return;
int *rgbArray;
jintArray jreRgbArray, androidRgbArray;
jclass class_awt = (*runtimeJNIEnvPtr_ANDROID)->FindClass(runtimeJNIEnvPtr_ANDROID, "net/java/openjdk/cacio/ctc/CTCScreen");
jmethodID method_awt = (*runtimeJNIEnvPtr_ANDROID)->GetStaticMethodID(runtimeJNIEnvPtr_ANDROID, class_awt, "getCurrentScreenRGB");
jreRgbArray = (jintArray) (*runtimeJNIEnvPtr_ANDROID)->CallStaticObjectMethod(
runtimeJNIEnvPtr_ANDROID,
class_awt,
method_awt
);
// Copy JRE RGB array memory to Android.
int arrayLength = (*runtimeJNIEnvPtr_ANDROID)->GetArrayLength(runtimeJNIEnvPtr_ANDROID, jreRgbArray);
rgbArray = (*runtimeJNIEnvPtr_ANDROID)->GetIntArrayElements(runtimeJNIEnvPtr_ANDROID, jreRgbArray, 0);
androidRgbArray = (*runtimeJNIEnvPtr_ANDROID)->NewIntArray(runtimeJNIEnvPtr_ANDROID, arrayLength);
(*runtimeJNIEnvPtr_ANDROID)->SetIntArrayRegion(runtimeJNIEnvPtr_ANDROID, androidRgbArray, 0, arrayLength, rgbArray);
// Maybe use Skia lib instead?
jclass class_canvas = (*dalvikJNIEnvPtr_ANDROID)->GetObjectClass(dalvikJNIEnvPtr_ANDROID, canvas);
jmethodID method_canvas = (*dalvikJNIEnvPtr_ANDROID)->GetMethodID(dalvikJNIEnvPtr_ANDROID, class_canvas, "drawBitmap", "[IIIFFIIZLandroid/graphics/Paint;");
(*runtimeJNIEnvPtr_ANDROID)->CallVoidMethod(
runtimeJNIEnvPtr_ANDROID,
canvas,
method_canvas,
rgbArray, 0, width, 0, 0, width, height, JNI_TRUE, NULL
);
// android_graphics_Canvas_native_drawBitmap
(*runtimeJNIEnvPtr_ANDROID)->ReleaseIntArrayElements(runtimeJNIEnvPtr_ANDROID, jreRgbArray, rgbArray);
(*dalvikJNIEnvPtr_ANDROID)->DeleteLocalRef(dalvikJNIEnvPtr_ANDROID, androidRgbArray);
// free(rgbArray);
}

View File

@ -34,10 +34,6 @@ EGLConfig config;
typedef jint RegalMakeCurrent_func(EGLContext context); typedef jint RegalMakeCurrent_func(EGLContext context);
JNIEXPORT void JNICALL Java_net_kdt_pojavlaunch_JREUtils_setupBridgeWindow(JNIEnv* env, jclass clazz, jobject surface) {
potatoBridge.androidWindow = ANativeWindow_fromSurface(env, surface);
}
// Called from JNI_OnLoad of liblwjgl_opengl // Called from JNI_OnLoad of liblwjgl_opengl
void pojav_openGLOnLoad() { void pojav_openGLOnLoad() {