1. Fix for https://github.com/termux/termux-packages/issues/10940 working inside shell_loader
2. Getting rid of using `Reflection` API and `CrossVersionReflectedMethod` in the project
3. Unhiding some non-SDK API's to the project using gradle's `compileOnly` dependency
4. Getting rid of library unpacking and making loader open it directly from apk ( 6cdfb75c44 (commitcomment-77856313) ). @agnostic-apollo is the best!!!
Some cleanup...
Bumping versionCode
com.termux.x11 W/Bundle: Key com.termux.x11.launched_by_companion expected String but value was a java.lang.Integer. The default value <null> was returned.
com.termux.x11 W/Bundle: Attempt to cast generated internal exception:
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at android.os.BaseBundle.getString(BaseBundle.java:1199)
at android.content.Intent.getStringExtra(Intent.java:8248)
at com.termux.x11.MainActivity.onCreate(MainActivity.java:62)
```
~ $ termux-x11 :0
java.lang.UnsatisfiedLinkError: No implementation found for void com.termux.x11.starter.Starter.checkXdgRuntimeDir() (tried Java_com_termux_x11_starter_Starter_checkXdgRuntimeDir and Java_com_termux_x11_starter_Starter_checkXdgRuntimeDir__)
at com.termux.x11.starter.Starter.checkXdgRuntimeDir(Native Method)
at com.termux.x11.starter.Starter.onRun(Starter.java:84)
at com.termux.x11.starter.Starter.lambda$main$0(Starter.java:61)
at com.termux.x11.starter.Starter$$ExternalSyntheticLambda1.run(Unknown Source)
at java.lang.Thread.run(Thread.java:762)
```
The issue was fixed by calling `System.load()` instead of `Runtime.getRuntime().load()`.
Before 2018-07/f0346c9f/android 10, android was not using `Reflection.getCallerClass()` to get caller class of methods and was using either `VMStack.getCallerClass1()` or `VMStack.getCallerClass2()`. The `VMStack.getCallerClass2()` is a native method and returns class of the caller's caller. It is "normally not supposed" to be called directly and instead `VMStack.getCallerClass1()` should be called instead, which calls `VMStack.getCallerClass2()` itself, effectively returning caller's class, due to an additional stack frame for the `VMStack.getCallerClass1()` wrapper.
```
public static Class<?> getStackClass1() {
return getStackClass2();
}
native public static Class<?> getStackClass2();
```
caller2() -> caller1() -> `VMStack.getCallerClass1()` -> `VMStack.getCallerClass2()` = Returns caller2's class
caller2() -> caller1() -> `VMStack.getCallerClass2()` = Returns caller2's caller class (caller3)
Now for issue at hand, let's check implementation of `System.load()` and `Runtime.load()`.
Before f0346c9f
```
System.load(String filename) {
Runtime.getRuntime().load0(VMStack.getStackClass1(), filename);
}
Runtime.load(String filename) {
load0(VMStack.getStackClass2(), filename);
}
```
After f0346c9f
```
System.load(String filename) {
Runtime.getRuntime().load0(Reflection.getCallerClass(), filename);
}
Runtime.load(String filename) {
load0(Reflection.getCallerClass(), filename);
}
```
The javadocs for `System.load()` say that `The call System.load(name) is effectively equivalent to the call: Runtime.getRuntime().load(name)`, but that is technically not true, before f0346c9f, they were not the same. As you can see, `Runtime.load()` will use caller's caller class instead of caller's class and so will use the wrong `ClassLoader` when calling `fromClass.getClassLoader()` later in `Runtime.load0()`. After f0346c9f, ClassLoader used will actually be same for both calls.
Now normally, this shouldn't be an issue if called in an app with nested method calls. But if you are using `/system/bin/app_process` to start a process from an apk, with its `main()` function as entry point, then both the `main()` function and the main class's static block, will have a different `caller3` class while loading, i.e `RuntimeInit`. So if `Runtime.getRuntime().load()` is used in either of them, the load call will fail and so `System.load()` must be used to make loading work on all android versions. However, you can use either inside any methods called from `main()`.
```
export CLASSPATH=/data/data/com.termux/files/usr/libexec/termux-x11/starter.apk
unset LD_LIBRARY_PATH LD_PRELOAD
exec /system/bin/app_process / com.termux.x11.starter.Starter "$@"
```
```
Log.i("starter", "caller=" + Thread.currentThread().getStackTrace()[2].getClassName());
Log.i("starter", "caller=" + Thread.currentThread().getStackTrace()[3].getClassName());
I/starter: caller2=com.termux.x11.starter.Starter
I/starter: caller3=com.android.internal.os.RuntimeInit
```
https://cs.android.com/android/_/android/platform/libcore/+/f0346c9fhttps://cs.android.com/android/platform/superproject/+/android-7.0.0_r1:libcore/ojluni/src/main/java/java/lang/System.java;l=1505https://cs.android.com/android/platform/superproject/+/android-12.0.0_r34:libcore/ojluni/src/main/java/java/lang/System.java;l=1620https://cs.android.com/android/platform/superproject/+/android-7.0.0_r1:libcore/ojluni/src/main/java/java/lang/Runtime.java;l=871https://cs.android.com/android/platform/superproject/+/android-12.0.0_r34:libcore/ojluni/src/main/java/java/lang/Runtime.java;l=892https://cs.android.com/android/platform/superproject/+/android-7.0.0_r1:libcore/libart/src/main/java/dalvik/system/VMStack.java;l=40https://cs.android.com/android/platform/superproject/+/android-12.0.0_r34:libcore/libart/src/main/java/dalvik/system/VMStack.java;l=67https://cs.android.com/android/platform/superproject/+/android-12.0.0_r34:libcore/ojluni/src/main/java/sun/reflect/Reflection.java;l=75https://github.com/termux/termux-x11/blob/f9a9ce31/termux-x11
Also changing native lib name since `libstarter` is too generic a name which may conflict with potential system libs causing similar issues. Related https://stackoverflow.com/a/27760201Closes#56