From c936333c74f13ac36ef7de386711c9552d088a83 Mon Sep 17 00:00:00 2001 From: Mis012 Date: Sat, 12 Aug 2023 13:05:34 +0200 Subject: [PATCH] src/main-executable: show actual package name as window title, preparation for showing app icon, re-add some missing stuff --- src/api-impl/android/app/Application.java | 23 +++++ src/api-impl/android/content/Context.java | 28 +++++- src/main-executable/main.c | 102 +++++++++++++++------- 3 files changed, 118 insertions(+), 35 deletions(-) diff --git a/src/api-impl/android/app/Application.java b/src/api-impl/android/app/Application.java index ddc755a3..b3b1add5 100644 --- a/src/api-impl/android/app/Application.java +++ b/src/api-impl/android/app/Application.java @@ -1,10 +1,23 @@ package android.app; + import android.os.Bundle; import android.content.res.Configuration; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import com.reandroid.apk.AndroidFrameworks; +import com.reandroid.arsc.chunk.xml.AndroidManifestBlock; +import java.io.InputStream; +import java.io.IOException; import android.content.Context; public class Application extends Context { + private String app_icon_path = null; + + private String get_app_icon_path() { + return app_icon_path; + } + public interface ActivityLifecycleCallbacks { void onActivityCreated(Activity activity, Bundle savedInstanceState); void onActivityStarted(Activity activity); @@ -28,7 +41,17 @@ public class Application extends Context { */ public void onProvideAssistData(Activity activity, Bundle data); } + public Application() { + /* TODO: is this the right place to put this? */ + InputStream inStream = ClassLoader.getSystemClassLoader().getResourceAsStream("AndroidManifest.xml"); + try { + AndroidManifestBlock manifest = AndroidManifestBlock.load(inStream); + int app_icon_resid = manifest.getIconResourceId(); + app_icon_path = this.getResources().getString(app_icon_resid); + } catch (IOException e) { + e.printStackTrace(); + } } /** * Called when the application is starting, before any activity, service, diff --git a/src/api-impl/android/content/Context.java b/src/api-impl/android/content/Context.java index 21b4d344..876a9779 100644 --- a/src/api-impl/android/content/Context.java +++ b/src/api-impl/android/content/Context.java @@ -33,10 +33,13 @@ import android.util.DisplayMetrics; import android.util.Log; import android.view.WindowManager; import android.view.WindowManagerImpl; +import com.reandroid.arsc.chunk.xml.AndroidManifestBlock; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.IOException; public class Context extends Object { private final static String TAG = "Context"; @@ -46,6 +49,8 @@ public class Context extends Object { public static final String AUDIO_SERVICE = "audio"; public static final String DISPLAY_SERVICE = "display"; public static final String MEDIA_ROUTER_SERVICE = "media_router"; + public static final String WINDOW_SERVICE = "window"; + private static AndroidManifestBlock manifest = null; static AssetManager assets; static DisplayMetrics dm; @@ -70,6 +75,13 @@ public class Context extends Object { r = new Resources(assets, dm, config); this_application = new Application(); // TODO: the application context is presumably not identical to the Activity context, what is the difference for us though? application_info = new ApplicationInfo(); + + InputStream inStream = ClassLoader.getSystemClassLoader().getResourceAsStream("AndroidManifest.xml"); + try { + manifest = AndroidManifestBlock.load(inStream); + } catch (IOException e) { + e.printStackTrace(); + } } public Context() { @@ -156,7 +168,7 @@ public class Context extends Object { } public String getPackageName() { - return "com.example.demo_app"; + return manifest.getPackageName(); } public String getPackageCodePath() { @@ -254,7 +266,7 @@ public class Context extends Object { } public SharedPreferences getSharedPreferences(String name, int mode) { - System.out.println("\n\n...> getSharedPreferences(" + name + ",)\n\n"); + System.out.println("\n\n...> getSharedPreferences(" + name + ")\n\n"); File prefsFile = getSharedPrefsFile(name); return new SharedPreferencesImpl(prefsFile, mode); } @@ -289,6 +301,18 @@ public class Context extends Object { public void registerComponentCallbacks(ComponentCallbacks callbacks) {} + public boolean bindService(Intent dummy, ServiceConnection dummy2, int dummy3) { + System.out.println("bindService("+dummy+", "+dummy2+", "+dummy3+")"); + return false; // maybe? + } + + public void startActivity(Intent intent) { + System.out.println("------------------"); + System.out.println("app wants to startActivity("+intent+"), but we don't support that... :/"); + try { throw new java.lang.Exception(); } catch (java.lang.Exception e) { e.printStackTrace(); } + System.out.println("------------------"); + } + // these may not look like typical stubs, but they definitely are stubs public final TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs) { return new TypedArray(r, new int[1000], new int[1000], 0); } public final TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) { return new TypedArray(r, new int[1000], new int[1000], 0); } diff --git a/src/main-executable/main.c b/src/main-executable/main.c index d8c56ec7..b3dbc5ed 100644 --- a/src/main-executable/main.c +++ b/src/main-executable/main.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -155,6 +156,7 @@ static void open(GtkApplication *app, GFile** files, gint nfiles, const gchar* h char *api_impl_jar; char *microg_apk = NULL; char *framework_res_apk = NULL; + const char *package_name; int errno_libdir; int errno_localdir; int ret; @@ -306,6 +308,23 @@ static void open(GtkApplication *app, GFile** files, gint nfiles, const gchar* h set_up_handle_cache(env); + /* -- register our JNI library under the appropriate classloader -- */ + + /* 'android/view/View' is part of the "hax.dex" package, any other function from that package would serve just as well */ + jmethodID getClassLoader = _METHOD((*env)->FindClass(env, "java/lang/Class"), "getClassLoader", "()Ljava/lang/ClassLoader;"); + jobject class_loader = (*env)->CallObjectMethod(env, (*env)->FindClass(env, "android/view/View"), getClassLoader); + + jclass java_runtime_class = (*env)->FindClass(env, "java/lang/Runtime"); + + jmethodID getRuntime = _STATIC_METHOD(java_runtime_class, "getRuntime", "()Ljava/lang/Runtime;"); + jobject java_runtime = (*env)->CallStaticObjectMethod(env, java_runtime_class, getRuntime); + + /* this method is private, but it seems we get away with calling it from C */ + jmethodID loadLibrary_with_classloader = _METHOD(java_runtime_class, "loadLibrary", "(Ljava/lang/String;Ljava/lang/ClassLoader;)V"); + (*env)->CallVoidMethod(env, java_runtime, loadLibrary_with_classloader, _JSTRING("translation_layer_main"), class_loader); + + /* -- misc -- */ + jclass display_class = (*env)->FindClass(env, "android/view/Display"); _SET_STATIC_INT_FIELD(display_class, "window_width", d->window_width); _SET_STATIC_INT_FIELD(display_class, "window_height", d->window_height); @@ -319,32 +338,10 @@ static void open(GtkApplication *app, GFile** files, gint nfiles, const gchar* h window = gtk_application_window_new(app); - gtk_window_set_title(GTK_WINDOW(window), "com.example.demo_application"); - gtk_window_set_default_size(GTK_WINDOW(window), d->window_width, d->window_height); - g_signal_connect(window, "close-request", G_CALLBACK (app_exit), env); - -// TODO: set icon according to how android gets it for the purposes of displaying it in the launcher -// gtk_window_set_icon_name(window, "weather-clear"); - if(getenv("ATL_DISABLE_WINDOW_DECORATIONS")) gtk_window_set_decorated(GTK_WINDOW(window), 0); - gtk_widget_show(window); - - /* -- register our JNI library under the appropriate classloader -- */ - - /* 'android/view/View' is part of the "hax.dex" package, any other function from that package would serve just as well */ - jmethodID getClassLoader = _METHOD((*env)->FindClass(env, "java/lang/Class"), "getClassLoader", "()Ljava/lang/ClassLoader;"); - jobject class_loader = (*env)->CallObjectMethod(env, handle_cache.view.class, getClassLoader); - - jclass java_runtime_class = (*env)->FindClass(env, "java/lang/Runtime"); - - jmethodID getRuntime = _STATIC_METHOD(java_runtime_class, "getRuntime", "()Ljava/lang/Runtime;"); - jobject java_runtime = (*env)->CallStaticObjectMethod(env, java_runtime_class, getRuntime); - - /* this method is private, but it seems we get away with calling it from C */ - jmethodID loadLibrary_with_classloader = _METHOD(java_runtime_class, "loadLibrary", "(Ljava/lang/String;Ljava/lang/ClassLoader;)V"); - (*env)->CallVoidMethod(env, java_runtime, loadLibrary_with_classloader, _JSTRING("translation_layer_main"), class_loader); + gtk_window_present(GTK_WINDOW(window)); extract_from_apk("assets/", "assets/"); /* extract native libraries from apk*/ @@ -359,6 +356,45 @@ static void open(GtkApplication *app, GFile** files, gint nfiles, const gchar* h if((*env)->ExceptionCheck(env)) (*env)->ExceptionDescribe(env); + + /* -- set the window title and (FIXME) app icon -- */ + + package_name = _CSTRING((*env)->CallObjectMethod(env, activity_object, handle_cache.context.get_package_name)); + if((*env)->ExceptionCheck(env)) + (*env)->ExceptionDescribe(env); + +/* const char *app_icon_path = _CSTRING((*env)->CallObjectMethod(env, handle_cache.application.object, handle_cache.application.get_app_icon_path)); + if((*env)->ExceptionCheck(env)) + (*env)->ExceptionDescribe(env); + + char *tmp = strdup(app_icon_path); + const char *app_icon_dirname = dirname(tmp); + char *app_icon_basename = basename(app_icon_path); + *strrchr(app_icon_basename, '.') = '\0'; + extract_from_apk(app_icon_path, app_icon_path); + char *app_icon_basedir_fullpath = malloc(strlen(app_data_dir) + strlen(app_icon_dirname) + strlen("/hicolor") + 1); + strcpy(app_icon_basedir_fullpath, app_data_dir); + strcat(app_icon_basedir_fullpath, app_icon_dirname); + strcat(app_icon_basedir_fullpath, "/hicolor"); +*/ + gtk_window_set_title(GTK_WINDOW(window), package_name); + gtk_window_set_default_size(GTK_WINDOW(window), d->window_width, d->window_height); + g_signal_connect(window, "close-request", G_CALLBACK (app_exit), env); +/* + GtkIconTheme *theme = gtk_icon_theme_get_for_display(gdk_display_get_default()); + printf(">>%s<<\n", app_icon_basedir_fullpath); + printf(">%s<\n", app_icon_basename); + gtk_icon_theme_set_search_path(theme, (const char *const[]){app_icon_basedir_fullpath, NULL}); + + printf(">>>%d<<<\n", gtk_icon_theme_has_icon(theme, app_icon_basename)); + + gtk_window_set_icon_name(GTK_WINDOW(window), app_icon_basename); + + exit(69); +*/ +// free(tmp); +// free(app_icon_basedir_fullpath); + activity_start(env, activity_object); g_timeout_add(10, G_SOURCE_FUNC(hacky_on_window_focus_changed_callback), env); @@ -421,8 +457,8 @@ void init__r_debug(); int main(int argc, char **argv/*, JNIEnv *env*/) { - GtkApplication *app; - int status; + GtkApplication *app; + int status; /* this has to be done in the main executable, so might as well do it here*/ init__r_debug(); @@ -436,19 +472,19 @@ int main(int argc, char **argv/*, JNIEnv *env*/) callback_data->window_width = 960; callback_data->window_height = 540; - app = gtk_application_new("com.example.demo_application", G_APPLICATION_NON_UNIQUE | G_APPLICATION_HANDLES_OPEN); + app = gtk_application_new("com.example.demo_application", G_APPLICATION_NON_UNIQUE | G_APPLICATION_HANDLES_OPEN); // cmdline related setup init_cmd_parameters(G_APPLICATION(app), callback_data); g_application_set_option_context_summary(G_APPLICATION(app), "a translation layer for running android applications natively on Linux"); - g_signal_connect(app, "activate", G_CALLBACK (activate), callback_data); - g_signal_connect(app, "open", G_CALLBACK (open), callback_data); - status = g_application_run(G_APPLICATION(app), argc, argv); - g_object_unref(app); + g_signal_connect(app, "activate", G_CALLBACK (activate), callback_data); + g_signal_connect(app, "open", G_CALLBACK (open), callback_data); + status = g_application_run(G_APPLICATION(app), argc, argv); + g_object_unref(app); - return status; + return status; } -const char dl_loader[] __attribute__((section(".interp"))) = - "/lib/ld-linux.so.2"; +/* TODO: recall what this is doing here */ +const char dl_loader[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2";