21 #include "../../SDL_internal.h" 33 #include "../../events/SDL_events_c.h" 34 #include "../../video/android/SDL_androidkeyboard.h" 35 #include "../../video/android/SDL_androidmouse.h" 36 #include "../../video/android/SDL_androidtouch.h" 37 #include "../../video/android/SDL_androidvideo.h" 38 #include "../../video/android/SDL_androidwindow.h" 39 #include "../../joystick/android/SDL_sysjoystick_c.h" 41 #include <android/log.h> 43 #include <sys/types.h> 45 #define LOG_TAG "SDL_android" 48 #define LOGI(...) do {} while (0) 49 #define LOGE(...) do {} while (0) 54 static void Android_JNI_ThreadDestroyed(
void*);
60 #include <android/log.h> 66 static pthread_key_t mThreadKey;
67 static JavaVM* mJavaVM;
70 static jclass mActivityClass;
73 static jmethodID midGetNativeSurface;
74 static jmethodID midAudioOpen;
75 static jmethodID midAudioWriteShortBuffer;
76 static jmethodID midAudioWriteByteBuffer;
77 static jmethodID midAudioClose;
78 static jmethodID midCaptureOpen;
79 static jmethodID midCaptureReadShortBuffer;
80 static jmethodID midCaptureReadByteBuffer;
81 static jmethodID midCaptureClose;
82 static jmethodID midPollInputDevices;
85 static float fLastAccelerometer[3];
93 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm,
void* reserved)
97 LOGI(
"JNI_OnLoad called");
98 if ((*mJavaVM)->GetEnv(mJavaVM, (
void**) &env, JNI_VERSION_1_4) != JNI_OK) {
99 LOGE(
"Failed to get the environment using GetEnv()");
106 if (pthread_key_create(&mThreadKey, Android_JNI_ThreadDestroyed) != 0) {
107 __android_log_print(ANDROID_LOG_ERROR,
"SDL",
"Error initializing pthread key");
111 return JNI_VERSION_1_4;
115 JNIEXPORT
void JNICALL SDL_Android_Init(JNIEnv* mEnv, jclass cls)
117 __android_log_print(ANDROID_LOG_INFO,
"SDL",
"SDL_Android_Init()");
121 mActivityClass = (jclass)((*mEnv)->NewGlobalRef(mEnv, cls));
123 midGetNativeSurface = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
124 "getNativeSurface",
"()Landroid/view/Surface;");
125 midAudioOpen = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
126 "audioOpen",
"(IZZI)I");
127 midAudioWriteShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
128 "audioWriteShortBuffer",
"([S)V");
129 midAudioWriteByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
130 "audioWriteByteBuffer",
"([B)V");
131 midAudioClose = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
132 "audioClose",
"()V");
133 midCaptureOpen = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
134 "captureOpen",
"(IZZI)I");
135 midCaptureReadShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
136 "captureReadShortBuffer",
"([SZ)I");
137 midCaptureReadByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
138 "captureReadByteBuffer",
"([BZ)I");
139 midCaptureClose = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
140 "captureClose",
"()V");
141 midPollInputDevices = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
142 "pollInputDevices",
"()V");
146 if (!midGetNativeSurface ||
147 !midAudioOpen || !midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioClose ||
148 !midCaptureOpen || !midCaptureReadShortBuffer || !midCaptureReadByteBuffer || !midCaptureClose ||
149 !midPollInputDevices) {
150 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"SDL: Couldn't locate Java callbacks, check that they're named and typed correctly");
152 __android_log_print(ANDROID_LOG_INFO,
"SDL",
"SDL_Android_Init() finished!");
156 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_onNativeDropFile(
157 JNIEnv* env, jclass jcls,
160 const char *
path = (*env)->GetStringUTFChars(env, filename,
NULL);
162 (*env)->ReleaseStringUTFChars(env, filename, path);
167 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_onNativeResize(
168 JNIEnv* env, jclass jcls,
175 JNIEXPORT jint JNICALL Java_org_libsdl_app_SDLActivity_onNativePadDown(
176 JNIEnv* env, jclass jcls,
177 jint device_id, jint keycode)
179 return Android_OnPadDown(device_id, keycode);
183 JNIEXPORT jint JNICALL Java_org_libsdl_app_SDLActivity_onNativePadUp(
184 JNIEnv* env, jclass jcls,
185 jint device_id, jint keycode)
187 return Android_OnPadUp(device_id, keycode);
191 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_onNativeJoy(
192 JNIEnv* env, jclass jcls,
195 Android_OnJoy(device_id, axis, value);
199 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_onNativeHat(
200 JNIEnv* env, jclass jcls,
201 jint device_id, jint hat_id, jint
x, jint
y)
203 Android_OnHat(device_id, hat_id, x, y);
207 JNIEXPORT jint JNICALL Java_org_libsdl_app_SDLActivity_nativeAddJoystick(
208 JNIEnv* env, jclass jcls,
209 jint device_id, jstring device_name, jint is_accelerometer,
210 jint nbuttons, jint naxes, jint nhats, jint nballs)
213 const char *
name = (*env)->GetStringUTFChars(env, device_name,
NULL);
215 retval = Android_AddJoystick(device_id, name, (
SDL_bool) is_accelerometer, nbuttons, naxes, nhats, nballs);
217 (*env)->ReleaseStringUTFChars(env, device_name, name);
222 JNIEXPORT jint JNICALL Java_org_libsdl_app_SDLActivity_nativeRemoveJoystick(
223 JNIEnv* env, jclass jcls, jint device_id)
225 return Android_RemoveJoystick(device_id);
230 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_onNativeSurfaceChanged(JNIEnv* env, jclass jcls)
256 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_onNativeSurfaceDestroyed(JNIEnv* env, jclass jcls)
273 SDL_EGL_MakeCurrent(_this,
NULL,
NULL);
283 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_onNativeKeyDown(
284 JNIEnv* env, jclass jcls, jint keycode)
290 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_onNativeKeyUp(
291 JNIEnv* env, jclass jcls, jint keycode)
297 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_onNativeKeyboardFocusLost(
298 JNIEnv* env, jclass jcls)
306 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_onNativeTouch(
307 JNIEnv* env, jclass jcls,
308 jint touch_device_id_in, jint pointer_finger_id_in,
309 jint
action, jfloat
x, jfloat
y, jfloat
p)
311 Android_OnTouch(touch_device_id_in, pointer_finger_id_in, action, x, y, p);
315 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_onNativeMouse(
316 JNIEnv* env, jclass jcls,
323 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_onNativeAccel(
324 JNIEnv* env, jclass jcls,
325 jfloat
x, jfloat
y, jfloat
z)
327 fLastAccelerometer[0] =
x;
328 fLastAccelerometer[1] =
y;
329 fLastAccelerometer[2] =
z;
334 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_nativeLowMemory(
335 JNIEnv* env, jclass cls)
341 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_nativeQuit(
342 JNIEnv* env, jclass cls)
357 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_nativePause(
358 JNIEnv* env, jclass cls)
360 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"nativePause()");
374 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLActivity_nativeResume(
375 JNIEnv* env, jclass cls)
377 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"nativeResume()");
392 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLInputConnection_nativeCommitText(
393 JNIEnv* env, jclass cls,
394 jstring
text, jint newCursorPosition)
396 const char *utftext = (*env)->GetStringUTFChars(env, text,
NULL);
400 (*env)->ReleaseStringUTFChars(env, text, utftext);
403 JNIEXPORT
void JNICALL Java_org_libsdl_app_SDLInputConnection_nativeSetComposingText(
404 JNIEnv* env, jclass cls,
405 jstring text, jint newCursorPosition)
407 const char *utftext = (*env)->GetStringUTFChars(env, text,
NULL);
411 (*env)->ReleaseStringUTFChars(env, text, utftext);
414 JNIEXPORT jstring JNICALL Java_org_libsdl_app_SDLActivity_nativeGetHint(JNIEnv* env, jclass cls, jstring name) {
415 const char *utfname = (*env)->GetStringUTFChars(env, name,
NULL);
418 jstring
result = (*env)->NewStringUTF(env, hint);
419 (*env)->ReleaseStringUTFChars(env, name, utfname);
428 static int s_active = 0;
429 struct LocalReferenceHolder
435 static struct LocalReferenceHolder LocalReferenceHolder_Setup(const char *
func)
437 struct LocalReferenceHolder refholder;
438 refholder.m_env =
NULL;
439 refholder.m_func =
func;
446 static SDL_bool LocalReferenceHolder_Init(
struct LocalReferenceHolder *refholder, JNIEnv *env)
448 const int capacity = 16;
449 if ((*env)->PushLocalFrame(env, capacity) < 0) {
450 SDL_SetError(
"Failed to allocate enough JVM local references");
454 refholder->m_env = env;
458 static void LocalReferenceHolder_Cleanup(
struct LocalReferenceHolder *refholder)
461 SDL_Log(
"Leaving function %s", refholder->m_func);
463 if (refholder->m_env) {
464 JNIEnv* env = refholder->m_env;
465 (*env)->PopLocalFrame(env,
NULL);
470 static SDL_bool LocalReferenceHolder_IsActive(
void)
481 s = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetNativeSurface);
482 anw = ANativeWindow_fromSurface(env, s);
483 (*env)->DeleteLocalRef(env, s);
492 mid = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
"setActivityTitle",
"(Ljava/lang/String;)Z");
494 jstring jtitle = (jstring)((*mEnv)->NewStringUTF(mEnv, title));
495 (*mEnv)->CallStaticBooleanMethod(mEnv, mActivityClass, mid, jtitle);
496 (*mEnv)->DeleteLocalRef(mEnv, jtitle);
506 for (i = 0; i < 3; ++
i) {
507 values[
i] = fLastAccelerometer[
i];
516 static void Android_JNI_ThreadDestroyed(
void*
value)
519 JNIEnv *env = (JNIEnv*) value;
521 (*mJavaVM)->DetachCurrentThread(mJavaVM);
522 pthread_setspecific(mThreadKey,
NULL);
541 int status = (*mJavaVM)->AttachCurrentThread(mJavaVM, &env,
NULL);
543 LOGE(
"failed to attach current thread");
556 pthread_setspecific(mThreadKey, (
void*) env);
570 static jboolean audioBuffer16Bit = JNI_FALSE;
571 static jobject audioBuffer =
NULL;
572 static void* audioBufferPinned =
NULL;
573 static jboolean captureBuffer16Bit = JNI_FALSE;
574 static jobject captureBuffer =
NULL;
578 jboolean audioBufferStereo;
579 int audioBufferFrames;
580 jobject jbufobj =
NULL;
586 LOGE(
"callback_handler: failed to attach current thread");
590 audioBufferStereo = channelCount > 1;
593 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"SDL audio: opening device for capture");
594 captureBuffer16Bit = is16Bit;
595 if ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureOpen, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
597 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"SDL audio: error on AudioRecord initialization!");
601 __android_log_print(ANDROID_LOG_VERBOSE,
"SDL",
"SDL audio: opening device for output");
602 audioBuffer16Bit = is16Bit;
603 if ((*env)->CallStaticIntMethod(env, mActivityClass, midAudioOpen, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
605 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"SDL audio: error on AudioTrack initialization!");
614 jshortArray audioBufferLocal = (*env)->NewShortArray(env, desiredBufferFrames * (audioBufferStereo ? 2 : 1));
615 if (audioBufferLocal) {
616 jbufobj = (*env)->NewGlobalRef(env, audioBufferLocal);
617 (*env)->DeleteLocalRef(env, audioBufferLocal);
621 jbyteArray audioBufferLocal = (*env)->NewByteArray(env, desiredBufferFrames * (audioBufferStereo ? 2 : 1));
622 if (audioBufferLocal) {
623 jbufobj = (*env)->NewGlobalRef(env, audioBufferLocal);
624 (*env)->DeleteLocalRef(env, audioBufferLocal);
628 if (jbufobj ==
NULL) {
629 __android_log_print(ANDROID_LOG_WARN,
"SDL",
"SDL audio: could not allocate an audio buffer!");
634 captureBuffer = jbufobj;
636 audioBuffer = jbufobj;
643 audioBufferPinned = (*env)->GetShortArrayElements(env, (jshortArray)audioBuffer, &isCopy);
645 audioBufferFrames = (*env)->GetArrayLength(env, (jshortArray)audioBuffer);
648 audioBufferPinned = (*env)->GetByteArrayElements(env, (jbyteArray)audioBuffer, &isCopy);
650 audioBufferFrames = (*env)->GetArrayLength(env, (jbyteArray)audioBuffer);
653 if (audioBufferStereo) {
654 audioBufferFrames /= 2;
657 return audioBufferFrames;
662 return audioBufferPinned;
669 if (audioBuffer16Bit) {
670 (*mAudioEnv)->ReleaseShortArrayElements(mAudioEnv, (jshortArray)audioBuffer, (jshort *)audioBufferPinned, JNI_COMMIT);
671 (*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mActivityClass, midAudioWriteShortBuffer, (jshortArray)audioBuffer);
673 (*mAudioEnv)->ReleaseByteArrayElements(mAudioEnv, (jbyteArray)audioBuffer, (jbyte *)audioBufferPinned, JNI_COMMIT);
674 (*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mActivityClass, midAudioWriteByteBuffer, (jbyteArray)audioBuffer);
683 jboolean isCopy = JNI_FALSE;
686 if (captureBuffer16Bit) {
687 SDL_assert((*env)->GetArrayLength(env, (jshortArray)captureBuffer) == (buflen / 2));
688 br = (*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_TRUE);
690 jshort *
ptr = (*env)->GetShortArrayElements(env, (jshortArray)captureBuffer, &isCopy);
693 (*env)->ReleaseShortArrayElements(env, (jshortArray)captureBuffer, (jshort *)ptr, JNI_ABORT);
696 SDL_assert((*env)->GetArrayLength(env, (jshortArray)captureBuffer) == buflen);
697 br = (*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_TRUE);
699 jbyte *ptr = (*env)->GetByteArrayElements(env, (jbyteArray)captureBuffer, &isCopy);
701 (*env)->ReleaseByteArrayElements(env, (jbyteArray)captureBuffer, (jbyte *)ptr, JNI_ABORT);
712 if (captureBuffer16Bit) {
713 const jint
len = (*env)->GetArrayLength(env, (jshortArray)captureBuffer);
714 while ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_FALSE) ==
len) { }
716 const jint len = (*env)->GetArrayLength(env, (jbyteArray)captureBuffer);
717 while ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_FALSE) ==
len) { }
720 if (captureBuffer16Bit) {
721 (*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_FALSE);
723 (*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_FALSE);
733 (*env)->CallStaticVoidMethod(env, mActivityClass, midCaptureClose);
735 (*env)->DeleteGlobalRef(env, captureBuffer);
736 captureBuffer =
NULL;
739 (*env)->CallStaticVoidMethod(env, mActivityClass, midAudioClose);
741 (*env)->DeleteGlobalRef(env, audioBuffer);
743 audioBufferPinned =
NULL;
753 jthrowable exception;
757 exception = (*mEnv)->ExceptionOccurred(mEnv);
758 if (exception !=
NULL) {
762 (*mEnv)->ExceptionClear(mEnv);
765 jclass exceptionClass = (*mEnv)->GetObjectClass(mEnv, exception);
766 jclass classClass = (*mEnv)->FindClass(mEnv,
"java/lang/Class");
767 jstring exceptionName;
768 const char* exceptionNameUTF8;
769 jstring exceptionMessage;
771 mid = (*mEnv)->GetMethodID(mEnv, classClass,
"getName",
"()Ljava/lang/String;");
772 exceptionName = (jstring)(*mEnv)->CallObjectMethod(mEnv, exceptionClass, mid);
773 exceptionNameUTF8 = (*mEnv)->GetStringUTFChars(mEnv, exceptionName, 0);
775 mid = (*mEnv)->GetMethodID(mEnv, exceptionClass,
"getMessage",
"()Ljava/lang/String;");
776 exceptionMessage = (jstring)(*mEnv)->CallObjectMethod(mEnv, exception, mid);
778 if (exceptionMessage !=
NULL) {
779 const char* exceptionMessageUTF8 = (*mEnv)->GetStringUTFChars(mEnv, exceptionMessage, 0);
780 SDL_SetError(
"%s: %s", exceptionNameUTF8, exceptionMessageUTF8);
781 (*mEnv)->ReleaseStringUTFChars(mEnv, exceptionMessage, exceptionMessageUTF8);
786 (*mEnv)->ReleaseStringUTFChars(mEnv, exceptionName, exceptionNameUTF8);
795 static int Internal_Android_JNI_FileOpen(
SDL_RWops* ctx)
797 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
803 jobject assetManager;
806 jobject readableByteChannel;
807 jstring fileNameJString;
813 if (!LocalReferenceHolder_Init(&refs, mEnv)) {
817 fileNameJString = (jstring)ctx->
hidden.androidio.fileNameRef;
818 ctx->
hidden.androidio.position = 0;
821 mid = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
822 "getContext",
"()Landroid/content/Context;");
823 context = (*mEnv)->CallStaticObjectMethod(mEnv, mActivityClass, mid);
827 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, context),
828 "getAssets",
"()Landroid/content/res/AssetManager;");
829 assetManager = (*mEnv)->CallObjectMethod(mEnv, context, mid);
834 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, assetManager),
"openFd",
"(Ljava/lang/String;)Landroid/content/res/AssetFileDescriptor;");
835 inputStream = (*mEnv)->CallObjectMethod(mEnv, assetManager, mid, fileNameJString);
836 if (Android_JNI_ExceptionOccurred(
SDL_TRUE)) {
840 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
"getStartOffset",
"()J");
841 ctx->
hidden.androidio.offset = (*mEnv)->CallLongMethod(mEnv, inputStream, mid);
842 if (Android_JNI_ExceptionOccurred(
SDL_TRUE)) {
846 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
"getDeclaredLength",
"()J");
847 ctx->
hidden.androidio.
size = (*mEnv)->CallLongMethod(mEnv, inputStream, mid);
848 if (Android_JNI_ExceptionOccurred(
SDL_TRUE)) {
852 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
"getFileDescriptor",
"()Ljava/io/FileDescriptor;");
853 fd = (*mEnv)->CallObjectMethod(mEnv, inputStream, mid);
854 fdCls = (*mEnv)->GetObjectClass(mEnv, fd);
855 descriptor = (*mEnv)->GetFieldID(mEnv, fdCls,
"descriptor",
"I");
856 ctx->
hidden.androidio.fd = (*mEnv)->GetIntField(mEnv, fd, descriptor);
857 ctx->
hidden.androidio.assetFileDescriptorRef = (*mEnv)->NewGlobalRef(mEnv, inputStream);
860 lseek(ctx->
hidden.androidio.fd, (off_t)ctx->
hidden.androidio.offset, SEEK_SET);
868 ctx->
hidden.androidio.assetFileDescriptorRef =
NULL;
871 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, assetManager),
872 "open",
"(Ljava/lang/String;I)Ljava/io/InputStream;");
873 inputStream = (*mEnv)->CallObjectMethod(mEnv, assetManager, mid, fileNameJString, 1 );
874 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
876 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, context),
877 "openAPKExpansionInputStream",
"(Ljava/lang/String;)Ljava/io/InputStream;");
879 SDL_SetError(
"No openAPKExpansionInputStream() in Java class");
882 inputStream = (*mEnv)->CallObjectMethod(mEnv, context, mid, fileNameJString);
887 if (Android_JNI_ExceptionOccurred(
SDL_FALSE) || !inputStream) {
892 ctx->
hidden.androidio.inputStreamRef = (*mEnv)->NewGlobalRef(mEnv, inputStream);
902 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
904 ctx->
hidden.androidio.
size = (long)(*mEnv)->CallIntMethod(mEnv, inputStream, mid);
905 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
910 channels = (*mEnv)->FindClass(mEnv,
"java/nio/channels/Channels");
911 mid = (*mEnv)->GetStaticMethodID(mEnv, channels,
913 "(Ljava/io/InputStream;)Ljava/nio/channels/ReadableByteChannel;");
914 readableByteChannel = (*mEnv)->CallStaticObjectMethod(
915 mEnv, channels, mid, inputStream);
916 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
920 ctx->
hidden.androidio.readableByteChannelRef =
921 (*mEnv)->NewGlobalRef(mEnv, readableByteChannel);
924 mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, readableByteChannel),
925 "read",
"(Ljava/nio/ByteBuffer;)I");
926 ctx->
hidden.androidio.readMethod = mid;
933 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.fileNameRef);
935 if(ctx->
hidden.androidio.inputStreamRef !=
NULL) {
936 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.inputStreamRef);
939 if(ctx->
hidden.androidio.readableByteChannelRef !=
NULL) {
940 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.readableByteChannelRef);
943 if(ctx->
hidden.androidio.assetFileDescriptorRef !=
NULL) {
944 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.assetFileDescriptorRef);
949 LocalReferenceHolder_Cleanup(&refs);
954 const char* fileName,
const char*
mode)
956 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
959 jstring fileNameJString;
961 if (!LocalReferenceHolder_Init(&refs, mEnv)) {
962 LocalReferenceHolder_Cleanup(&refs);
967 LocalReferenceHolder_Cleanup(&refs);
971 fileNameJString = (*mEnv)->NewStringUTF(mEnv, fileName);
972 ctx->
hidden.androidio.fileNameRef = (*mEnv)->NewGlobalRef(mEnv, fileNameJString);
974 ctx->
hidden.androidio.readableByteChannelRef =
NULL;
976 ctx->
hidden.androidio.assetFileDescriptorRef =
NULL;
978 retval = Internal_Android_JNI_FileOpen(ctx);
979 LocalReferenceHolder_Cleanup(&refs);
984 size_t size,
size_t maxnum)
986 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
988 if (ctx->
hidden.androidio.assetFileDescriptorRef) {
989 size_t bytesMax = size * maxnum;
994 result = read(ctx->
hidden.androidio.fd, buffer, bytesMax );
997 LocalReferenceHolder_Cleanup(&refs);
998 return result /
size;
1000 LocalReferenceHolder_Cleanup(&refs);
1003 jlong bytesRemaining = (jlong) (size * maxnum);
1004 jlong bytesMax = (jlong) (ctx->
hidden.androidio.
size - ctx->
hidden.androidio.position);
1007 jobject readableByteChannel;
1008 jmethodID readMethod;
1012 if (bytesRemaining > bytesMax) bytesRemaining = bytesMax;
1015 if (!LocalReferenceHolder_Init(&refs, mEnv)) {
1016 LocalReferenceHolder_Cleanup(&refs);
1020 readableByteChannel = (jobject)ctx->
hidden.androidio.readableByteChannelRef;
1021 readMethod = (jmethodID)ctx->
hidden.androidio.readMethod;
1022 byteBuffer = (*mEnv)->NewDirectByteBuffer(mEnv, buffer, bytesRemaining);
1024 while (bytesRemaining > 0) {
1026 int result = (*mEnv)->CallIntMethod(mEnv, readableByteChannel, readMethod, byteBuffer);
1028 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
1029 LocalReferenceHolder_Cleanup(&refs);
1037 bytesRemaining -=
result;
1041 LocalReferenceHolder_Cleanup(&refs);
1042 return bytesRead /
size;
1047 size_t size,
size_t num)
1049 SDL_SetError(
"Cannot write to Android package filesystem");
1055 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1060 if (!LocalReferenceHolder_Init(&refs, mEnv)) {
1061 LocalReferenceHolder_Cleanup(&refs);
1062 return SDL_SetError(
"Failed to allocate enough JVM local references");
1067 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.fileNameRef);
1070 if (ctx->
hidden.androidio.assetFileDescriptorRef) {
1071 jobject inputStream = (jobject)ctx->
hidden.androidio.assetFileDescriptorRef;
1072 jmethodID mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
1074 (*mEnv)->CallVoidMethod(mEnv, inputStream, mid);
1075 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.assetFileDescriptorRef);
1076 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
1081 jobject inputStream = (jobject)ctx->
hidden.androidio.inputStreamRef;
1084 jmethodID mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
1086 (*mEnv)->CallVoidMethod(mEnv, inputStream, mid);
1087 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.inputStreamRef);
1088 (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->
hidden.androidio.readableByteChannelRef);
1089 if (Android_JNI_ExceptionOccurred(
SDL_FALSE)) {
1099 LocalReferenceHolder_Cleanup(&refs);
1111 if (ctx->
hidden.androidio.assetFileDescriptorRef) {
1116 offset += ctx->
hidden.androidio.offset;
1119 offset += ctx->
hidden.androidio.position;
1121 offset += ctx->
hidden.androidio.offset;
1131 ret = lseek(ctx->
hidden.androidio.fd, (off_t)offset, SEEK_SET);
1132 if (ret == -1)
return -1;
1133 ctx->
hidden.androidio.position = ret - ctx->
hidden.androidio.offset;
1153 if (newPosition < 0) {
1156 if (newPosition > ctx->
hidden.androidio.
size) {
1160 movement = newPosition - ctx->
hidden.androidio.position;
1162 unsigned char buffer[4096];
1165 while (movement > 0) {
1168 if (amount > movement) {
1180 }
else if (movement < 0) {
1183 Internal_Android_JNI_FileClose(ctx,
SDL_FALSE);
1184 Internal_Android_JNI_FileOpen(ctx);
1189 return ctx->
hidden.androidio.position;
1195 return Internal_Android_JNI_FileClose(ctx,
SDL_TRUE);
1199 static jobject Android_JNI_GetSystemServiceObject(
const char* name)
1201 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1203 jobject retval =
NULL;
1209 if (!LocalReferenceHolder_Init(&refs, env)) {
1210 LocalReferenceHolder_Cleanup(&refs);
1214 service = (*env)->NewStringUTF(env, name);
1216 mid = (*env)->GetStaticMethodID(env, mActivityClass,
"getContext",
"()Landroid/content/Context;");
1217 context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
1219 mid = (*env)->GetMethodID(env, mActivityClass,
"getSystemServiceFromUiThread",
"(Ljava/lang/String;)Ljava/lang/Object;");
1220 manager = (*env)->CallObjectMethod(env, context, mid, service);
1222 (*env)->DeleteLocalRef(env, service);
1224 retval = manager ? (*env)->NewGlobalRef(env, manager) :
NULL;
1225 LocalReferenceHolder_Cleanup(&refs);
1229 #define SETUP_CLIPBOARD(error) \ 1230 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__); \ 1231 JNIEnv* env = Android_JNI_GetEnv(); \ 1232 jobject clipboard; \ 1233 if (!LocalReferenceHolder_Init(&refs, env)) { \ 1234 LocalReferenceHolder_Cleanup(&refs); \ 1237 clipboard = Android_JNI_GetSystemServiceObject("clipboard"); \ 1239 LocalReferenceHolder_Cleanup(&refs); \ 1243 #define CLEANUP_CLIPBOARD() \ 1244 LocalReferenceHolder_Cleanup(&refs); 1253 jmethodID mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard),
"setText",
"(Ljava/lang/CharSequence;)V");
1254 jstring
string = (*env)->NewStringUTF(env, text);
1255 (*env)->CallVoidMethod(env, clipboard, mid,
string);
1256 (*env)->DeleteGlobalRef(env, clipboard);
1257 (*env)->DeleteLocalRef(env,
string);
1259 CLEANUP_CLIPBOARD();
1271 jmethodID mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard),
"getText",
"()Ljava/lang/CharSequence;");
1272 jobject sequence = (*env)->CallObjectMethod(env, clipboard, mid);
1273 (*env)->DeleteGlobalRef(env, clipboard);
1277 mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, sequence),
"toString",
"()Ljava/lang/String;");
1278 string = (jstring)((*env)->CallObjectMethod(env, sequence, mid));
1279 utf = (*env)->GetStringUTFChars(env,
string, 0);
1282 (*env)->ReleaseStringUTFChars(env,
string, utf);
1284 CLEANUP_CLIPBOARD();
1290 CLEANUP_CLIPBOARD();
1302 mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard),
"hasText",
"()Z");
1303 has = (*env)->CallBooleanMethod(env, clipboard, mid);
1304 (*env)->DeleteGlobalRef(env, clipboard);
1306 CLEANUP_CLIPBOARD();
1318 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1330 if (!LocalReferenceHolder_Init(&refs, env)) {
1331 LocalReferenceHolder_Cleanup(&refs);
1336 mid = (*env)->GetStaticMethodID(env, mActivityClass,
"getContext",
"()Landroid/content/Context;");
1337 context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
1339 action = (*env)->NewStringUTF(env,
"android.intent.action.BATTERY_CHANGED");
1341 cls = (*env)->FindClass(env,
"android/content/IntentFilter");
1343 mid = (*env)->GetMethodID(env, cls,
"<init>",
"(Ljava/lang/String;)V");
1344 filter = (*env)->NewObject(env, cls, mid, action);
1346 (*env)->DeleteLocalRef(env, action);
1348 mid = (*env)->GetMethodID(env, mActivityClass,
"registerReceiver",
"(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Intent;");
1349 intent = (*env)->CallObjectMethod(env, context, mid,
NULL, filter);
1351 (*env)->DeleteLocalRef(env, filter);
1353 cls = (*env)->GetObjectClass(env, intent);
1355 imid = (*env)->GetMethodID(env, cls,
"getIntExtra",
"(Ljava/lang/String;I)I");
1358 #define GET_INT_EXTRA(var, key) \ 1360 iname = (*env)->NewStringUTF(env, key); \ 1361 var = (*env)->CallIntMethod(env, intent, imid, iname, -1); \ 1362 (*env)->DeleteLocalRef(env, iname); 1364 bmid = (*env)->GetMethodID(env, cls,
"getBooleanExtra",
"(Ljava/lang/String;Z)Z");
1367 #define GET_BOOL_EXTRA(var, key) \ 1369 bname = (*env)->NewStringUTF(env, key); \ 1370 var = (*env)->CallBooleanMethod(env, intent, bmid, bname, JNI_FALSE); \ 1371 (*env)->DeleteLocalRef(env, bname); 1375 GET_INT_EXTRA(plug,
"plugged")
1377 LocalReferenceHolder_Cleanup(&refs);
1382 *plugged = (0 < plug) ? 1 : 0;
1387 GET_INT_EXTRA(status,
"status")
1389 LocalReferenceHolder_Cleanup(&refs);
1393 *charged = (status == 5) ? 1 : 0;
1397 GET_BOOL_EXTRA(present,
"present")
1398 *battery = present ? 1 : 0;
1411 GET_INT_EXTRA(level_temp,
"level")
1416 GET_INT_EXTRA(scale_temp,
"scale")
1420 if ((level == -1) || (scale == -1)) {
1421 LocalReferenceHolder_Cleanup(&refs);
1424 *percent = level * 100 /
scale;
1427 (*env)->DeleteLocalRef(env, intent);
1429 LocalReferenceHolder_Cleanup(&refs);
1437 jmethodID mid = (*env)->GetStaticMethodID(env, mActivityClass,
"inputGetInputDeviceIds",
"(I)[I");
1438 jintArray
array = (jintArray) (*env)->CallStaticObjectMethod(env, mActivityClass, mid, sources);
1442 number = (int) (*env)->GetArrayLength(env, array);
1444 jint* elements = (*env)->GetIntArrayElements(env, array,
NULL);
1448 for (i = 0; i < number; ++
i) {
1449 (*ids)[
i] = elements[
i];
1451 (*env)->ReleaseIntArrayElements(env, array, elements, JNI_ABORT);
1454 (*env)->DeleteLocalRef(env, array);
1462 (*env)->CallStaticVoidMethod(env, mActivityClass, midPollInputDevices);
1466 #define COMMAND_SET_KEEP_SCREEN_ON 5 1477 mid = (*env)->GetStaticMethodID(env, mActivityClass,
"sendMessage",
"(II)Z");
1481 success = (*env)->CallStaticBooleanMethod(env, mActivityClass, mid, command, param);
1482 return success ? 0 : -1;
1498 mid = (*env)->GetStaticMethodID(env, mActivityClass,
"showTextInput",
"(IIII)Z");
1502 (*env)->CallStaticBooleanMethod(env, mActivityClass, mid,
1512 const int COMMAND_TEXTEDIT_HIDE = 3;
1516 int Android_JNI_ShowMessageBox(
const SDL_MessageBoxData *messageboxdata,
int *buttonid)
1524 jintArray button_flags;
1525 jintArray button_ids;
1526 jobjectArray button_texts;
1536 clazz = (*env)->FindClass(env,
"java/lang/String");
1538 title = (*env)->NewStringUTF(env, messageboxdata->
title);
1539 message = (*env)->NewStringUTF(env, messageboxdata->
message);
1541 button_flags = (*env)->NewIntArray(env, messageboxdata->
numbuttons);
1542 button_ids = (*env)->NewIntArray(env, messageboxdata->
numbuttons);
1543 button_texts = (*env)->NewObjectArray(env, messageboxdata->
numbuttons,
1545 for (i = 0; i < messageboxdata->
numbuttons; ++
i) {
1547 (*env)->SetIntArrayRegion(env, button_flags, i, 1, &temp);
1549 (*env)->SetIntArrayRegion(env, button_ids, i, 1, &temp);
1550 text = (*env)->NewStringUTF(env, messageboxdata->
buttons[i].
text);
1551 (*env)->SetObjectArrayElement(env, button_texts, i, text);
1552 (*env)->DeleteLocalRef(env, text);
1558 temp = (0xFF << 24) |
1562 (*env)->SetIntArrayRegion(env, colors, i, 1, &temp);
1568 (*env)->DeleteLocalRef(env, clazz);
1572 mid = (*env)->GetStaticMethodID(env, mActivityClass,
"getContext",
"()Landroid/content/Context;");
1574 context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
1576 clazz = (*env)->GetObjectClass(env, context);
1578 mid = (*env)->GetMethodID(env, clazz,
1579 "messageboxShowMessageBox",
"(ILjava/lang/String;Ljava/lang/String;[I[I[Ljava/lang/String;[I)I");
1580 *buttonid = (*env)->CallIntMethod(env, context, mid,
1581 messageboxdata->
flags,
1589 (*env)->DeleteLocalRef(env, context);
1590 (*env)->DeleteLocalRef(env, clazz);
1594 (*env)->DeleteLocalRef(env, title);
1595 (*env)->DeleteLocalRef(env, message);
1596 (*env)->DeleteLocalRef(env, button_flags);
1597 (*env)->DeleteLocalRef(env, button_ids);
1598 (*env)->DeleteLocalRef(env, button_texts);
1599 (*env)->DeleteLocalRef(env, colors);
1607 // Functions exposed to SDL applications in SDL_system.h
1630 mid = (*env)->GetStaticMethodID(env, mActivityClass,
1631 "getContext",
"()Landroid/content/Context;");
1632 return (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
1637 static char *s_AndroidInternalFilesPath =
NULL;
1639 if (!s_AndroidInternalFilesPath) {
1640 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1648 if (!LocalReferenceHolder_Init(&refs, env)) {
1649 LocalReferenceHolder_Cleanup(&refs);
1654 mid = (*env)->GetStaticMethodID(env, mActivityClass,
1655 "getContext",
"()Landroid/content/Context;");
1656 context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
1659 mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context),
1660 "getFilesDir",
"()Ljava/io/File;");
1661 fileObject = (*env)->CallObjectMethod(env, context, mid);
1664 LocalReferenceHolder_Cleanup(&refs);
1669 mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, fileObject),
1670 "getAbsolutePath",
"()Ljava/lang/String;");
1671 pathString = (jstring)(*env)->CallObjectMethod(env, fileObject, mid);
1673 path = (*env)->GetStringUTFChars(env, pathString,
NULL);
1674 s_AndroidInternalFilesPath =
SDL_strdup(path);
1675 (*env)->ReleaseStringUTFChars(env, pathString, path);
1677 LocalReferenceHolder_Cleanup(&refs);
1679 return s_AndroidInternalFilesPath;
1684 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1687 jstring stateString;
1692 if (!LocalReferenceHolder_Init(&refs, env)) {
1693 LocalReferenceHolder_Cleanup(&refs);
1697 cls = (*env)->FindClass(env,
"android/os/Environment");
1698 mid = (*env)->GetStaticMethodID(env, cls,
1699 "getExternalStorageState",
"()Ljava/lang/String;");
1700 stateString = (jstring)(*env)->CallStaticObjectMethod(env, cls, mid);
1702 state = (*env)->GetStringUTFChars(env, stateString,
NULL);
1705 __android_log_print(ANDROID_LOG_INFO,
"SDL",
"external storage state: %s", state);
1708 stateFlags = SDL_ANDROID_EXTERNAL_STORAGE_READ |
1709 SDL_ANDROID_EXTERNAL_STORAGE_WRITE;
1710 }
else if (
SDL_strcmp(state,
"mounted_ro") == 0) {
1711 stateFlags = SDL_ANDROID_EXTERNAL_STORAGE_READ;
1715 (*env)->ReleaseStringUTFChars(env, stateString, state);
1717 LocalReferenceHolder_Cleanup(&refs);
1723 static char *s_AndroidExternalFilesPath =
NULL;
1725 if (!s_AndroidExternalFilesPath) {
1726 struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1734 if (!LocalReferenceHolder_Init(&refs, env)) {
1735 LocalReferenceHolder_Cleanup(&refs);
1740 mid = (*env)->GetStaticMethodID(env, mActivityClass,
1741 "getContext",
"()Landroid/content/Context;");
1742 context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
1745 mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context),
1746 "getExternalFilesDir",
"(Ljava/lang/String;)Ljava/io/File;");
1747 fileObject = (*env)->CallObjectMethod(env, context, mid,
NULL);
1750 LocalReferenceHolder_Cleanup(&refs);
1755 mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, fileObject),
1756 "getAbsolutePath",
"()Ljava/lang/String;");
1757 pathString = (jstring)(*env)->CallObjectMethod(env, fileObject, mid);
1759 path = (*env)->GetStringUTFChars(env, pathString,
NULL);
1760 s_AndroidExternalFilesPath =
SDL_strdup(path);
1761 (*env)->ReleaseStringUTFChars(env, pathString, path);
1763 LocalReferenceHolder_Cleanup(&refs);
1765 return s_AndroidExternalFilesPath;
1770 return mActivityClass;
int Android_JNI_CaptureAudioBuffer(void *buffer, int buflen)
void Android_SetScreenResolution(int width, int height, Uint32 format, float rate)
GLenum GLenum GLenum GLenum GLenum scale
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
int Android_JNI_FileClose(SDL_RWops *ctx)
int Android_OnKeyUp(int keycode)
int Android_JNI_SendMessage(int command, int param)
void Android_JNI_ShowTextInput(SDL_Rect *inputRect)
GLint GLint GLsizei width
void Android_JNI_WriteAudioBuffer(void)
GLsizei const GLchar *const * string
GLuint GLsizei const GLchar * message
GLint GLint GLint GLint GLint x
SDL_bool Android_JNI_GetAccelerometerValues(float values[3])
int SDL_SendDropFile(SDL_Window *window, const char *file)
#define SDL_AndroidGetExternalStoragePath
set set set set set set set set set set set set set set set set set set set set *set set set macro pixldst op &r &cond WK op &r &cond WK op &r &cond WK else op &m &cond &ia op &r &cond WK else op &m &cond &ia elseif elseif else error unsupported base if elseif elseif else error unsupported unaligned pixldst unaligned endm macro pixst base base else pixldst base endif endm macro PF ptr
void Android_JNI_SetActivityTitle(const char *title)
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d ®2 endm macro vzip8 reg2 vzip d d ®2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld [DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp local skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
char * Android_JNI_GetClipboardText(void)
int Android_OnKeyDown(int keycode)
void Android_OnTouch(int touch_device_id_in, int pointer_finger_id_in, int action, float x, float y, float p)
GLuint const GLchar * name
int SDL_SendWindowEvent(SDL_Window *window, Uint8 windowevent, int data1, int data2)
GLint GLint GLsizei GLsizei height
int Android_JNI_FileOpen(SDL_RWops *ctx, const char *fileName, const char *mode)
int SDL_SendDropComplete(SDL_Window *window)
SDL_sem * Android_PauseSem
int Android_JNI_OpenAudioDevice(int iscapture, int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames)
static SDL_VideoDevice * _this
int Android_JNI_SetupThread(void)
void Android_JNI_FlushCapturedAudio(void)
#define SDL_StopTextInput
GLenum GLsizei const void * pathString
GLint GLint GLint GLint GLint GLint y
GLsizei const GLfloat * value
int SDL_SendKeyboardText(const char *text)
void Android_JNI_CloseAudioDevice(const int iscapture)
SDL_bool Android_JNI_HasClipboardText(void)
int Android_JNI_GetPowerInfo(int *plugged, int *charged, int *battery, int *seconds, int *percent)
size_t Android_JNI_FileWrite(SDL_RWops *ctx, const void *buffer, size_t size, size_t num)
SDL_Window * Android_Window
void * Android_JNI_GetAudioBuffer(void)
GLenum GLsizei GLsizei GLint * values
void Android_JNI_SuspendScreenSaver(SDL_bool suspend)
const SDL_MessageBoxButtonData * buttons
MessageBox structure containing title, text, window, etc.
void Android_OnMouse(int button, int action, float x, float y)
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Sint64(* size)(struct SDL_RWops *context)
#define SDL_assert(condition)
ANativeWindow * Android_JNI_GetNativeWindow(void)
jclass Android_JNI_GetActivityClass(void)
union SDL_RWops::@10 hidden
static char text[MAX_TEXT_LENGTH]
void Android_JNI_HideTextInput(void)
#define SDL_AndroidGetActivity
SDL_sem * Android_ResumeSem
size_t Android_JNI_FileRead(SDL_RWops *ctx, void *buffer, size_t size, size_t maxnum)
int Android_JNI_SetClipboardText(const char *text)
#define SDL_AndroidGetExternalStorageState
SDL_VideoDevice * SDL_GetVideoDevice(void)
GLsizei const GLchar *const * path
int SDL_SendAppEvent(SDL_EventType eventType)
void Android_JNI_PollInputDevices(void)
int64_t Sint64
A signed 64-bit integer type.
#define SDL_AndroidGetJNIEnv
ANativeWindow * native_window
int Android_JNI_GetTouchDeviceIds(int **ids)
const SDL_MessageBoxColorScheme * colorScheme
SDL_MessageBoxColor colors[SDL_MESSAGEBOX_COLOR_MAX]
set set set set set set set set set set set set set set set set set set set set *set set set macro pixldst op &r &cond WK op &r &cond WK op &r &cond WK else op &m &cond &ia op &r &cond WK else op &m &cond &ia elseif elseif else error unsupported base if elseif elseif else error unsupported unaligned pixldst unaligned endm macro pixst base base else pixldst base endif endm macro PF base if bpp PF set rept prefetch_distance PF set OFFSET endr endif endm macro preload_leading_step2 base if bpp ifc DST PF PF else if bpp lsl PF PF lsl PF PF lsl PF PF PF else PF lsl PF lsl PF lsl PF endif SIZE macro preload_middle scratch_holds_offset if bpp if else PF PF endif endif endif endm macro preload_trailing base if bpp if bpp *pix_per_block PF PF lsl PF PF PF PF PF else PF lsl PF lsl PF PF PF PF PF base if bpp if narrow_case &&bpp<=dst_w_bpp) PF bic, WK0, base, #31 PF pld, [WK0] PF add, WK1, base, X, LSL #bpp_shift PF sub, WK1, WK1, #1 PF bic, WK1, WK1, #31 PF cmp, WK1, WK0 PF beq, 90f PF pld, [WK1]90:.else PF bic, WK0, base, #31 PF pld, [WK0] PF add, WK1, base, X, lsl #bpp_shift PF sub, WK1, WK1, #1 PF bic, WK1, WK1, #31 PF cmp, WK1, WK0 PF beq, 92f91:PF add, WK0, WK0, #32 PF cmp, WK0, WK1 PF pld, [WK0] PF bne, 91b92:.endif .endif.endm.macro conditional_process1_helper cond, process_head, process_tail, numbytes, firstreg, unaligned_src, unaligned_mask, decrementx process_head cond, numbytes, firstreg, unaligned_src, unaligned_mask, 0 .if decrementx sub &cond X, X, #8 *numbytes/dst_w_bpp .endif process_tail cond, numbytes, firstreg .if !((flags) &FLAG_PROCESS_DOES_STORE) pixst cond, numbytes, firstreg, DST .endif.endm.macro conditional_process1 cond, process_head, process_tail, numbytes, firstreg, unaligned_src, unaligned_mask, decrementx .if(flags) &FLAG_BRANCH_OVER .ifc cond, mi bpl 100f .endif .ifc cond, cs bcc 100f .endif .ifc cond, ne beq 100f .endif conditional_process1_helper, process_head, process_tail, numbytes, firstreg, unaligned_src, unaligned_mask, decrementx100:.else conditional_process1_helper cond, process_head, process_tail, numbytes, firstreg, unaligned_src, unaligned_mask, decrementx .endif.endm.macro conditional_process2 test, cond1, cond2, process_head, process_tail, numbytes1, numbytes2, firstreg1, firstreg2, unaligned_src, unaligned_mask, decrementx .if(flags) &(FLAG_DST_READWRITE|FLAG_BRANCH_OVER|FLAG_PROCESS_CORRUPTS_PSR|FLAG_PROCESS_DOES_STORE) test conditional_process1 cond1, process_head, process_tail, numbytes1, firstreg1, unaligned_src, unaligned_mask, decrementx .if(flags) &FLAG_PROCESS_CORRUPTS_PSR test .endif conditional_process1 cond2, process_head, process_tail, numbytes2, firstreg2, unaligned_src, unaligned_mask, decrementx .else test process_head cond1, numbytes1, firstreg1, unaligned_src, unaligned_mask, 0 process_head cond2, numbytes2, firstreg2, unaligned_src, unaligned_mask, 0 .if decrementx sub &cond1 X, X, #8 *numbytes1/dst_w_bpp sub &cond2 X, X, #8 *numbytes2/dst_w_bpp .endif process_tail cond1, numbytes1, firstreg1 process_tail cond2, numbytes2, firstreg2 pixst cond1, numbytes1, firstreg1, DST pixst cond2, numbytes2, firstreg2, DST .endif.endm.macro test_bits_1_0_ptr .if(flags) &FLAG_PROCESS_CORRUPTS_WK0 movs SCRATCH, X, lsl #32-1 .else movs SCRATCH, WK0, lsl #32-1 .endif.endm.macro test_bits_3_2_ptr .if(flags) &FLAG_PROCESS_CORRUPTS_WK0 movs SCRATCH, X, lsl #32-3 .else movs SCRATCH, WK0, lsl #32-3 .endif.endm.macro leading_15bytes process_head, process_tail .set DECREMENT_X, 1 .if(flags) &FLAG_PROCESS_CORRUPTS_WK0 .set DECREMENT_X, 0 sub X, X, WK0, lsr #dst_bpp_shift str X, [sp, #LINE_SAVED_REG_COUNT *4] mov X, WK0 .endif .if dst_w_bpp==8 conditional_process2 test_bits_1_0_ptr, mi, cs, process_head, process_tail, 1, 2, 1, 2, 1, 1, DECREMENT_X .elseif dst_w_bpp==16 test_bits_1_0_ptr conditional_process1 cs, process_head, process_tail, 2, 2, 1, 1, DECREMENT_X .endif conditional_process2 test_bits_3_2_ptr, mi, cs, process_head, process_tail, 4, 8, 1, 2, 1, 1, DECREMENT_X .if(flags) &FLAG_PROCESS_CORRUPTS_WK0 ldr X, [sp, #LINE_SAVED_REG_COUNT *4] .endif.endm.macro test_bits_3_2_pix movs SCRATCH, X, lsl #dst_bpp_shift+32-3.endm.macro test_bits_1_0_pix .if dst_w_bpp==8 movs SCRATCH, X, lsl #dst_bpp_shift+32-1 .else movs SCRATCH, X, lsr #1 .endif.endm.macro trailing_15bytes process_head, process_tail, unaligned_src, unaligned_mask conditional_process2 test_bits_3_2_pix, cs, mi, process_head, process_tail, 8, 4, 0, 2, unaligned_src, unaligned_mask, 0 .if dst_w_bpp==16 test_bits_1_0_pix conditional_process1 cs, process_head, process_tail, 2, 0, unaligned_src, unaligned_mask, 0 .elseif dst_w_bpp==8 conditional_process2 test_bits_1_0_pix, cs, mi, process_head, process_tail, 2, 1, 0, 1, unaligned_src, unaligned_mask, 0 .endif.endm.macro wide_case_inner_loop process_head, process_tail, unaligned_src, unaligned_mask, dst_alignment110:.set SUBBLOCK, 0 .rept pix_per_block *dst_w_bpp/128 process_head, 16, 0, unaligned_src, unaligned_mask, 1 .if(src_bpp > 0) &&(mask_bpp==0) &&((flags) &FLAG_PROCESS_PRESERVES_SCRATCH) preload_middle src_bpp, SRC, 1 .elseif(src_bpp==0) &&(mask_bpp > 0) &&((flags) &FLAG_PROCESS_PRESERVES_SCRATCH) preload_middle mask_bpp, MASK, 1 .else preload_middle src_bpp, SRC, 0 preload_middle mask_bpp, MASK, 0 .endif .if(dst_r_bpp > 0) &&((SUBBLOCK % 2)==0) &&(((flags) &FLAG_NO_PRELOAD_DST)==0) PF pld, [DST, #32 *prefetch_distance - dst_alignment] .endif process_tail, 16, 0 .if !((flags) &FLAG_PROCESS_DOES_STORE) pixst, 16, 0, DST .endif .set SUBBLOCK, SUBBLOCK+1 .endr subs X, X, #pix_per_block bhs 110b.endm.macro wide_case_inner_loop_and_trailing_pixels process_head, process_tail, process_inner_loop, exit_label, unaligned_src, unaligned_mask .if dst_r_bpp > tst bne process_inner_loop DST_PRELOAD_BIAS endif preload_trailing SRC preload_trailing MASK DST endif add medium_case_inner_loop_and_trailing_pixels unaligned_mask endm macro medium_case_inner_loop_and_trailing_pixels DST endif subs bhs tst beq exit_label trailing_15bytes unaligned_mask endm macro narrow_case_inner_loop_and_trailing_pixels unaligned_mask tst conditional_process1 trailing_15bytes unaligned_mask endm macro switch_on_alignment action
#define SDL_AndroidGetInternalStoragePath
JNIEnv * Android_JNI_GetEnv(void)
int SDL_SendEditingText(const char *text, int start, int length)
Sint64 Android_JNI_FileSeek(SDL_RWops *ctx, Sint64 offset, int whence)
A rectangle, with the origin at the upper left.
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Sint64 Android_JNI_FileSize(SDL_RWops *ctx)