diff --git a/meson.build b/meson.build index feab875d..8165b4af 100644 --- a/meson.build +++ b/meson.build @@ -33,6 +33,7 @@ libtranslationlayer_so = shared_library('translation_layer_main', [ 'src/api-impl-jni/widgets/WrapperWidget.c', 'src/api-impl-jni/widgets/android_widget_TextView.c', 'src/api-impl-jni/widgets/android_widget_LinearLayout.c', + 'src/api-impl-jni/widgets/android_view_SurfaceView.c', 'src/api-impl-jni/views/android_view_View.c', 'src/api-impl-jni/views/android_view_ViewGroup.c', 'src/api-impl-jni/android_graphics_Bitmap.c' @@ -60,11 +61,18 @@ executable('android-translation-layer', [ # libandroid shared_library('android', [ + 'src/libandroid/asset_manager.c', + 'src/libandroid/media.c', 'src/libandroid/misc.c', - 'src/libandroid/asset_manager.c' + 'src/libandroid/native_window.c', + 'src/libandroid/sensor.c', + 'src/libandroid/looper.c' ], install: true, - soversion: 0,) + soversion: 0, + dependencies: [ + dependency('gtk4'), dependency('jni'), dependency('glfw3') + ]) # hax_arsc_parser.dex (named as classes2.dex so it works inside a jar) subdir('src/arsc_parser') diff --git a/src/api-impl-jni/generated_headers/android_view_SurfaceView.h b/src/api-impl-jni/generated_headers/android_view_SurfaceView.h new file mode 100644 index 00000000..1f81788b --- /dev/null +++ b/src/api-impl-jni/generated_headers/android_view_SurfaceView.h @@ -0,0 +1,163 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class android_view_SurfaceView */ + +#ifndef _Included_android_view_SurfaceView +#define _Included_android_view_SurfaceView +#ifdef __cplusplus +extern "C" { +#endif +#undef android_view_SurfaceView_NO_ID +#define android_view_SurfaceView_NO_ID -1L +#undef android_view_SurfaceView_NOT_FOCUSABLE +#define android_view_SurfaceView_NOT_FOCUSABLE 0L +#undef android_view_SurfaceView_FOCUSABLE +#define android_view_SurfaceView_FOCUSABLE 1L +#undef android_view_SurfaceView_FOCUSABLE_MASK +#define android_view_SurfaceView_FOCUSABLE_MASK 1L +#undef android_view_SurfaceView_FITS_SYSTEM_WINDOWS +#define android_view_SurfaceView_FITS_SYSTEM_WINDOWS 2L +#undef android_view_SurfaceView_VISIBLE +#define android_view_SurfaceView_VISIBLE 0L +#undef android_view_SurfaceView_INVISIBLE +#define android_view_SurfaceView_INVISIBLE 4L +#undef android_view_SurfaceView_GONE +#define android_view_SurfaceView_GONE 8L +#undef android_view_SurfaceView_VISIBILITY_MASK +#define android_view_SurfaceView_VISIBILITY_MASK 12L +#undef android_view_SurfaceView_ENABLED +#define android_view_SurfaceView_ENABLED 0L +#undef android_view_SurfaceView_DISABLED +#define android_view_SurfaceView_DISABLED 32L +#undef android_view_SurfaceView_ENABLED_MASK +#define android_view_SurfaceView_ENABLED_MASK 32L +#undef android_view_SurfaceView_WILL_NOT_DRAW +#define android_view_SurfaceView_WILL_NOT_DRAW 128L +#undef android_view_SurfaceView_DRAW_MASK +#define android_view_SurfaceView_DRAW_MASK 128L +#undef android_view_SurfaceView_SCROLLBARS_NONE +#define android_view_SurfaceView_SCROLLBARS_NONE 0L +#undef android_view_SurfaceView_SCROLLBARS_HORIZONTAL +#define android_view_SurfaceView_SCROLLBARS_HORIZONTAL 256L +#undef android_view_SurfaceView_SCROLLBARS_VERTICAL +#define android_view_SurfaceView_SCROLLBARS_VERTICAL 512L +#undef android_view_SurfaceView_SCROLLBARS_MASK +#define android_view_SurfaceView_SCROLLBARS_MASK 768L +#undef android_view_SurfaceView_FILTER_TOUCHES_WHEN_OBSCURED +#define android_view_SurfaceView_FILTER_TOUCHES_WHEN_OBSCURED 1024L +#undef android_view_SurfaceView_OPTIONAL_FITS_SYSTEM_WINDOWS +#define android_view_SurfaceView_OPTIONAL_FITS_SYSTEM_WINDOWS 2048L +#undef android_view_SurfaceView_FADING_EDGE_NONE +#define android_view_SurfaceView_FADING_EDGE_NONE 0L +#undef android_view_SurfaceView_FADING_EDGE_HORIZONTAL +#define android_view_SurfaceView_FADING_EDGE_HORIZONTAL 4096L +#undef android_view_SurfaceView_FADING_EDGE_VERTICAL +#define android_view_SurfaceView_FADING_EDGE_VERTICAL 8192L +#undef android_view_SurfaceView_FADING_EDGE_MASK +#define android_view_SurfaceView_FADING_EDGE_MASK 12288L +#undef android_view_SurfaceView_CLICKABLE +#define android_view_SurfaceView_CLICKABLE 16384L +#undef android_view_SurfaceView_DRAWING_CACHE_ENABLED +#define android_view_SurfaceView_DRAWING_CACHE_ENABLED 32768L +#undef android_view_SurfaceView_SAVE_DISABLED +#define android_view_SurfaceView_SAVE_DISABLED 65536L +#undef android_view_SurfaceView_SAVE_DISABLED_MASK +#define android_view_SurfaceView_SAVE_DISABLED_MASK 65536L +#undef android_view_SurfaceView_WILL_NOT_CACHE_DRAWING +#define android_view_SurfaceView_WILL_NOT_CACHE_DRAWING 131072L +#undef android_view_SurfaceView_FOCUSABLE_IN_TOUCH_MODE +#define android_view_SurfaceView_FOCUSABLE_IN_TOUCH_MODE 262144L +#undef android_view_SurfaceView_DRAWING_CACHE_QUALITY_LOW +#define android_view_SurfaceView_DRAWING_CACHE_QUALITY_LOW 524288L +#undef android_view_SurfaceView_DRAWING_CACHE_QUALITY_HIGH +#define android_view_SurfaceView_DRAWING_CACHE_QUALITY_HIGH 1048576L +#undef android_view_SurfaceView_DRAWING_CACHE_QUALITY_AUTO +#define android_view_SurfaceView_DRAWING_CACHE_QUALITY_AUTO 0L +#undef android_view_SurfaceView_DRAWING_CACHE_QUALITY_MASK +#define android_view_SurfaceView_DRAWING_CACHE_QUALITY_MASK 1572864L +#undef android_view_SurfaceView_LONG_CLICKABLE +#define android_view_SurfaceView_LONG_CLICKABLE 2097152L +#undef android_view_SurfaceView_DUPLICATE_PARENT_STATE +#define android_view_SurfaceView_DUPLICATE_PARENT_STATE 4194304L +#undef android_view_SurfaceView_SCROLLBARS_INSIDE_OVERLAY +#define android_view_SurfaceView_SCROLLBARS_INSIDE_OVERLAY 0L +#undef android_view_SurfaceView_SCROLLBARS_INSIDE_INSET +#define android_view_SurfaceView_SCROLLBARS_INSIDE_INSET 16777216L +#undef android_view_SurfaceView_SCROLLBARS_OUTSIDE_OVERLAY +#define android_view_SurfaceView_SCROLLBARS_OUTSIDE_OVERLAY 33554432L +#undef android_view_SurfaceView_SCROLLBARS_OUTSIDE_INSET +#define android_view_SurfaceView_SCROLLBARS_OUTSIDE_INSET 50331648L +#undef android_view_SurfaceView_SCROLLBARS_INSET_MASK +#define android_view_SurfaceView_SCROLLBARS_INSET_MASK 16777216L +#undef android_view_SurfaceView_SCROLLBARS_OUTSIDE_MASK +#define android_view_SurfaceView_SCROLLBARS_OUTSIDE_MASK 33554432L +#undef android_view_SurfaceView_SCROLLBARS_STYLE_MASK +#define android_view_SurfaceView_SCROLLBARS_STYLE_MASK 50331648L +#undef android_view_SurfaceView_KEEP_SCREEN_ON +#define android_view_SurfaceView_KEEP_SCREEN_ON 67108864L +#undef android_view_SurfaceView_SOUND_EFFECTS_ENABLED +#define android_view_SurfaceView_SOUND_EFFECTS_ENABLED 134217728L +#undef android_view_SurfaceView_HAPTIC_FEEDBACK_ENABLED +#define android_view_SurfaceView_HAPTIC_FEEDBACK_ENABLED 268435456L +#undef android_view_SurfaceView_PARENT_SAVE_DISABLED +#define android_view_SurfaceView_PARENT_SAVE_DISABLED 536870912L +#undef android_view_SurfaceView_PARENT_SAVE_DISABLED_MASK +#define android_view_SurfaceView_PARENT_SAVE_DISABLED_MASK 536870912L +#undef android_view_SurfaceView_FOCUSABLES_ALL +#define android_view_SurfaceView_FOCUSABLES_ALL 0L +#undef android_view_SurfaceView_FOCUSABLES_TOUCH_MODE +#define android_view_SurfaceView_FOCUSABLES_TOUCH_MODE 1L +#undef android_view_SurfaceView_FOCUS_BACKWARD +#define android_view_SurfaceView_FOCUS_BACKWARD 1L +#undef android_view_SurfaceView_FOCUS_FORWARD +#define android_view_SurfaceView_FOCUS_FORWARD 2L +#undef android_view_SurfaceView_FOCUS_LEFT +#define android_view_SurfaceView_FOCUS_LEFT 17L +#undef android_view_SurfaceView_FOCUS_UP +#define android_view_SurfaceView_FOCUS_UP 33L +#undef android_view_SurfaceView_FOCUS_RIGHT +#define android_view_SurfaceView_FOCUS_RIGHT 66L +#undef android_view_SurfaceView_FOCUS_DOWN +#define android_view_SurfaceView_FOCUS_DOWN 130L +#undef android_view_SurfaceView_MEASURED_SIZE_MASK +#define android_view_SurfaceView_MEASURED_SIZE_MASK 16777215L +#undef android_view_SurfaceView_MEASURED_STATE_MASK +#define android_view_SurfaceView_MEASURED_STATE_MASK -16777216L +#undef android_view_SurfaceView_MEASURED_HEIGHT_STATE_SHIFT +#define android_view_SurfaceView_MEASURED_HEIGHT_STATE_SHIFT 16L +#undef android_view_SurfaceView_MEASURED_STATE_TOO_SMALL +#define android_view_SurfaceView_MEASURED_STATE_TOO_SMALL 16777216L +#undef android_view_SurfaceView_PFLAG2_DRAG_CAN_ACCEPT +#define android_view_SurfaceView_PFLAG2_DRAG_CAN_ACCEPT 1L +#undef android_view_SurfaceView_PFLAG2_DRAG_HOVERED +#define android_view_SurfaceView_PFLAG2_DRAG_HOVERED 2L +#undef android_view_SurfaceView_LAYOUT_DIRECTION_LTR +#define android_view_SurfaceView_LAYOUT_DIRECTION_LTR 0L +#undef android_view_SurfaceView_LAYOUT_DIRECTION_RTL +#define android_view_SurfaceView_LAYOUT_DIRECTION_RTL 1L +#undef android_view_SurfaceView_LAYOUT_DIRECTION_INHERIT +#define android_view_SurfaceView_LAYOUT_DIRECTION_INHERIT 2L +#undef android_view_SurfaceView_LAYOUT_DIRECTION_LOCALE +#define android_view_SurfaceView_LAYOUT_DIRECTION_LOCALE 3L +#undef android_view_SurfaceView_PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT +#define android_view_SurfaceView_PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT 2L +#undef android_view_SurfaceView_PFLAG2_LAYOUT_DIRECTION_MASK +#define android_view_SurfaceView_PFLAG2_LAYOUT_DIRECTION_MASK 12L +#undef android_view_SurfaceView_PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL +#define android_view_SurfaceView_PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL 16L +#undef android_view_SurfaceView_PFLAG2_LAYOUT_DIRECTION_RESOLVED +#define android_view_SurfaceView_PFLAG2_LAYOUT_DIRECTION_RESOLVED 32L +#undef android_view_SurfaceView_PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK +#define android_view_SurfaceView_PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK 48L +/* + * Class: android_view_SurfaceView + * Method: native_constructor + * Signature: (Landroid/content/Context;)V + */ +JNIEXPORT void JNICALL Java_android_view_SurfaceView_native_1constructor + (JNIEnv *, jobject, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/api-impl-jni/util.c b/src/api-impl-jni/util.c index 6af19d25..f700c9c0 100644 --- a/src/api-impl-jni/util.c +++ b/src/api-impl-jni/util.c @@ -27,7 +27,8 @@ void set_up_handle_cache(JNIEnv *env, char *apk_main_activity_class) if((*env)->ExceptionCheck(env)) (*env)->ExceptionDescribe(env); handle_cache.apk_main_activity.onCreate = _METHOD(handle_cache.apk_main_activity.class, "onCreate", "(Landroid/os/Bundle;)V"); -// handle_cache.apk_main_activity.onWindowFocusChanged = _METHOD(handle_cache.apk_main_activity.class, "onWindowFocusChanged", "(B)V"); + handle_cache.apk_main_activity.onWindowFocusChanged = _METHOD(handle_cache.apk_main_activity.class, "onWindowFocusChanged", "(Z)V"); + handle_cache.apk_main_activity.onResume = _METHOD(handle_cache.apk_main_activity.class, "onResume", "()V"); handle_cache.apk_main_activity.onDestroy = _METHOD(handle_cache.apk_main_activity.class, "onDestroy", "()V"); handle_cache.apk_main_activity.set_window = _METHOD((*env)->FindClass(env, "android/app/Activity"), "set_window", "(J)V"); diff --git a/src/api-impl-jni/util.h b/src/api-impl-jni/util.h index 9214f1ac..f992470e 100644 --- a/src/api-impl-jni/util.h +++ b/src/api-impl-jni/util.h @@ -10,6 +10,7 @@ struct handle_cache { jclass class; jobject object; jmethodID onCreate; + jmethodID onResume; jmethodID onWindowFocusChanged; jmethodID onDestroy; jmethodID set_window; diff --git a/src/api-impl-jni/views/android_view_View.c b/src/api-impl-jni/views/android_view_View.c index 17ae58b5..21d97bc0 100644 --- a/src/api-impl-jni/views/android_view_View.c +++ b/src/api-impl-jni/views/android_view_View.c @@ -192,7 +192,7 @@ static void draw_function(GtkDrawingArea *area, cairo_t *cr, int width, int heig (*env)->ExceptionDescribe(env); } -void on_mapped(GtkWidget* self, struct jni_callback_data *d) +static void on_mapped(GtkWidget* self, struct jni_callback_data *d) { JNIEnv *env; (*d->jvm)->GetEnv(d->jvm, (void**)&env, JNI_VERSION_1_6); @@ -200,6 +200,7 @@ void on_mapped(GtkWidget* self, struct jni_callback_data *d) (*env)->CallVoidMethod(env, d->this, _METHOD(d->this_class, "onMeasure", "(II)V"), gtk_widget_get_width(self), gtk_widget_get_height(self)); } +// FIXME: this is used in one other place as well, should probably go in util.c or gtk_util.c? gboolean tick_callback(GtkWidget* widget, GdkFrameClock* frame_clock, gpointer user_data) { gtk_widget_queue_draw(widget); diff --git a/src/api-impl-jni/widgets/android_view_SurfaceView.c b/src/api-impl-jni/widgets/android_view_SurfaceView.c new file mode 100644 index 00000000..80c504e1 --- /dev/null +++ b/src/api-impl-jni/widgets/android_view_SurfaceView.c @@ -0,0 +1,38 @@ +#include + +#include "../defines.h" +#include "../util.h" + +#include "WrapperWidget.h" + +#include "../generated_headers/android_view_SurfaceView.h" + +struct jni_callback_data { JavaVM *jvm; jobject this; jclass this_class;}; + +static void on_mapped(GtkWidget* self, struct jni_callback_data *d) +{ + JNIEnv *env; + (*d->jvm)->GetEnv(d->jvm, (void**)&env, JNI_VERSION_1_6); + + (*env)->CallVoidMethod(env, d->this, _METHOD(d->this_class, "surfaceChanged", "(Landroid/view/SurfaceHolder;III)V"), _GET_OBJ_FIELD(d->this, "mSurfaceHolder", "Landroid/view/SurfaceHolder;"), 1 /*RGBA_8888*/, /*FIXME*/700, /*FIXME*/700); +} + +JNIEXPORT void JNICALL Java_android_view_SurfaceView_native_1constructor(JNIEnv *env, jobject this, jobject context) +{ + GtkWidget *wrapper = wrapper_widget_new(); + GtkWidget *dummy = gtk_fixed_new(); + gtk_widget_set_name(dummy, "dummy widget for SurfaceView"); + wrapper_widget_set_child(WRAPPER_WIDGET(wrapper), dummy); + + JavaVM *jvm; + (*env)->GetJavaVM(env, &jvm); + + struct jni_callback_data *callback_data = malloc(sizeof(struct jni_callback_data)); + callback_data->jvm = jvm; + callback_data->this = _REF(this); + callback_data->this_class = _REF(_CLASS(this)); + + g_signal_connect(dummy, "map", G_CALLBACK(on_mapped), callback_data); + + _SET_LONG_FIELD(this, "widget", _INTPTR(dummy)); +} diff --git a/src/api-impl/android/app/Activity.java b/src/api-impl/android/app/Activity.java index b95c1830..2fdce189 100644 --- a/src/api-impl/android/app/Activity.java +++ b/src/api-impl/android/app/Activity.java @@ -21,6 +21,7 @@ import java.io.StringReader; public class Activity extends Context { LayoutInflater layout_inflater; Window window = new Window(); + int requested_orientation = -1 /*ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED*/; // dummy protected void set_window(long native_window) { window.native_window = native_window; @@ -49,6 +50,14 @@ public class Activity extends Context { // return new Intent(); } + public int getRequestedOrientation() { + return requested_orientation; + } + + public void setRequestedOrientation (int orientation) { + requested_orientation = orientation; + } + public boolean isFinishing() { return false; // FIXME } diff --git a/src/api-impl/android/app/AlertDialog.java b/src/api-impl/android/app/AlertDialog.java index 11876455..45d6c045 100644 --- a/src/api-impl/android/app/AlertDialog.java +++ b/src/api-impl/android/app/AlertDialog.java @@ -27,10 +27,12 @@ public class AlertDialog extends Dialog { } public AlertDialog.Builder setTitle (CharSequence title) { + System.out.println("AlertDialog.Builder setTitle called with: '"+title+"'"); return this; } public AlertDialog.Builder setMessage (CharSequence message) { + System.out.println("AlertDialog.Builder setMessage called with: '"+message+"'"); return this; } diff --git a/src/api-impl/android/content/Context.java b/src/api-impl/android/content/Context.java index 4a9daac3..66933f5c 100644 --- a/src/api-impl/android/content/Context.java +++ b/src/api-impl/android/content/Context.java @@ -3,10 +3,14 @@ package android.content; import android.util.Log; import android.content.pm.PackageManager; +import android.content.pm.ApplicationInfo; import android.content.res.AssetManager; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; +import android.content.Intent; +import android.content.BroadcastReceiver; + import android.util.AttributeSet; import android.util.DisplayMetrics; import android.content.SharedPreferences; @@ -23,6 +27,8 @@ import android.app.KeyguardManager; import android.telephony.TelephonyManager; import android.media.AudioManager; import android.app.ActivityManager; +import android.hardware.usb.UsbManager; +import android.os.Vibrator; import java.io.File; import java.io.FileInputStream; @@ -55,6 +61,10 @@ public class Context extends Object { System.out.println("new Context! this one is: " + this); } + public ApplicationInfo getApplicationInfo () { + return new ApplicationInfo(); + } + public Context getApplicationContext() { return (Context)this_application; } @@ -81,12 +91,20 @@ public class Context extends Object { return new AudioManager(); case "activity": return new ActivityManager(); + case "usb": + return new UsbManager(); + case "vibrator": + return new Vibrator(); default: System.out.println("!!!!!!! getSystemService: case >"+name+"< is not implemented yet"); return null; } } + public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { + return new Intent(); + } + public Looper getMainLooper() { System.out.println("returning the main Looper, most definitely doing just that!"); return new Looper(); diff --git a/src/api-impl/android/content/IntentFilter.java b/src/api-impl/android/content/IntentFilter.java new file mode 100644 index 00000000..ebee0740 --- /dev/null +++ b/src/api-impl/android/content/IntentFilter.java @@ -0,0 +1,5 @@ +package android.content; + +public class IntentFilter { + public void addAction(String action) {} +} diff --git a/src/api-impl/android/content/res/AssetManager.java b/src/api-impl/android/content/res/AssetManager.java index 6dec8093..570907ac 100644 --- a/src/api-impl/android/content/res/AssetManager.java +++ b/src/api-impl/android/content/res/AssetManager.java @@ -339,7 +339,8 @@ public final class AssetManager { } } throw new FileNotFoundException("Asset file: " + fileName);*/ - return null; // FIXME + throw new IOException("FIXME: 'public final AssetFileDescriptor openFd(String fileName)': throwing an exception, which makes e.g SDL2 fall back to using something that we actually have implemented"); +// return null; // FIXME } /** diff --git a/src/api-impl/android/hardware/SensorManager.java b/src/api-impl/android/hardware/SensorManager.java index 59103a7a..b17d6baa 100644 --- a/src/api-impl/android/hardware/SensorManager.java +++ b/src/api-impl/android/hardware/SensorManager.java @@ -1,7 +1,13 @@ package android.hardware; +import android.os.Handler; + public class SensorManager { public Sensor getDefaultSensor(int type) { return null; } + + public boolean registerListener (SensorEventListener listener, Sensor sensor, int samplingPeriodUs, Handler handler) { + return true; // we could try saying that the sensor doesn't exist and hope the app just doesn't use it then, but as long as we never call the handler the app should leave this alone + } } diff --git a/src/api-impl/android/hardware/usb/UsbManager.java b/src/api-impl/android/hardware/usb/UsbManager.java new file mode 100644 index 00000000..0441cc5a --- /dev/null +++ b/src/api-impl/android/hardware/usb/UsbManager.java @@ -0,0 +1,9 @@ +package android.hardware.usb; + +import java.util.HashMap; + +public class UsbManager { + public HashMap getDeviceList() { + return new HashMap(); + } +} diff --git a/src/api-impl/android/os/Vibrator.java b/src/api-impl/android/os/Vibrator.java new file mode 100644 index 00000000..e0804c29 --- /dev/null +++ b/src/api-impl/android/os/Vibrator.java @@ -0,0 +1,5 @@ +package android.os; + +public class Vibrator { + +} diff --git a/src/api-impl/android/view/Display.java b/src/api-impl/android/view/Display.java index bde6d72c..56f4126d 100644 --- a/src/api-impl/android/view/Display.java +++ b/src/api-impl/android/view/Display.java @@ -17,4 +17,8 @@ public final class Display { public int getRotation() { return 0/*ROTATION_0*/; } + + public float getRefreshRate() { + return 60; // FIXME + } } diff --git a/src/api-impl/android/view/InputDevice.java b/src/api-impl/android/view/InputDevice.java new file mode 100644 index 00000000..b2e74ab5 --- /dev/null +++ b/src/api-impl/android/view/InputDevice.java @@ -0,0 +1,11 @@ +package android.view; + +public class InputDevice { + public static int[] getDeviceIds() { + return new int[]{0}; // might work? + } + + public static InputDevice getDevice(int id) { + return null; + } +} diff --git a/src/api-impl/android/view/InputEvent.java b/src/api-impl/android/view/InputEvent.java index aa2b68e8..85c4b1d9 100644 --- a/src/api-impl/android/view/InputEvent.java +++ b/src/api-impl/android/view/InputEvent.java @@ -18,8 +18,6 @@ package android.view; import java.util.concurrent.atomic.AtomicInteger; -class InputDevice {} - /** * Common base class for input events. */ diff --git a/src/api-impl/android/view/SurfaceView.java b/src/api-impl/android/view/SurfaceView.java index b099f3d9..cb6c5396 100644 --- a/src/api-impl/android/view/SurfaceView.java +++ b/src/api-impl/android/view/SurfaceView.java @@ -6,187 +6,191 @@ import android.graphics.Rect; import android.content.Context; public class SurfaceView extends View { + public SurfaceView(Context context) { super(context); -// native_constructor(context); + native_constructor(context); } + private native void native_constructor(Context context); + public SurfaceHolder getHolder() { - return mSurfaceHolder; + return mSurfaceHolder; } + void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {} + final Surface mSurface = new Surface(); private final SurfaceHolder mSurfaceHolder = new SurfaceHolder() { + private static final String LOG_TAG = "SurfaceHolder"; - private static final String LOG_TAG = "SurfaceHolder"; - - @Override - public boolean isCreating() { -// return mIsCreating; + @Override + public boolean isCreating() { + // return mIsCreating; return false; - } + } - @Override - public void addCallback(Callback callback) { -/* synchronized (mCallbacks) { - // This is a linear search, but in practice we'll - // have only a couple callbacks, so it doesn't matter. - if (mCallbacks.contains(callback) == false) { - mCallbacks.add(callback); - } - }*/ - } + @Override + public void addCallback(Callback callback) { + /* synchronized (mCallbacks) { + // This is a linear search, but in practice we'll + // have only a couple callbacks, so it doesn't matter. + if (mCallbacks.contains(callback) == false) { + mCallbacks.add(callback); + } + }*/ + } - @Override - public void removeCallback(Callback callback) { -/* synchronized (mCallbacks) { - mCallbacks.remove(callback); - }*/ - } + @Override + public void removeCallback(Callback callback) { + /* synchronized (mCallbacks) { + mCallbacks.remove(callback); + }*/ + } - @Override - public void setFixedSize(int width, int height) { -/* if (mRequestedWidth != width || mRequestedHeight != height) { - mRequestedWidth = width; - mRequestedHeight = height; - requestLayout(); - }*/ - } + @Override + public void setFixedSize(int width, int height) { + /* if (mRequestedWidth != width || mRequestedHeight != height) { + mRequestedWidth = width; + mRequestedHeight = height; + requestLayout(); + }*/ + } - @Override - public void setSizeFromLayout() { -/* if (mRequestedWidth != -1 || mRequestedHeight != -1) { - mRequestedWidth = mRequestedHeight = -1; - requestLayout(); - }*/ - } + @Override + public void setSizeFromLayout() { + /* if (mRequestedWidth != -1 || mRequestedHeight != -1) { + mRequestedWidth = mRequestedHeight = -1; + requestLayout(); + }*/ + } - @Override - public void setFormat(int format) { -/* - // for backward compatibility reason, OPAQUE always - // means 565 for SurfaceView - if (format == PixelFormat.OPAQUE) - format = PixelFormat.RGB_565; + @Override + public void setFormat(int format) { + /* + // for backward compatibility reason, OPAQUE always + // means 565 for SurfaceView + if (format == PixelFormat.OPAQUE) + format = PixelFormat.RGB_565; - mRequestedFormat = format; - if (mWindow != null) { - updateWindow(false, false); - }*/ - } + mRequestedFormat = format; + if (mWindow != null) { + updateWindow(false, false); + }*/ + } - /** - * @deprecated setType is now ignored. - */ - @Override - @Deprecated - public void setType(int type) { } + /** + * @deprecated setType is now ignored. + */ + @Override + @Deprecated + public void setType(int type) { } - @Override - public void setKeepScreenOn(boolean screenOn) { -// Message msg = mHandler.obtainMessage(KEEP_SCREEN_ON_MSG); -// msg.arg1 = screenOn ? 1 : 0; -// mHandler.sendMessage(msg); - } + @Override + public void setKeepScreenOn(boolean screenOn) { + // Message msg = mHandler.obtainMessage(KEEP_SCREEN_ON_MSG); + // msg.arg1 = screenOn ? 1 : 0; + // mHandler.sendMessage(msg); + } - /** - * Gets a {@link Canvas} for drawing into the SurfaceView's Surface - * - * After drawing into the provided {@link Canvas}, the caller must - * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface. - * - * The caller must redraw the entire surface. - * @return A canvas for drawing into the surface. - */ - @Override - public Canvas lockCanvas() { -// return internalLockCanvas(null); + /** + * Gets a {@link Canvas} for drawing into the SurfaceView's Surface + * + * After drawing into the provided {@link Canvas}, the caller must + * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface. + * + * The caller must redraw the entire surface. + * @return A canvas for drawing into the surface. + */ + @Override + public Canvas lockCanvas() { + // return internalLockCanvas(null); return null; - } + } - /** - * Gets a {@link Canvas} for drawing into the SurfaceView's Surface - * - * After drawing into the provided {@link Canvas}, the caller must - * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface. - * - * @param inOutDirty A rectangle that represents the dirty region that the caller wants - * to redraw. This function may choose to expand the dirty rectangle if for example - * the surface has been resized or if the previous contents of the surface were - * not available. The caller must redraw the entire dirty region as represented - * by the contents of the inOutDirty rectangle upon return from this function. - * The caller may also pass null instead, in the case where the - * entire surface should be redrawn. - * @return A canvas for drawing into the surface. - */ - @Override - public Canvas lockCanvas(Rect inOutDirty) { -// return internalLockCanvas(inOutDirty); + /** + * Gets a {@link Canvas} for drawing into the SurfaceView's Surface + * + * After drawing into the provided {@link Canvas}, the caller must + * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface. + * + * @param inOutDirty A rectangle that represents the dirty region that the caller wants + * to redraw. This function may choose to expand the dirty rectangle if for example + * the surface has been resized or if the previous contents of the surface were + * not available. The caller must redraw the entire dirty region as represented + * by the contents of the inOutDirty rectangle upon return from this function. + * The caller may also pass null instead, in the case where the + * entire surface should be redrawn. + * @return A canvas for drawing into the surface. + */ + @Override + public Canvas lockCanvas(Rect inOutDirty) { + // return internalLockCanvas(inOutDirty); return null; - } + } - private final Canvas internalLockCanvas(Rect dirty) { -/* mSurfaceLock.lock(); + private final Canvas internalLockCanvas(Rect dirty) { + /* mSurfaceLock.lock(); - if (DEBUG) Log.i(TAG, "Locking canvas... stopped=" - + mDrawingStopped + ", win=" + mWindow); + if (DEBUG) Log.i(TAG, "Locking canvas... stopped=" + + mDrawingStopped + ", win=" + mWindow); - Canvas c = null; - if (!mDrawingStopped && mWindow != null) { - try { - c = mSurface.lockCanvas(dirty); - } catch (Exception e) { - Log.e(LOG_TAG, "Exception locking surface", e); - } - } + Canvas c = null; + if (!mDrawingStopped && mWindow != null) { + try { + c = mSurface.lockCanvas(dirty); + } catch (Exception e) { + Log.e(LOG_TAG, "Exception locking surface", e); + } + } - if (DEBUG) Log.i(TAG, "Returned canvas: " + c); - if (c != null) { - mLastLockTime = SystemClock.uptimeMillis(); - return c; - } + if (DEBUG) Log.i(TAG, "Returned canvas: " + c); + if (c != null) { + mLastLockTime = SystemClock.uptimeMillis(); + return c; + } - // If the Surface is not ready to be drawn, then return null, - // but throttle calls to this function so it isn't called more - // than every 100ms. - long now = SystemClock.uptimeMillis(); - long nextTime = mLastLockTime + 100; - if (nextTime > now) { - try { - Thread.sleep(nextTime-now); - } catch (InterruptedException e) { - } - now = SystemClock.uptimeMillis(); - } - mLastLockTime = now; - mSurfaceLock.unlock(); -*/ - return null; - } - - /** - * Posts the new contents of the {@link Canvas} to the surface and - * releases the {@link Canvas}. - * - * @param canvas The canvas previously obtained from {@link #lockCanvas}. - */ - @Override - public void unlockCanvasAndPost(Canvas canvas) { -// mSurface.unlockCanvasAndPost(canvas); -// mSurfaceLock.unlock(); - } - - @Override - public Surface getSurface() { - return mSurface; - } - - @Override - public Rect getSurfaceFrame() { -// return mSurfaceFrame; + // If the Surface is not ready to be drawn, then return null, + // but throttle calls to this function so it isn't called more + // than every 100ms. + long now = SystemClock.uptimeMillis(); + long nextTime = mLastLockTime + 100; + if (nextTime > now) { + try { + Thread.sleep(nextTime-now); + } catch (InterruptedException e) { + } + now = SystemClock.uptimeMillis(); + } + mLastLockTime = now; + mSurfaceLock.unlock(); + */ return null; - } - }; + } + + /** + * Posts the new contents of the {@link Canvas} to the surface and + * releases the {@link Canvas}. + * + * @param canvas The canvas previously obtained from {@link #lockCanvas}. + */ + @Override + public void unlockCanvasAndPost(Canvas canvas) { + // mSurface.unlockCanvasAndPost(canvas); + // mSurfaceLock.unlock(); + } + + @Override + public Surface getSurface() { + return mSurface; + } + + @Override + public Rect getSurfaceFrame() { + // return mSurfaceFrame; + return null; + } + }; } diff --git a/src/api-impl/android/view/View.java b/src/api-impl/android/view/View.java index f611b683..2ae9e1b4 100644 --- a/src/api-impl/android/view/View.java +++ b/src/api-impl/android/view/View.java @@ -525,6 +525,14 @@ public class View extends Object { // TODO } + public interface OnGenericMotionListener { + // TODO + } + + public interface OnSystemUiVisibilityChangeListener { + // TODO + } + public static interface OnKeyListener { // TODO // boolean onKey(View v, int keyCode, KeyEvent event); @@ -741,6 +749,7 @@ public class View extends Object { public native void setGravity(int gravity); public native void setOnTouchListener(OnTouchListener l); public native void setOnClickListener(OnClickListener l); + public /*native*/ void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {} public native final int getWidth(); public native final int getHeight(); diff --git a/src/api-impl/android/view/Window.java b/src/api-impl/android/view/Window.java index 80d0470d..c3c4373a 100644 --- a/src/api-impl/android/view/Window.java +++ b/src/api-impl/android/view/Window.java @@ -28,5 +28,9 @@ public class Window { set_widget_as_root(native_window, view.widget); } + public View getDecorView() { + return new View(); // FIXME: this can probably backfire + } + private native void set_widget_as_root(long native_window, long widget); } diff --git a/src/api-impl/meson.build b/src/api-impl/meson.build index c564bafb..1b56822f 100644 --- a/src/api-impl/meson.build +++ b/src/api-impl/meson.build @@ -142,6 +142,7 @@ hax_jar = jar('hax', [ 'android/view/WindowManager.java', 'android/view/ViewGroup.java', 'android/view/SurfaceHolder.java', + 'android/view/InputDevice.java', 'android/view/InputEvent.java', 'android/view/View.java', 'android/view/LayoutInflater.java', @@ -154,6 +155,7 @@ hax_jar = jar('hax', [ 'android/hardware/SensorEventListener.java', 'android/hardware/Sensor.java', 'android/hardware/SensorManager.java', + 'android/hardware/usb/UsbManager.java', 'android/text/TextUtils.java', 'android/text/Spannable.java', 'android/text/ClipboardManager.java', @@ -173,6 +175,7 @@ hax_jar = jar('hax', [ 'android/content/Context.java', 'android/content/ActivityNotFoundException.java', 'android/content/DialogInterface.java', + 'android/content/IntentFilter.java', 'android/content/OperationApplicationException.java', 'android/content/res/ColorStateList.java', 'android/content/res/XmlResourceParser.java', diff --git a/src/libandroid/looper.c b/src/libandroid/looper.c new file mode 100644 index 00000000..89cfc5fe --- /dev/null +++ b/src/libandroid/looper.c @@ -0,0 +1,22 @@ +#include + +struct ALooper { + int dummy; +}; + +struct ALooper a_looper; + +struct ALooper* ALooper_forThread() +{ + return &a_looper; +} + +struct ALooper* ALooper_prepare(int opts) +{ + return NULL; +} + +int ALooper_pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData) +{ + return 0; +} diff --git a/src/libandroid/media.c b/src/libandroid/media.c new file mode 100644 index 00000000..aac9db5c --- /dev/null +++ b/src/libandroid/media.c @@ -0,0 +1,567 @@ + +#include +#include +#include +#include + + + +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file defines an NDK API. + * Do not remove methods. + * Do not change method signatures. + * Do not change the value of constants. + * Do not change the size of any of the classes defined in here. + * Do not reference types that are not part of the NDK. + * Do not #include files that aren't part of the NDK. + */ + + +typedef enum { + AMEDIA_OK = 0, + + AMEDIA_ERROR_BASE = -10000, + AMEDIA_ERROR_UNKNOWN = AMEDIA_ERROR_BASE, + AMEDIA_ERROR_MALFORMED = AMEDIA_ERROR_BASE - 1, + AMEDIA_ERROR_UNSUPPORTED = AMEDIA_ERROR_BASE - 2, + AMEDIA_ERROR_INVALID_OBJECT = AMEDIA_ERROR_BASE - 3, + AMEDIA_ERROR_INVALID_PARAMETER = AMEDIA_ERROR_BASE - 4, + AMEDIA_ERROR_INVALID_OPERATION = AMEDIA_ERROR_BASE - 5, + + AMEDIA_DRM_ERROR_BASE = -20000, + AMEDIA_DRM_NOT_PROVISIONED = AMEDIA_DRM_ERROR_BASE - 1, + AMEDIA_DRM_RESOURCE_BUSY = AMEDIA_DRM_ERROR_BASE - 2, + AMEDIA_DRM_DEVICE_REVOKED = AMEDIA_DRM_ERROR_BASE - 3, + AMEDIA_DRM_SHORT_BUFFER = AMEDIA_DRM_ERROR_BASE - 4, + AMEDIA_DRM_SESSION_NOT_OPENED = AMEDIA_DRM_ERROR_BASE - 5, + AMEDIA_DRM_TAMPER_DETECTED = AMEDIA_DRM_ERROR_BASE - 6, + AMEDIA_DRM_VERIFY_FAILED = AMEDIA_DRM_ERROR_BASE - 7, + AMEDIA_DRM_NEED_KEY = AMEDIA_DRM_ERROR_BASE - 8, + AMEDIA_DRM_LICENSE_EXPIRED = AMEDIA_DRM_ERROR_BASE - 9, + + AMEDIA_IMGREADER_ERROR_BASE = -30000, + AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE = AMEDIA_IMGREADER_ERROR_BASE - 1, + AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED = AMEDIA_IMGREADER_ERROR_BASE - 2, + AMEDIA_IMGREADER_CANNOT_LOCK_IMAGE = AMEDIA_IMGREADER_ERROR_BASE - 3, + AMEDIA_IMGREADER_CANNOT_UNLOCK_IMAGE = AMEDIA_IMGREADER_ERROR_BASE - 4, + AMEDIA_IMGREADER_IMAGE_NOT_LOCKED = AMEDIA_IMGREADER_ERROR_BASE - 5, +} media_status_t; + + + +struct AMediaFormat; +typedef struct AMediaFormat AMediaFormat; + +AMediaFormat *AMediaFormat_new(); +media_status_t AMediaFormat_delete(AMediaFormat*); + +/** + * Human readable representation of the format. The returned string is owned by the format, + * and remains valid until the next call to toString, or until the format is deleted. + */ +const char* AMediaFormat_toString(AMediaFormat*); + +bool AMediaFormat_getInt32(AMediaFormat*, const char *name, int32_t *out); +bool AMediaFormat_getInt64(AMediaFormat*, const char *name, int64_t *out); +bool AMediaFormat_getFloat(AMediaFormat*, const char *name, float *out); +/** + * The returned data is owned by the format and remains valid as long as the named entry + * is part of the format. + */ +bool AMediaFormat_getBuffer(AMediaFormat*, const char *name, void** data, size_t *size); +/** + * The returned string is owned by the format, and remains valid until the next call to getString, + * or until the format is deleted. + */ +bool AMediaFormat_getString(AMediaFormat*, const char *name, const char **out); + + +void AMediaFormat_setInt32(AMediaFormat*, const char* name, int32_t value); +void AMediaFormat_setInt64(AMediaFormat*, const char* name, int64_t value); +void AMediaFormat_setFloat(AMediaFormat*, const char* name, float value); +/** + * The provided string is copied into the format. + */ +void AMediaFormat_setString(AMediaFormat*, const char* name, const char* value); +/** + * The provided data is copied into the format. + */ +void AMediaFormat_setBuffer(AMediaFormat*, const char* name, void* data, size_t size); + + + +/** + * XXX should these be ints/enums that we look up in a table as needed? + */ +extern const char* AMEDIAFORMAT_KEY_AAC_PROFILE; +extern const char* AMEDIAFORMAT_KEY_BIT_RATE; +extern const char* AMEDIAFORMAT_KEY_CHANNEL_COUNT; +extern const char* AMEDIAFORMAT_KEY_CHANNEL_MASK; +extern const char* AMEDIAFORMAT_KEY_COLOR_FORMAT; +extern const char* AMEDIAFORMAT_KEY_DURATION; +extern const char* AMEDIAFORMAT_KEY_FLAC_COMPRESSION_LEVEL; +extern const char* AMEDIAFORMAT_KEY_FRAME_RATE; +extern const char* AMEDIAFORMAT_KEY_HEIGHT; +extern const char* AMEDIAFORMAT_KEY_IS_ADTS; +extern const char* AMEDIAFORMAT_KEY_IS_AUTOSELECT; +extern const char* AMEDIAFORMAT_KEY_IS_DEFAULT; +extern const char* AMEDIAFORMAT_KEY_IS_FORCED_SUBTITLE; +extern const char* AMEDIAFORMAT_KEY_I_FRAME_INTERVAL; +extern const char* AMEDIAFORMAT_KEY_LANGUAGE; +extern const char* AMEDIAFORMAT_KEY_MAX_HEIGHT; +extern const char* AMEDIAFORMAT_KEY_MAX_INPUT_SIZE; +extern const char* AMEDIAFORMAT_KEY_MAX_WIDTH; +extern const char* AMEDIAFORMAT_KEY_MIME; +extern const char* AMEDIAFORMAT_KEY_PUSH_BLANK_BUFFERS_ON_STOP; +extern const char* AMEDIAFORMAT_KEY_REPEAT_PREVIOUS_FRAME_AFTER; +extern const char* AMEDIAFORMAT_KEY_SAMPLE_RATE; +extern const char* AMEDIAFORMAT_KEY_WIDTH; +extern const char* AMEDIAFORMAT_KEY_STRIDE; + + + + + +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License") +{ + return -1; +} + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file defines an NDK API. + * Do not remove methods. + * Do not change method signatures. + * Do not change the value of constants. + * Do not change the size of any of the classes defined in here. + * Do not reference types that are not part of the NDK. + * Do not #include files that aren't part of the NDK. + */ + +struct ANativeWindow; + +struct AMediaCodec; +typedef struct AMediaCodec AMediaCodec; + +struct AMediaCodecBufferInfo { + int32_t offset; + int32_t size; + int64_t presentationTimeUs; + uint32_t flags; +}; +typedef struct AMediaCodecBufferInfo AMediaCodecBufferInfo; +typedef struct AMediaCodecCryptoInfo AMediaCodecCryptoInfo; + +enum { + AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM = 4, + AMEDIACODEC_CONFIGURE_FLAG_ENCODE = 1, + AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED = -3, + AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED = -2, + AMEDIACODEC_INFO_TRY_AGAIN_LATER = -1 +}; + + +/** + * Create codec by name. Use this if you know the exact codec you want to use. + * When configuring, you will need to specify whether to use the codec as an + * encoder or decoder. + */ +AMediaCodec* AMediaCodec_createCodecByName(const char *name) +{ + return 0; +} + +/** + * Create codec by mime type. Most applications will use this, specifying a + * mime type obtained from media extractor. + */ +AMediaCodec* AMediaCodec_createDecoderByType(const char *mime_type) +{ + return 0; +} + +/** + * Create encoder by name. + */ +AMediaCodec* AMediaCodec_createEncoderByType(const char *mime_type) +{ + return -0; +} + +/** + * delete the codec and free its resources + */ +media_status_t AMediaCodec_delete(AMediaCodec*) +{ + return -1; +} + +typedef void AMediaCrypto; +typedef void ANativeWindow; + + +/** + * Configure the codec. For decoding you would typically get the format from an extractor. + */ +media_status_t AMediaCodec_configure( + AMediaCodec*, + const AMediaFormat* format, + ANativeWindow* surface, + AMediaCrypto *crypto, + uint32_t flags) +{ + return -1; +} + +/** + * Start the codec. A codec must be configured before it can be started, and must be started + * before buffers can be sent to it. + */ +media_status_t AMediaCodec_start(AMediaCodec*) +{ + return -1; +} + +/** + * Stop the codec. + */ +media_status_t AMediaCodec_stop(AMediaCodec*) +{ + return -1; +} + +/* + * Flush the codec's input and output. All indices previously returned from calls to + * AMediaCodec_dequeueInputBuffer and AMediaCodec_dequeueOutputBuffer become invalid. + */ +media_status_t AMediaCodec_flush(AMediaCodec*) +{ + return -1; +} + +/** + * Get an input buffer. The specified buffer index must have been previously obtained from + * dequeueInputBuffer, and not yet queued. + */ +uint8_t* AMediaCodec_getInputBuffer(AMediaCodec* x, size_t idx, size_t *out_size) +{ + return -0; +} + +/** + * Get an output buffer. The specified buffer index must have been previously obtained from + * dequeueOutputBuffer, and not yet queued. + */ +uint8_t* AMediaCodec_getOutputBuffer(AMediaCodec*, size_t idx, size_t *out_size) +{ + return -0; +} + +/** + * Get the index of the next available input buffer. An app will typically use this with + * getInputBuffer() to get a pointer to the buffer, then copy the data to be encoded or decoded + * into the buffer before passing it to the codec. + */ +ssize_t AMediaCodec_dequeueInputBuffer(AMediaCodec* x, int64_t timeoutUs) +{ + return -1; +} + +/** + * Send the specified buffer to the codec for processing. + */ +media_status_t AMediaCodec_queueInputBuffer(AMediaCodec*, + size_t idx, off_t offset, size_t size, uint64_t time, uint32_t flags) +{ + return -1; +} + +/** + * Send the specified buffer to the codec for processing. + */ +media_status_t AMediaCodec_queueSecureInputBuffer(AMediaCodec*, + size_t idx, off_t offset, AMediaCodecCryptoInfo*, uint64_t time, uint32_t flags) +{ + return -1; +} + +/** + * Get the index of the next available buffer of processed data. + */ +ssize_t AMediaCodec_dequeueOutputBuffer(AMediaCodec*, AMediaCodecBufferInfo *info, + int64_t timeoutUs) +{ + return -1; +} +AMediaFormat* AMediaCodec_getOutputFormat(AMediaCodec*) +{ + return -0; +} + +/** + * If you are done with a buffer, use this call to return the buffer to + * the codec. If you previously specified a surface when configuring this + * video decoder you can optionally render the buffer. + */ +media_status_t AMediaCodec_releaseOutputBuffer(AMediaCodec*, size_t idx, bool render) +{ + return -1; +} + +/** + * Dynamically sets the output surface of a codec. + * + * This can only be used if the codec was configured with an output surface. The + * new output surface should have a compatible usage type to the original output surface. + * E.g. codecs may not support switching from a SurfaceTexture (GPU readable) output + * to ImageReader (software readable) output. + * + * For more details, see the Java documentation for MediaCodec.setOutputSurface. + */ +media_status_t AMediaCodec_setOutputSurface(AMediaCodec*, ANativeWindow* surface) +{ + return -1; +} + +/** + * If you are done with a buffer, use this call to update its surface timestamp + * and return it to the codec to render it on the output surface. If you + * have not specified an output surface when configuring this video codec, + * this call will simply return the buffer to the codec. + * + * For more details, see the Java documentation for MediaCodec.releaseOutputBuffer. + */ +media_status_t AMediaCodec_releaseOutputBufferAtTime( + AMediaCodec *mData, size_t idx, int64_t timestampNs) +{ + return -1; +} + +/** + * Creates a Surface that can be used as the input to encoder, in place of input buffers + * + * This can only be called after the codec has been configured via + * AMediaCodec_configure(..) +{ + return -1; +} and before AMediaCodec_start() has been called. + * + * The application is responsible for releasing the surface by calling + * ANativeWindow_release() when done. + * + * For more details, see the Java documentation for MediaCodec.createInputSurface. + */ +media_status_t AMediaCodec_createInputSurface( + AMediaCodec *mData, ANativeWindow **surface) +{ + return -1; +} + +/** + * Creates a persistent Surface that can be used as the input to encoder + * + * Persistent surface can be reused by MediaCodec instances and can be set + * on a new instance via AMediaCodec_setInputSurface(). + * A persistent surface can be connected to at most one instance of MediaCodec + * at any point in time. + * + * The application is responsible for releasing the surface by calling + * ANativeWindow_release() when done. + * + * For more details, see the Java documentation for MediaCodec.createPersistentInputSurface. + */ +media_status_t AMediaCodec_createPersistentInputSurface( + ANativeWindow **surface) +{ + return -1; +} + +/** + * Set a persistent-surface that can be used as the input to encoder, in place of input buffers + * + * The surface provided *must* be a persistent surface created via + * AMediaCodec_createPersistentInputSurface() + * This can only be called after the codec has been configured by calling + * AMediaCodec_configure(..) +{ + return -1; +} and before AMediaCodec_start() has been called. + * + * For more details, see the Java documentation for MediaCodec.setInputSurface. + */ +media_status_t AMediaCodec_setInputSurface( + AMediaCodec *mData, ANativeWindow *surface) +{ + return -1; +} + +/** + * Signal additional parameters to the codec instance. + * + * Parameters can be communicated only when the codec is running, i.e + * after AMediaCodec_start() has been called. + * + * NOTE: Some of these parameter changes may silently fail to apply. + */ +media_status_t AMediaCodec_setParameters( + AMediaCodec *mData, const AMediaFormat* params) +{ + return -1; +} + +/** + * Signals end-of-stream on input. Equivalent to submitting an empty buffer with + * AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM set. + * + * Returns AMEDIA_ERROR_INVALID_OPERATION when used with an encoder not in executing state + * or not receiving input from a Surface created by AMediaCodec_createInputSurface or + * AMediaCodec_createPersistentInputSurface. + * + * Returns the previous codec error if one exists. + * + * Returns AMEDIA_OK when completed succesfully. + * + * For more details, see the Java documentation for MediaCodec.signalEndOfInputStream. + */ +media_status_t AMediaCodec_signalEndOfInputStream(AMediaCodec *mData) +{ + return -1; +} + + + +typedef enum { + AMEDIACODECRYPTOINFO_MODE_CLEAR = 0, + AMEDIACODECRYPTOINFO_MODE_AES_CTR = 1, + AMEDIACODECRYPTOINFO_MODE_AES_WV = 2, + AMEDIACODECRYPTOINFO_MODE_AES_CBC = 3 +} cryptoinfo_mode_t; + +typedef struct { + int32_t encryptBlocks; + int32_t skipBlocks; +} cryptoinfo_pattern_t; + +/** + * Create an AMediaCodecCryptoInfo from scratch. Use this if you need to use custom + * crypto info, rather than one obtained from AMediaExtractor. + * + * AMediaCodecCryptoInfo describes the structure of an (at least + * partially) encrypted input sample. + * A buffer's data is considered to be partitioned into "subsamples", + * each subsample starts with a (potentially empty) run of plain, + * unencrypted bytes followed by a (also potentially empty) run of + * encrypted bytes. + * numBytesOfClearData can be null to indicate that all data is encrypted. + * This information encapsulates per-sample metadata as outlined in + * ISO/IEC FDIS 23001-7:2011 "Common encryption in ISO base media file format files". + */ +AMediaCodecCryptoInfo *AMediaCodecCryptoInfo_new( + int numsubsamples, + uint8_t key[16], + uint8_t iv[16], + cryptoinfo_mode_t mode, + size_t *clearbytes, + size_t *encryptedbytes) +{ + return -0; +} + +/** + * delete an AMediaCodecCryptoInfo created previously with AMediaCodecCryptoInfo_new, or + * obtained from AMediaExtractor + */ +media_status_t AMediaCodecCryptoInfo_delete(AMediaCodecCryptoInfo*) +{ + return -1; +} + +/** + * Set the crypto pattern on an AMediaCryptoInfo object + */ +void AMediaCodecCryptoInfo_setPattern( + AMediaCodecCryptoInfo *info, + cryptoinfo_pattern_t *pattern) +{ + return; +} + +/** + * The number of subsamples that make up the buffer's contents. + */ +size_t AMediaCodecCryptoInfo_getNumSubSamples(AMediaCodecCryptoInfo*) +{ + return -1; +} + +/** + * A 16-byte opaque key + */ +media_status_t AMediaCodecCryptoInfo_getKey(AMediaCodecCryptoInfo*, uint8_t *dst) +{ + return -1; +} + +/** + * A 16-byte initialization vector + */ +media_status_t AMediaCodecCryptoInfo_getIV(AMediaCodecCryptoInfo*, uint8_t *dst) +{ + return -1; +} + +/** + * The type of encryption that has been applied, + * one of AMEDIACODECRYPTOINFO_MODE_CLEAR or AMEDIACODECRYPTOINFO_MODE_AES_CTR. + */ +cryptoinfo_mode_t AMediaCodecCryptoInfo_getMode(AMediaCodecCryptoInfo*) +{ + return -1; +} + +/** + * The number of leading unencrypted bytes in each subsample. + */ +media_status_t AMediaCodecCryptoInfo_getClearBytes(AMediaCodecCryptoInfo*, size_t *dst) +{ + return -1; +} + +/** + * The number of trailing encrypted bytes in each subsample. + */ +media_status_t AMediaCodecCryptoInfo_getEncryptedBytes(AMediaCodecCryptoInfo*, size_t *dst) +{ + return -1; +} + + diff --git a/src/libandroid/native_window.c b/src/libandroid/native_window.c new file mode 100644 index 00000000..abec0d3e --- /dev/null +++ b/src/libandroid/native_window.c @@ -0,0 +1,343 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License") +{ + return -1; +} + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @addtogroup NativeActivity Native Activity + * @{ + */ + +/** + * @file native_window.h + * @brief API for accessing a native window. + */ + + +#include +#include + +#include +#include + +//#include +#include + +#define GLFW_INCLUDE_NONE +#include + +#define GLFW_EXPOSE_NATIVE_WAYLAND +#include + +#include + + +/** + * Transforms that can be applied to buffers as they are displayed to a window. + * + * Supported transforms are any combination of horizontal mirror, vertical + * mirror, and clockwise 90 degree rotation, in that order. Rotations of 180 + * and 270 degrees are made up of those basic transforms. + */ +enum ANativeWindowTransform { + ANATIVEWINDOW_TRANSFORM_IDENTITY = 0x00, + ANATIVEWINDOW_TRANSFORM_MIRROR_HORIZONTAL = 0x01, + ANATIVEWINDOW_TRANSFORM_MIRROR_VERTICAL = 0x02, + ANATIVEWINDOW_TRANSFORM_ROTATE_90 = 0x04, + + ANATIVEWINDOW_TRANSFORM_ROTATE_180 = ANATIVEWINDOW_TRANSFORM_MIRROR_HORIZONTAL | + ANATIVEWINDOW_TRANSFORM_MIRROR_VERTICAL, + ANATIVEWINDOW_TRANSFORM_ROTATE_270 = ANATIVEWINDOW_TRANSFORM_ROTATE_180 | + ANATIVEWINDOW_TRANSFORM_ROTATE_90, +}; + +struct ANativeWindow { + GLFWwindow *glfw_window; + EGLNativeWindowType egl_window; +}; + +/** + * Opaque type that provides access to a native window. + * + * A pointer can be obtained using {@link ANativeWindow_fromSurface()}. + */ +typedef struct ANativeWindow ANativeWindow; + +/** + * Struct that represents a windows buffer. + * + * A pointer can be obtained using {@link ANativeWindow_lock()}. + */ +typedef struct ANativeWindow_Buffer { + // The number of pixels that are show horizontally. + int32_t width; + + // The number of pixels that are shown vertically. + int32_t height; + + // The number of *pixels* that a line in the buffer takes in + // memory. This may be >= width. + int32_t stride; + + // The format of the buffer. One of AHARDWAREBUFFER_FORMAT_* + int32_t format; + + // The actual bits. + void* bits; + + // Do not touch. + uint32_t reserved[6]; +} ANativeWindow_Buffer; + +/** + * Acquire a reference on the given {@link ANativeWindow} object. This prevents the object + * from being deleted until the reference is removed. + */ +void ANativeWindow_acquire(struct ANativeWindow *native_window) +{ + // FIXME: refcount +} + +void ANativeWindow_release(struct ANativeWindow *native_window) +{ + // FIXME: refcount +} + +int32_t ANativeWindow_getWidth(struct ANativeWindow *native_window) +{ + int v = 0; + glfwGetWindowSize(native_window->glfw_window, &v, NULL); + return v; +} + +int32_t ANativeWindow_getHeight(struct ANativeWindow *native_window) +{ + int v = 0; + glfwGetWindowSize(native_window->glfw_window, NULL, &v); + return v; +} + +/** + * Return the current pixel format (AHARDWAREBUFFER_FORMAT_*) of the window surface. + * + * \return a negative value on error. + */ +int32_t ANativeWindow_getFormat(ANativeWindow* window) +{ + return -1; +} + +/** + * Change the format and size of the window buffers. + * + * The width and height control the number of pixels in the buffers, not the + * dimensions of the window on screen. If these are different than the + * window's physical size, then its buffer will be scaled to match that size + * when compositing it to the screen. The width and height must be either both zero + * or both non-zero. + * + * For all of these parameters, if 0 is supplied then the window's base + * value will come back in force. + * + * \param width width of the buffers in pixels. + * \param height height of the buffers in pixels. + * \param format one of AHARDWAREBUFFER_FORMAT_* constants. + * \return 0 for success, or a negative value on error. + */ +int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window, + int32_t width, int32_t height, int32_t format) +{ + return -1; +} + +/** + * Lock the window's next drawing surface for writing. + * inOutDirtyBounds is used as an in/out parameter, upon entering the + * function, it contains the dirty region, that is, the region the caller + * intends to redraw. When the function returns, inOutDirtyBounds is updated + * with the actual area the caller needs to redraw -- this region is often + * extended by {@link ANativeWindow_lock}. + * + * \return 0 for success, or a negative value on error. + */ + +typedef void ARect; + +int32_t ANativeWindow_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffer, + ARect* inOutDirtyBounds) +{ + return -1; +} + +/** + * Unlock the window's drawing surface after previously locking it, + * posting the new buffer to the display. + * + * \return 0 for success, or a negative value on error. + */ +int32_t ANativeWindow_unlockAndPost(ANativeWindow* window) +{ + return -1; +} + +/** + * Set a transform that will be applied to future buffers posted to the window. + * + * \param transform combination of {@link ANativeWindowTransform} flags + * \return 0 for success, or -EINVAL if \p transform is invalid + */ +int32_t ANativeWindow_setBuffersTransform(ANativeWindow* window, int32_t transform) +{ + return -1; +} + +// FIXME: include the header +struct wl_surface; +struct wl_egl_window *wl_egl_window_create(struct wl_surface *surface,int width, int height); + +static void +glfw_error_cb(int code, const char *error) +{ + fprintf(stderr, "glfw: (%d) %s\n", code, error); +} + +ANativeWindow * ANativeWindow_fromSurface(JNIEnv* env, jobject surface) +{ + // FIXME: add a path for x11 +// TODO: something with subsurfaces +/* GdkDisplay *display = gdk_display_get_default(); //TODO: edge cases? + struct wl_display *wl_display = gdk_wayland_display_get_wl_display(display); + struct wl_compositor *wl_compositor = gdk_wayland_display_get_wl_compositor(display); + //GdkSurface *popup_surface = gdk_surface_new_popup (GdkSurface* parent, gboolean autohide) // TODO: could this work better for us? (need to somehow get the parent surface) + struct wl_surface *toplevel_surface = gdk_wayland_surface_get_wl_surface(gdk_surface_new_toplevel(display)); + struct wl_surface *our_surface = wl_compositor_create_surface(wl_compositor); +// wl_subsurface* our_subsurface = wl_subcompositor_get_subsurface(wl_compositor, our_surface; our_parent); + struct wl_egl_window *egl_window = wl_egl_window_create(our_surface, 700, 700); + return (ANativeWindow *)egl_window;*/ + + struct ANativeWindow *native_window = malloc(sizeof(struct ANativeWindow)); + + glfwInit(); + fprintf(stderr, "glfw: %s\n", glfwGetVersionString()); + glfwSetErrorCallback(glfw_error_cb); + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + native_window->glfw_window = glfwCreateWindow(700, 700, "FIXME: don't create a separate window for this widget", NULL, NULL); + struct wl_surface *wayland_surface = glfwGetWaylandWindow(native_window->glfw_window); + int width, height; + glfwGetWindowSize(native_window->glfw_window, &width, &height); + printf("glfw::: width: %d, height: %d\n", width, height); + native_window->egl_window = (EGLNativeWindowType)wl_egl_window_create(wayland_surface, width, height); + + printf("EGL::: wayland_surface: %p\n", wayland_surface); + printf("EGL::: native_window->glfw_window: %p\n", native_window->glfw_window); + printf("EGL::: native_window->egl_window: %ld\n", native_window->egl_window); + + return native_window; +} + +ANativeWindow * ANativeWindow_fromSurfaceTexture(JNIEnv* env, jobject surfaceTexture) +{ + return NULL; +} + +// temporary for debugging +static void PrintConfigAttributes(EGLDisplay display, EGLConfig config) +{ + EGLint value; + printf("-------------------------------------------------------------------------------\n"); + eglGetConfigAttrib(display,config,EGL_CONFIG_ID,&value); + printf("EGL_CONFIG_ID %d\n",value); + + eglGetConfigAttrib(display,config,EGL_BUFFER_SIZE,&value); + printf("EGL_BUFFER_SIZE %d\n",value); + eglGetConfigAttrib(display,config,EGL_RED_SIZE,&value); + printf("EGL_RED_SIZE %d\n",value); + eglGetConfigAttrib(display,config,EGL_GREEN_SIZE,&value); + printf("EGL_GREEN_SIZE %d\n",value); + eglGetConfigAttrib(display,config,EGL_BLUE_SIZE,&value); + printf("EGL_BLUE_SIZE %d\n",value); + eglGetConfigAttrib(display,config,EGL_ALPHA_SIZE,&value); + printf("EGL_ALPHA_SIZE %d\n",value); + eglGetConfigAttrib(display,config,EGL_DEPTH_SIZE,&value); + printf("EGL_DEPTH_SIZE %d\n",value); + eglGetConfigAttrib(display,config,EGL_STENCIL_SIZE,&value); + printf("EGL_STENCIL_SIZE %d\n",value); + eglGetConfigAttrib(display,config,EGL_SAMPLE_BUFFERS,&value); + printf("EGL_SAMPLE_BUFFERS %d\n",value); + eglGetConfigAttrib(display,config,EGL_SAMPLES,&value); + printf("EGL_SAMPLES %d\n",value); + + eglGetConfigAttrib(display,config,EGL_CONFIG_CAVEAT,&value); + switch(value) + { + case EGL_NONE: + printf("EGL_CONFIG_CAVEAT EGL_NONE\n"); + break; + case EGL_SLOW_CONFIG: + printf("EGL_CONFIG_CAVEAT EGL_SLOW_CONFIG\n"); + break; + } + + eglGetConfigAttrib(display,config,EGL_MAX_PBUFFER_WIDTH,&value); + printf("EGL_MAX_PBUFFER_WIDTH %d\n",value); + eglGetConfigAttrib(display,config,EGL_MAX_PBUFFER_HEIGHT,&value); + printf("EGL_MAX_PBUFFER_HEIGHT %d\n",value); + eglGetConfigAttrib(display,config,EGL_MAX_PBUFFER_PIXELS,&value); + printf("EGL_MAX_PBUFFER_PIXELS %d\n",value); + eglGetConfigAttrib(display,config,EGL_NATIVE_RENDERABLE,&value); + printf("EGL_NATIVE_RENDERABLE %s \n",(value ? "true" : "false")); + eglGetConfigAttrib(display,config,EGL_NATIVE_VISUAL_ID,&value); + printf("EGL_NATIVE_VISUAL_ID %d\n",value); + eglGetConfigAttrib(display,config,EGL_NATIVE_VISUAL_TYPE,&value); + printf("EGL_NATIVE_VISUAL_TYPE %d\n",value); + eglGetConfigAttrib(display,config,EGL_RENDERABLE_TYPE,&value); + printf("EGL_RENDERABLE_TYPE %d\n",value); + eglGetConfigAttrib(display,config,EGL_SURFACE_TYPE,&value); + printf("EGL_SURFACE_TYPE %d\n",value); + eglGetConfigAttrib(display,config,EGL_TRANSPARENT_TYPE,&value); + printf("EGL_TRANSPARENT_TYPE %d\n",value); + printf("-------------------------------------------------------------------------------\n"); +} + +// FIXME: this possibly belongs elsewhere + +EGLDisplay bionic_eglGetDisplay(NativeDisplayType native_display) +{ + /* + * On android, at least SDL passes 0 (EGL_DISPLAY_DEFAULT) to eglGetDisplay and uses the resulting display. + * We obviously want to make the app use the correct display, which may happen to be a different one + * than the "default" display (especially on Wayland) + */ + glfwInit(); // it's allegedly safe to call this multiple times + struct wl_display *glfw_wl_display = glfwGetWaylandDisplay(); + return eglGetPlatformDisplay(EGL_PLATFORM_WAYLAND_KHR, glfw_wl_display, NULL); +} + +EGLSurface bionic_eglCreateWindowSurface(EGLDisplay display, EGLConfig config, struct ANativeWindow *native_window, EGLint const *attrib_list) +{ + // TODO: eglGetDisplay((EGLNativeDisplayType)0) isn't ideal... + PrintConfigAttributes(display, config); + EGLSurface ret = eglCreateWindowSurface(display, config, native_window->egl_window, attrib_list); + + printf("EGL::: native_window->glfw_window: %p\n", native_window->glfw_window); + printf("EGL::: native_window->egl_window: %ld\n", native_window->egl_window); + printf("EGL::: eglGetError: %d\n", eglGetError()); + + printf("EGL::: ret: %p\n", ret); + + return ret; +} diff --git a/src/libandroid/sensor.c b/src/libandroid/sensor.c new file mode 100644 index 00000000..1727762a --- /dev/null +++ b/src/libandroid/sensor.c @@ -0,0 +1,155 @@ +#include +#include +#include +#include + +struct ASensorManager { + int dummy; +}; + +struct ASensorEventQueue; +struct ASensorList; +struct ASensor; +struct ALooper; +struct AHardwareBuffer; +struct ASensorEvent; + +typedef void * ALooper_callbackFunc; + +struct ASensorManager a_sensor_manager; + +struct ASensorManager* ASensorManager_getInstance() +{ + return &a_sensor_manager; +} + +// --- sensor manager + +int ASensorManager_getSensorList(struct ASensorManager* manager, struct ASensorList* list) +{ + return 0; // the number of sensors - any sane app should see this and stop messing with sensors +} + +int ASensorManager_destroyEventQueue(struct ASensorManager* manager, struct ASensorEventQueue* queue) +{ + return 0; +} + + +int ASensorManager_createSharedMemoryDirectChannel(struct ASensorManager* manager, int fd, size_t size) +{ + return 0; +} + + +int ASensorManager_createHardwareBufferDirectChannel(struct ASensorManager* manager, struct AHardwareBuffer const * buffer, size_t size) +{ + return 0; +} + + +void ASensorManager_destroyDirectChannel(struct ASensorManager* manager, int channelId) +{ + return; +} + + +int ASensorManager_configureDirectReport(struct ASensorManager* manager, struct ASensor const* sensor, int channelId, int rate) +{ + return 0; +} + +// --- event queue + +struct ASensorEventQueue* ASensorManager_createEventQueue(struct ASensorManager* manager, struct ALooper* looper, int ident, ALooper_callbackFunc callback, void* data) +{ + return NULL; +} + +int ASensorEventQueue_registerSensor(struct ASensorEventQueue* queue, struct ASensor const* sensor, int32_t samplingPeriodUs, int64_t maxBatchReportLatencyUs) +{ + return 0; +} + + +int ASensorEventQueue_enableSensor(struct ASensorEventQueue* queue, struct ASensor const* sensor) +{ + return 0; +} + + +int ASensorEventQueue_disableSensor(struct ASensorEventQueue* queue, struct ASensor const* sensor) +{ + return 0; +} + + +int ASensorEventQueue_setEventRate(struct ASensorEventQueue* queue, struct ASensor const* sensor, int32_t usec) +{ + return 0; +} + + +int ASensorEventQueue_hasEvents(struct ASensorEventQueue* queue) +{ + return 0; +} + + +ssize_t ASensorEventQueue_getEvents(struct ASensorEventQueue* queue, struct ASensorEvent* events, size_t count) +{ + return 0; +} + +// --- sensor + +const char* ASensor_getName(struct ASensor const* sensor) +{ + return "FIXME-ASensor_getName"; +} + +const char* ASensor_getVendor(struct ASensor const* sensor) +{ + return "FIXME-ASensor_getVendor"; +} + +int ASensor_getType(struct ASensor const* sensor) +{ + return 0; +} +float ASensor_getResolution(struct ASensor const* sensor) +{ + return 1; +} +int ASensor_getMinDelay(struct ASensor const* sensor) +{ + return 0; +} +int ASensor_getFifoMaxEventCount(struct ASensor const* sensor) +{ + return 0; +} +int ASensor_getFifoReservedEventCount(struct ASensor const* sensor) +{ + return 0; +} +const char* ASensor_getStringType(struct ASensor const* sensor) +{ + return "FIXME-ASensor_getStringType"; +} +int ASensor_getReportingMode(struct ASensor const* sensor) +{ + return 0; +} +bool ASensor_isWakeUpSensor(struct ASensor const* sensor) +{ + return 0; +} +bool ASensor_isDirectChannelTypeSupported(struct ASensor const* sensor, int channelType) +{ + return 0; +} +int ASensor_getHighestDirectReportRateLevel(struct ASensor const* sensor) +{ + return 1; +} diff --git a/src/main-executable/main.c b/src/main-executable/main.c index 215ecc36..cded24cd 100644 --- a/src/main-executable/main.c +++ b/src/main-executable/main.c @@ -294,9 +294,13 @@ static void open(GtkApplication *app, GFile** files, gint nfiles, const gchar* h (*env)->ExceptionDescribe(env); // TODO: some apps wait for this to actually do stuff -/* (*env)->CallVoidMethod(env, handle_cache.apk_main_activity.object, handle_cache.apk_main_activity.onWindowFocusChanged, true); + (*env)->CallVoidMethod(env, handle_cache.apk_main_activity.object, handle_cache.apk_main_activity.onResume); if((*env)->ExceptionCheck(env)) - (*env)->ExceptionDescribe(env);*/ + (*env)->ExceptionDescribe(env); + + (*env)->CallVoidMethod(env, handle_cache.apk_main_activity.object, handle_cache.apk_main_activity.onWindowFocusChanged, true); + if((*env)->ExceptionCheck(env)) + (*env)->ExceptionDescribe(env); } static void activate(GtkApplication *app, struct jni_callback_data *d)