You've already forked android_translation_layer
mirror of
https://gitlab.com/android_translation_layer/android_translation_layer.git
synced 2025-10-27 11:48:10 -07:00
get rid of launcher script requirement; fix app data dir being hardcoded; update documentation; remove prebuilt dalvik (NOTE - purged from history at this point, so is not part of the diff)
This commit is contained in:
@@ -1,25 +1,14 @@
|
||||
#### directory structure
|
||||
|
||||
`dalvik/*dalvik` - helper scripts for running bytecode in the dalvik VM (not used anymore, we link against `libdvm.so` directly now)
|
||||
`dalvik/linux-${arch}/` - pre-complied dalvik from https://gitlab.com/Mis012/dalvik_standalone
|
||||
|
||||
`arsc_parser/` - Java .arsc parser I found somewhere, with fixes (should eventually get replaced by C code)
|
||||
`data/` - the equivalent of `/data/data/${app-package-name}/`; TODO - use `data/${app-package-name}` instead
|
||||
to allow for storing the data of multiple apps at the same time
|
||||
`data/lib/` - hardcoded location, libraries under which are assumed to be linked against bionic
|
||||
(and will therefore be loaded with a shim bionic linker)
|
||||
`src/arsc_parser/` - Java .arsc parser I found somewhere, with fixes (should eventually get replaced by C code)
|
||||
`doc/` - documentation
|
||||
`jars/` - when we want to link against dalvik core java libs, we need to keep their non-dex versions here
|
||||
`jni/` - C code implementing things which it doesn't make sense to do in Java (ideally this would be most things)
|
||||
`libandroid-src/` - C code implementing `libandroid.so` (this is needed by most JNI libs which come with android apps)
|
||||
`libnative/` - compilation output for our `.so` libraries (currently `libtranslation_layer_main.so` and `libandroid.so`)
|
||||
`main-src/` - Java code implementing the android APIs
|
||||
`src/` - code for the main executable, which sets stuff up (including the JVM) and launches the activity specified on the cmdline
|
||||
`jars/` - contains core-libart-hostdex_classes.jar which we use as compile-time bootclasspath (TODO: have art-dev package install this system-wide)
|
||||
`src/api-impl/` - Java code implementing the android APIs
|
||||
`src/api-impl-jni/` - C code implementing things which it doesn't make sense to do in Java (ideally this would be most things)
|
||||
`src/libandroid/` - C code implementing `libandroid.so` (this is needed by most JNI libs which come with android apps)
|
||||
`src/main-executable` - code for the main executable, which sets stuff up (including the JVM) and launches the activity specified on the cmdline
|
||||
`test-apks/` - all apks known to somewhat work, except paid proprietary ones which we sadly can't really include
|
||||
|
||||
`./com.google.android.gms.apk`: microg; stopgap solution to run apps with GSF dependencies (fwiw, the actual solution will likely also use MicroG)
|
||||
`./*.dex` - compiled Java code; `hax_arsc_parser.dex` corresponds to `hax_arsc_parser.dex/`,
|
||||
`hax.dex` corresponds to `main-src`
|
||||
|
||||
#### philosophy
|
||||
|
||||
@@ -38,28 +27,22 @@ components, we also keep just the respective .so files from those apps
|
||||
and provide implementations/shims for the system libraries they are linked
|
||||
against)
|
||||
|
||||
#### current control flow (to be refined)
|
||||
#### current control flow
|
||||
|
||||
1. the user executes `launch_activity.sh`
|
||||
this wrapper accomplishes the following things:
|
||||
- `LD_PRELOAD` makes sure that `libbsd` (which provides some functions that bionic would on android) is loaded, even though bionic-linked libraries don't know they want it
|
||||
- `LD_PRELOAD` also loads libpthread_bio.so, which is a shim for translating libpthread calls made by bionic-linked libraries to calls to glibc/musl libpthread
|
||||
- `ANDROID_ROOT` and `ANDROID_DATA` get set, both of which are required by dalvik
|
||||
- `BIONIC_LD_LIBRARY_PATH` gets set to the path to the android app's lib folder (currently any app's data directory is `data/`) so that the shim bionic linker knows which .so files must not be loaded by the system linker
|
||||
- `LD_LIBRARY_PATH` is set up such that both the host linker and the shim bionic linker can find any non-system libraries they will need
|
||||
- `./main ${1} -l ${2}` calls the main executable and instructs it to load the apk file `${1}` into classpath before launching the activity `${2}` using the JVM
|
||||
1. the user executes the main executable (`android_translation_layer`)
|
||||
|
||||
2. the executable is compiled from `src/main.c`:
|
||||
2. the executable is compiled from `src/main-executable/main.c`:
|
||||
1. `int main(int argc, char **argv)` sets up a GtkApllication, cmdline handling, and calls `g_application_run`
|
||||
2. GtkApplication glue parses the cmdline and calls `static void open(GtkApplication *app, GFile** files, gint nfiles, const gchar* hint, struct jni_callback_data *d)`
|
||||
3. `static void open(GtkApplication *app, GFile** files, gint nfiles, const gchar* hint, struct jni_callback_data *d)`:
|
||||
1. constructs the classpath from the following:
|
||||
- `hax_arsc_parser.dex` is dalvik bytecode implementing .arsc parsing duties (to be replaced by C code eventually)
|
||||
- `hax.dex` contains all the implementations of android framework functions
|
||||
- `%s` will be substituted by the path to the app's apk (passed to us on cmdline), making the bytecode within (and resources.arsc, which is currently the only other file read straight from the apk) available in classpath
|
||||
- `com.google.android.gms.apk` is the path to a microG apk, needed for apps with a dependency on GSF; this is specified after the app's apk so that the the app's apk is the first zip file in the classpath (needed for getting the right resources.arsc, TODO: ask for the classloader which loaded the activity that was specified on the cmdline)
|
||||
2. contructs other options for and launches the dalvik virtual machine
|
||||
3. load `libtrasnlation_layer_main.so` using the internal function `dvmLoadNativeCode` (this contains our native methods, and dalvik will only search in libraries that were loaded using this or System.load) (NOTE: care is taken to register this with the right classloader so the java code which declares the native methods is the java code that can use them)
|
||||
- the path to api-impl.jar (contains the following, renamed to classes{2}.dex so that art loads them)
|
||||
- `hax_arsc_parser.dex` is dalvik bytecode implementing .arsc parsing duties (to be replaced by C code eventually)
|
||||
- `hax.dex` contains all the implementations of android framework functions
|
||||
- the path to the app's apk (passed to us on cmdline), making the bytecode within (and resources.arsc, which is currently the only other file read straight from the apk) available in classpath
|
||||
- the path to a microG apk, needed for apps with a dependency on GSF; this is specified after the app's apk so that the the app's apk is the first zip file in the classpath (needed for getting the right resources.arsc, TODO: ask for the classloader which loaded the activity that was specified on the cmdline)
|
||||
2. contructs other options (mainly library path) for and launches the dalvik virtual machine
|
||||
3. load `libtrasnlation_layer_main.so` using the internal version of Runtime.loadLibrary which lets us register this with the right classloader so the java code which declares the native methods is the java code that can use them
|
||||
4. sets up a JNI handle cache
|
||||
5. sets display size to be passed to apps according to optionally specified window size (some apps handle runtime resizing poorly, and our EGL code currently doesn't handle it at all)
|
||||
6. creates a Gtk Window with said size and shows it on screen
|
||||
@@ -68,6 +51,6 @@ this wrapper accomplishes the following things:
|
||||
3. the Activity specfified with `-l` calls various android APIs, which we hopefully implement;
|
||||
typically, it will set up some android widgets, which will appear in the Gtk window as Gtk widgets
|
||||
|
||||
5. you, the user, interact with the Gtk widgets, which the app might have registered callbacks for;
|
||||
4. you, the user, interact with the Gtk widgets, which the app might have registered callbacks for;
|
||||
as long as our implementation of android APIs is good enough for what the app needs, you can use the app
|
||||
as you would on android
|
||||
|
||||
@@ -11,7 +11,7 @@ you would probably prefer to first get the app to launch without errors. With a
|
||||
with writing stubs.
|
||||
|
||||
What is a stub? Well, the simplest stub would be an empty class, like this:
|
||||
`main-src/android/webkit/WebView.java:`
|
||||
`src/api-impl/android/webkit/WebView.java:`
|
||||
```Java
|
||||
package android.webkit;
|
||||
|
||||
@@ -34,7 +34,7 @@ public class WebView {
|
||||
}
|
||||
}
|
||||
```
|
||||
here, all that you need to take care of is that at `main-src/android/content/Context.java`, you have at minimum
|
||||
here, all that you need to take care of is that at `src/api-impl/android/content/Context.java`, you have at minimum
|
||||
a stub class.
|
||||
|
||||
Unfortunately, in the WebView case, the method that an app was trying call wasn't returning `void`. If this is
|
||||
@@ -94,7 +94,7 @@ to get to work in order to cut down on the amount of stubbing you need to do.
|
||||
There are two basic types of widgets (Views): containers (Layouts) and the rest.
|
||||
|
||||
To implement a container widget, simply copy an existing container widget implementation (e.g LinearLayout
|
||||
(`./main-src/android/widget/LinearLayout.java` and `./jni/widgets/android_widget_LinearLayout.c`)), and that's
|
||||
(`src/api-impl/android/widget/LinearLayout.java` and `src/api-impl-jni/widgets/android_widget_LinearLayout.c`)), and that's
|
||||
it! Now, chances are that you wanted something slightly different, but this will at least display the child
|
||||
widgets so that you can focus on implementing those.
|
||||
|
||||
@@ -108,7 +108,7 @@ the close-enough Gtk widget, since subclassing is mostly not possible in Gtk.
|
||||
|
||||
###### case study: ImageView
|
||||
|
||||
`main-src/android/widget/ImageView.java`
|
||||
`src/api-impl/android/widget/ImageView.java`
|
||||
```Java
|
||||
package android.widget;
|
||||
```
|
||||
@@ -151,7 +151,7 @@ public class ImageView extends View {
|
||||
|
||||
---
|
||||
|
||||
`jni/widgets/android_widget_ImageView.c`
|
||||
`src/api-impl-jni/widgets/android_widget_ImageView.c`
|
||||
```C
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
@@ -161,11 +161,11 @@ public class ImageView extends View {
|
||||
#include "WrapperWidget.h"
|
||||
|
||||
```
|
||||
↑ every widget will be under `jni/widgets/` and will have these includes
|
||||
↑ every widget will be under `src/api-impl-jni/widgets/` and will have these includes
|
||||
```C
|
||||
#include "android_widget_ImageView.h"
|
||||
#include "../generated_headers/android_widget_ImageView.h"
|
||||
```
|
||||
↑ this is the jni-generated header file; you will need to add this to the part of the Makefile which moves widget header files to `jni/widgets/`
|
||||
↑ this is the jni-generated header file (btw, t's name is what dicates the name of this .c file)
|
||||
↓ there should be two functions here, one for the `Context` costructor and one for the `AttributeSet` one; for start, you can keep them the same
|
||||
```C
|
||||
JNIEXPORT void JNICALL Java_android_widget_ImageView_native_1constructor__Landroid_content_Context_2(JNIEnv *env, jobject this, jobject context)
|
||||
@@ -173,7 +173,7 @@ JNIEXPORT void JNICALL Java_android_widget_ImageView_native_1constructor__Landro
|
||||
GtkWidget *wrapper = wrapper_widget_new();
|
||||
```
|
||||
↑ the wrapper widget is required, it's expected by generic functions operating on widgets; the purpose is to allow for things like background image
|
||||
handling independently of the
|
||||
handling for cases where we can't subclass the backing widget itself
|
||||
```C
|
||||
GtkWidget *image = gtk_image_new_from_icon_name("FIXME"); // will not actually use gtk_image_new_from_icon_name when implementing this, but we want that nice "broken image" icon
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user