Skip to content

Commit

Permalink
Update to latest upstream we can get
Browse files Browse the repository at this point in the history
  • Loading branch information
SolDev69 committed Jan 18, 2025
2 parents c9b5d85 + ed89b44 commit 2ad4e49
Show file tree
Hide file tree
Showing 15 changed files with 262 additions and 148 deletions.
3 changes: 2 additions & 1 deletion app_pojavlauncher/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@
</activity>
<activity
android:name=".LauncherActivity"
android:label="@string/app_short_name" />
android:label="@string/app_short_name"
android:windowSoftInputMode="adjustResize"/>
<activity
android:name=".ImportControlActivity"
android:configChanges="keyboard|keyboardHidden"
Expand Down
59 changes: 45 additions & 14 deletions app_pojavlauncher/src/main/java/com/kdt/mcgui/mcAccountSpinner.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.Toast;

import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.AppCompatSpinner;
import androidx.core.content.res.ResourcesCompat;

Expand Down Expand Up @@ -188,7 +189,10 @@ protected void onDraw(Canvas canvas) {
}

public void removeCurrentAccount(){
int position = getSelectedItemPosition();
removeAccount(getSelectedItemPosition());
}

private void removeAccount(int position) {
if(position == 0) return;
File accountFile = new File(Tools.DIR_ACCOUNT_NEW, mAccountList.get(position)+".json");
if(accountFile.exists()) accountFile.delete();
Expand Down Expand Up @@ -321,8 +325,9 @@ private void setImageFromSelectedAccount(){
BitmapDrawable oldBitmapDrawable = mHeadDrawable;

if(mSelectecAccount != null){
ExtendedTextView view = ((ExtendedTextView) getSelectedView());
if(view != null){
View layout = getSelectedView();
if(layout != null){
ExtendedTextView view = layout.findViewById(R.id.account_item);
Bitmap bitmap = mSelectecAccount.getSkinFace();
if(bitmap != null) {
mHeadDrawable = new BitmapDrawable(getResources(), bitmap);
Expand All @@ -339,8 +344,7 @@ private void setImageFromSelectedAccount(){
}
}


private static class AccountAdapter extends ArrayAdapter<String> {
private class AccountAdapter extends ArrayAdapter<String> {

private final HashMap<String, Drawable> mImageCache = new HashMap<>();
public AccountAdapter(@NonNull Context context, int resource, @NonNull String[] objects) {
Expand All @@ -349,20 +353,19 @@ public AccountAdapter(@NonNull Context context, int resource, @NonNull String[]

@Override
public View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
return getView(position, convertView, parent);
}

@NonNull
@Override
public View getView(int position, View convertView, @NonNull ViewGroup parent) {
if(convertView == null){
convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_minecraft_account, parent, false);
}
ExtendedTextView textview = (ExtendedTextView) convertView;

ExtendedTextView textview = convertView.findViewById(R.id.account_item);
ImageView deleteButton = convertView.findViewById(R.id.delete_account_button);
textview.setText(super.getItem(position));

// Handle the "Add account section"
if(position == 0) textview.setCompoundDrawables(ResourcesCompat.getDrawable(parent.getResources(), R.drawable.ic_add, null), null, null, null);
if(position == 0) {
textview.setCompoundDrawables(ResourcesCompat.getDrawable(parent.getResources(), R.drawable.ic_add, null), null, null, null);
deleteButton.setVisibility(View.GONE);
}
else {
String username = super.getItem(position);
Drawable accountHead = mImageCache.get(username);
Expand All @@ -371,9 +374,37 @@ public View getView(int position, View convertView, @NonNull ViewGroup parent) {
mImageCache.put(username, accountHead);
}
textview.setCompoundDrawables(accountHead, null, null, null);

deleteButton.setVisibility(View.VISIBLE);
deleteButton.setOnClickListener(v -> {
showDeleteDialog(getContext(), position);
});
}
return convertView;
}



@NonNull
@Override
public View getView(int position, View convertView, @NonNull ViewGroup parent) {
View view = getDropDownView(position, convertView, parent);
view.findViewById(R.id.delete_account_button).setVisibility(View.GONE);
return view;
}

private void showDeleteDialog(Context context, int position) {
new AlertDialog.Builder(context)
.setMessage(R.string.warning_remove_account)
.setPositiveButton(android.R.string.cancel, null)
.setNeutralButton(R.string.global_delete, (dialog, which) -> {
onDetachedFromWindow();
removeAccount(position);
})
.show();
}
}



}
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public class LauncherActivity extends BaseActivity {

private mcAccountSpinner mAccountSpinner;
private FragmentContainerView mFragmentView;
private ImageButton mSettingsButton, mDeleteAccountButton;
private ImageButton mSettingsButton;
private ProgressLayout mProgressLayout;
private ProgressServiceKeeper mProgressServiceKeeper;
private ModloaderInstallTracker mInstallTracker;
Expand Down Expand Up @@ -101,13 +101,6 @@ public void onFragmentResumed(@NonNull FragmentManager fm, @NonNull Fragment f)
}
};

/* Listener for account deletion */
private final View.OnClickListener mAccountDeleteButtonListener = v -> new AlertDialog.Builder(this)
.setMessage(R.string.warning_remove_account)
.setPositiveButton(android.R.string.cancel, null)
.setNeutralButton(R.string.global_delete, (dialog, which) -> mAccountSpinner.removeCurrentAccount())
.show();

private final ExtraListener<Boolean> mLaunchGameListener = (key, value) -> {
if(mProgressLayout.hasProcesses()){
Toast.makeText(this, R.string.tasks_ongoing, Toast.LENGTH_LONG).show();
Expand Down Expand Up @@ -200,7 +193,6 @@ protected void onCreate(Bundle savedInstanceState) {
ProgressKeeper.addTaskCountListener((mProgressServiceKeeper = new ProgressServiceKeeper(this)));

mSettingsButton.setOnClickListener(mSettingButtonListener);
mDeleteAccountButton.setOnClickListener(mAccountDeleteButtonListener);
ProgressKeeper.addTaskCountListener(mProgressLayout);
ExtraCore.addExtraListener(ExtraConstants.BACK_PREFERENCE, mBackPreferenceListener);
ExtraCore.addExtraListener(ExtraConstants.SELECT_AUTH_METHOD, mSelectAuthMethod);
Expand Down Expand Up @@ -343,7 +335,6 @@ public void askForNotificationPermission(Runnable onSuccessRunnable) {
private void bindViews(){
mFragmentView = findViewById(R.id.container_fragment);
mSettingsButton = findViewById(R.id.setting_button);
mDeleteAccountButton = findViewById(R.id.delete_account_button);
mAccountSpinner = findViewById(R.id.account_spinner);
mProgressLayout = findViewById(R.id.progress_layout);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@ public RightClickGesture(Handler mHandler) {
public final void inputEvent() {
if(!mGestureEnabled) return;
if(submit()) {
mGestureStartX = CallbackBridge.mouseX;
mGestureStartY = CallbackBridge.mouseY;
mGestureStartX = mGestureEndX = CallbackBridge.mouseX;
mGestureStartY = mGestureEndY = CallbackBridge.mouseY;
mGestureEnabled = false;
mGestureValid = true;
}
}

public void setMotion(float deltaX, float deltaY) {
System.out.println("set motion called");
mGestureEndX += deltaX;
mGestureEndY += deltaY;
}
Expand All @@ -49,6 +50,7 @@ public void onGestureCancelled(boolean isSwitching) {
mGestureEnabled = true;
if(!mGestureValid || isSwitching) return;
boolean fingerStill = LeftClickGesture.isFingerStill(mGestureStartX, mGestureStartY, mGestureEndX, mGestureEndY, LeftClickGesture.FINGER_STILL_THRESHOLD);
System.out.println("Right click: " + fingerStill);
if(!fingerStill) return;
CallbackBridge.sendMouseButton(LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_RIGHT, true);
CallbackBridge.sendMouseButton(LwjglGlfwKeycode.GLFW_MOUSE_BUTTON_RIGHT, false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,21 @@
import android.content.pm.PackageManager;
import android.util.Log;

import java.io.File;

public class FFmpegPlugin {
public static boolean isAvailable = false;
public static String libraryPath;
public static String executablePath;
public static void discover(Context context) {
PackageManager manager = context.getPackageManager();
try {
PackageInfo ffmpegPluginInfo = manager.getPackageInfo("net.kdt.pojavlaunch.ffmpeg", PackageManager.GET_SHARED_LIBRARY_FILES);
libraryPath = ffmpegPluginInfo.applicationInfo.nativeLibraryDir;
isAvailable = true;
File ffmpegExecutable = new File(libraryPath, "libffmpeg.so");
executablePath = ffmpegExecutable.getAbsolutePath();
// Older plugin versions still have the old executable location
isAvailable = ffmpegExecutable.exists();
}catch (Exception e) {
Log.i("FFmpegPlugin", "Failed to discover plugin", e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ public static void setJavaEnvironment(Activity activity, String jreHome) throws
envMap.put("LD_LIBRARY_PATH", LD_LIBRARY_PATH);
envMap.put("PATH", jreHome + "/bin:" + Os.getenv("PATH"));
if(FFmpegPlugin.isAvailable) {
envMap.put("PATH", FFmpegPlugin.libraryPath+":"+envMap.get("PATH"));
envMap.put("POJAV_FFMPEG_PATH", FFmpegPlugin.executablePath);
}

if(LOCAL_RENDERER != null) {
Expand Down Expand Up @@ -404,7 +404,8 @@ public static List<String> getJavaArgs(Context ctx, String runtimeHome, String u

"-Dnet.minecraft.clientmodname=" + Tools.APP_NAME,
"-Dfml.earlyprogresswindow=false", //Forge 1.14+ workaround
"-Dloader.disable_forked_guis=true"
"-Dloader.disable_forked_guis=true",
"-Djdk.lang.Process.launchMechanism=FORK" // Default is POSIX_SPAWN which requires starting jspawnhelper, which doesn't work on Android
));
if(LauncherPreferences.PREF_ARC_CAPES) {
overridableArguments.add("-javaagent:"+new File(Tools.DIR_DATA,"arc_dns_injector/arc_dns_injector.jar").getAbsolutePath()+"=23.95.137.176");
Expand Down
2 changes: 2 additions & 0 deletions app_pojavlauncher/src/main/jni/Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ LOCAL_SRC_FILES := \
jre_launcher.c \
utils.c \
stdio_is.c \
java_exec_hooks.c \
lwjgl_dlopen_hook.c \
driver_helper/nsbypass.c

ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
Expand Down
14 changes: 9 additions & 5 deletions app_pojavlauncher/src/main/jni/egl_bridge.c
Original file line number Diff line number Diff line change
Expand Up @@ -499,14 +499,18 @@ EXTERNAL_API void* pojavCreateContext(void* contextSrc) {
}
}

EXTERNAL_API JNIEXPORT jlong JNICALL
Java_org_lwjgl_vulkan_VK_getVulkanDriverHandle(ABI_COMPAT JNIEnv *env, ABI_COMPAT jclass thiz) {
printf("EGLBridge: LWJGL-side Vulkan loader requested the Vulkan handle\n");
// The code below still uses the env var because
void* maybe_load_vulkan() {
// We use the env var because
// 1. it's easier to do that
// 2. it won't break if something will try to load vulkan and osmesa simultaneously
if(getenv("VULKAN_PTR") == NULL) load_vulkan();
return strtoul(getenv("VULKAN_PTR"), NULL, 0x10);
return (void*) strtoul(getenv("VULKAN_PTR"), NULL, 0x10);
}

EXTERNAL_API JNIEXPORT jlong JNICALL
Java_org_lwjgl_vulkan_VK_getVulkanDriverHandle(ABI_COMPAT JNIEnv *env, ABI_COMPAT jclass thiz) {
printf("EGLBridge: LWJGL-side Vulkan loader requested the Vulkan handle\n");
return (jlong) maybe_load_vulkan();
}

EXTERNAL_API JNIEXPORT void JNICALL
Expand Down
80 changes: 1 addition & 79 deletions app_pojavlauncher/src/main/jni/input_bridge_v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@
#define EVENT_TYPE_MOUSE_BUTTON 1006
#define EVENT_TYPE_SCROLL 1007

jint (*orig_ProcessImpl_forkAndExec)(JNIEnv *env, jobject process, jint mode, jbyteArray helperpath, jbyteArray prog, jbyteArray argBlock, jint argc, jbyteArray envBlock, jint envc, jbyteArray dir, jintArray std_fds, jboolean redirectErrorStream);

static void registerFunctions(JNIEnv *env);

jint JNI_OnLoad(JavaVM* vm, __attribute__((unused)) void* reserved) {
Expand Down Expand Up @@ -59,7 +57,7 @@ jint JNI_OnLoad(JavaVM* vm, __attribute__((unused)) void* reserved) {
jobject mouseDownBufferJ = (*solcraft_environ->runtimeJNIEnvPtr_JRE)->GetStaticObjectField(solcraft_environ->runtimeJNIEnvPtr_JRE, solcraft_environ->vmGlfwClass, field_mouseDownBuffer);
solcraft_environ->mouseDownBuffer = (*solcraft_environ->runtimeJNIEnvPtr_JRE)->GetDirectBufferAddress(solcraft_environ->runtimeJNIEnvPtr_JRE, mouseDownBufferJ);
hookExec();
installLinkerBugMitigation();
installLwjglDlopenHook();
installEMUIIteratorMititgation();
}

Expand Down Expand Up @@ -230,82 +228,6 @@ void sendData(int type, int i1, int i2, int i3, int i4) {
atomic_fetch_add_explicit(&solcraft_environ->eventCounter, 1, memory_order_acquire);
}

/**
* Hooked version of java.lang.UNIXProcess.forkAndExec()
* which is used to handle the "open" command.
*/
jint
hooked_ProcessImpl_forkAndExec(JNIEnv *env, jobject process, jint mode, jbyteArray helperpath, jbyteArray prog, jbyteArray argBlock, jint argc, jbyteArray envBlock, jint envc, jbyteArray dir, jintArray std_fds, jboolean redirectErrorStream) {
char *pProg = (char *)((*env)->GetByteArrayElements(env, prog, NULL));

// Here we only handle the "xdg-open" command
if (strcmp(basename(pProg), "xdg-open") != 0) {
(*env)->ReleaseByteArrayElements(env, prog, (jbyte *)pProg, 0);
return orig_ProcessImpl_forkAndExec(env, process, mode, helperpath, prog, argBlock, argc, envBlock, envc, dir, std_fds, redirectErrorStream);
}
(*env)->ReleaseByteArrayElements(env, prog, (jbyte *)pProg, 0);

Java_org_lwjgl_glfw_CallbackBridge_nativeClipboard(env, NULL, /* CLIPBOARD_OPEN */ 2002, argBlock);
return 0;
}

void hookExec() {
jclass cls;
orig_ProcessImpl_forkAndExec = dlsym(RTLD_DEFAULT, "Java_java_lang_UNIXProcess_forkAndExec");
if (!orig_ProcessImpl_forkAndExec) {
orig_ProcessImpl_forkAndExec = dlsym(RTLD_DEFAULT, "Java_java_lang_ProcessImpl_forkAndExec");
cls = (*solcraft_environ->runtimeJNIEnvPtr_JRE)->FindClass(solcraft_environ->runtimeJNIEnvPtr_JRE, "java/lang/ProcessImpl");
} else {
cls = (*solcraft_environ->runtimeJNIEnvPtr_JRE)->FindClass(solcraft_environ->runtimeJNIEnvPtr_JRE, "java/lang/UNIXProcess");
}
JNINativeMethod methods[] = {
{"forkAndExec", "(I[B[B[BI[BI[B[IZ)I", (void *)&hooked_ProcessImpl_forkAndExec}
};
(*solcraft_environ->runtimeJNIEnvPtr_JRE)->RegisterNatives(solcraft_environ->runtimeJNIEnvPtr_JRE, cls, methods, 1);
printf("Registered forkAndExec\n");
}

/**
* Basically a verbatim implementation of ndlopen(), found at
* https://github.com/PojavLauncherTeam/lwjgl3/blob/3.3.1/modules/lwjgl/core/src/generated/c/linux/org_lwjgl_system_linux_DynamicLinkLoader.c#L11
* The idea is that since, on Android 10 and earlier, the linker doesn't really do namespace nesting.
* It is not a problem as most of the libraries are in the launcher path, but when you try to run
* VulkanMod which loads shaderc outside of the default jni libs directory through this method,
* it can't load it because the path is not in the allowed paths for the anonymous namesapce.
* This method fixes the issue by being in libpojavexec, and thus being in the classloader namespace
*/
jlong ndlopen_bugfix(__attribute__((unused)) JNIEnv *env,
__attribute__((unused)) jclass class,
jlong filename_ptr,
jint jmode) {
const char* filename = (const char*) filename_ptr;
int mode = (int)jmode;
return (jlong) dlopen(filename, mode);
}

/**
* Install the linker bug mitigation for Android 10 and lower. Fixes VulkanMod crashing on these
* Android versions due to missing namespace nesting.
*/
void installLinkerBugMitigation() {
if(android_get_device_api_level() >= 30) return;
__android_log_print(ANDROID_LOG_INFO, "Api29LinkerFix", "API < 30 detected, installing linker bug mitigation");
JNIEnv* env = solcraft_environ->runtimeJNIEnvPtr_JRE;
jclass dynamicLinkLoader = (*env)->FindClass(env, "org/lwjgl/system/linux/DynamicLinkLoader");
if(dynamicLinkLoader == NULL) {
__android_log_print(ANDROID_LOG_ERROR, "Api29LinkerFix", "Failed to find the target class");
(*env)->ExceptionClear(env);
return;
}
JNINativeMethod ndlopenMethod[] = {
{"ndlopen", "(JI)J", &ndlopen_bugfix}
};
if((*env)->RegisterNatives(env, dynamicLinkLoader, ndlopenMethod, 1) != 0) {
__android_log_print(ANDROID_LOG_ERROR, "Api29LinkerFix", "Failed to register the bugfix method");
(*env)->ExceptionClear(env);
}
}

/**
* This function is meant as a substitute for SharedLibraryUtil.getLibraryPath() that just returns 0
* (thus making the parent Java function return null). This is done to avoid using the LWJGL's default function,
Expand Down
Loading

0 comments on commit 2ad4e49

Please sign in to comment.