~ubuntu-branches/ubuntu/vivid/libsdl2/vivid

« back to all changes in this revision

Viewing changes to src/core/android/SDL_android.c

  • Committer: Package Import Robot
  • Author(s): Manuel A. Fernandez Montecelo, Felix Geyer
  • Date: 2013-12-28 12:31:19 UTC
  • mfrom: (1.1.3)
  • Revision ID: package-import@ubuntu.com-20131228123119-e0k27gckmnzskfgb
Tags: 2.0.1+dfsg1-1
* New upstream release (Closes: #728974)
  - Remove patch applied upstream:
    bug-723797-false_positives_in_mouse_wheel_code.patch
* Bump Standards-Version to 3.9.5, no changes needed.

[ Felix Geyer ]
* Import upstream gpg key for uscan to verify the orig tarball.

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
#include "../../video/android/SDL_androidkeyboard.h"
34
34
#include "../../video/android/SDL_androidtouch.h"
35
35
#include "../../video/android/SDL_androidvideo.h"
 
36
#include "../../video/android/SDL_androidwindow.h"
36
37
 
37
38
#include <android/log.h>
38
39
#include <pthread.h>
39
40
#include <sys/types.h>
40
41
#include <unistd.h>
41
42
#define LOG_TAG "SDL_android"
42
 
//#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
43
 
//#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
 
43
/* #define LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) */
 
44
/* #define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) */
44
45
#define LOGI(...) do {} while (false)
45
46
#define LOGE(...) do {} while (false)
46
47
 
47
48
/* Uncomment this to log messages entering and exiting methods in this file */
48
 
//#define DEBUG_JNI
 
49
/* #define DEBUG_JNI */
49
50
 
50
51
static void Android_JNI_ThreadDestroyed(void*);
51
52
 
63
64
static pthread_key_t mThreadKey;
64
65
static JavaVM* mJavaVM;
65
66
 
66
 
// Main activity
 
67
/* Main activity */
67
68
static jclass mActivityClass;
68
69
 
69
 
// method signatures
70
 
static jmethodID midCreateGLContext;
71
 
static jmethodID midDeleteGLContext;
 
70
/* method signatures */
 
71
static jmethodID midGetNativeSurface;
72
72
static jmethodID midFlipBuffers;
73
73
static jmethodID midAudioInit;
74
74
static jmethodID midAudioWriteShortBuffer;
75
75
static jmethodID midAudioWriteByteBuffer;
76
76
static jmethodID midAudioQuit;
77
77
 
78
 
// Accelerometer data storage
 
78
/* Accelerometer data storage */
79
79
static float fLastAccelerometer[3];
80
80
static bool bHasNewData;
81
81
 
83
83
                 Functions called by JNI
84
84
*******************************************************************************/
85
85
 
86
 
// Library init
 
86
/* Library init */
87
87
jint JNI_OnLoad(JavaVM* vm, void* reserved)
88
88
{
89
89
    JNIEnv *env;
107
107
    return JNI_VERSION_1_4;
108
108
}
109
109
 
110
 
// Called before SDL_main() to initialize JNI bindings
 
110
/* Called before SDL_main() to initialize JNI bindings */
111
111
void SDL_Android_Init(JNIEnv* mEnv, jclass cls)
112
112
{
113
113
    __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL_Android_Init()");
116
116
 
117
117
    mActivityClass = (jclass)((*mEnv)->NewGlobalRef(mEnv, cls));
118
118
 
119
 
    midCreateGLContext = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
120
 
                                "createGLContext","(II[I)Z");
121
 
    midDeleteGLContext = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
122
 
                                "deleteGLContext","()V");
 
119
    midGetNativeSurface = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
 
120
                                "getNativeSurface","()Landroid/view/Surface;");
123
121
    midFlipBuffers = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
124
122
                                "flipBuffers","()V");
125
123
    midAudioInit = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
133
131
 
134
132
    bHasNewData = false;
135
133
 
136
 
    if(!midCreateGLContext || !midFlipBuffers || !midAudioInit ||
 
134
    if(!midGetNativeSurface || !midFlipBuffers || !midAudioInit ||
137
135
       !midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioQuit) {
138
136
        __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL: Couldn't locate Java callbacks, check that they're named and typed correctly");
139
137
    }
140
138
    __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL_Android_Init() finished!");
141
139
}
142
140
 
143
 
// Resize
 
141
/* Resize */
144
142
void Java_org_libsdl_app_SDLActivity_onNativeResize(
145
143
                                    JNIEnv* env, jclass jcls,
146
144
                                    jint width, jint height, jint format)
148
146
    Android_SetScreenResolution(width, height, format);
149
147
}
150
148
 
151
 
// Keydown
 
149
 
 
150
/* Surface Created */
 
151
void Java_org_libsdl_app_SDLActivity_onNativeSurfaceChanged(JNIEnv* env, jclass jcls)
 
152
{
 
153
    SDL_WindowData *data;
 
154
    SDL_VideoDevice *_this;
 
155
 
 
156
    if (Android_Window == NULL || Android_Window->driverdata == NULL ) {
 
157
        return;
 
158
    }
 
159
    
 
160
    _this =  SDL_GetVideoDevice();
 
161
    data =  (SDL_WindowData *) Android_Window->driverdata;
 
162
    
 
163
    /* If the surface has been previously destroyed by onNativeSurfaceDestroyed, recreate it here */
 
164
    if (data->egl_surface == EGL_NO_SURFACE) {
 
165
        if(data->native_window) {
 
166
            ANativeWindow_release(data->native_window);
 
167
        }
 
168
        data->native_window = Android_JNI_GetNativeWindow();
 
169
        data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) data->native_window);
 
170
    }
 
171
    
 
172
    /* GL Context handling is done in the event loop because this function is run from the Java thread */
 
173
    
 
174
}
 
175
 
 
176
/* Surface Destroyed */
 
177
void Java_org_libsdl_app_SDLActivity_onNativeSurfaceDestroyed(JNIEnv* env, jclass jcls)
 
178
{
 
179
    /* We have to clear the current context and destroy the egl surface here
 
180
     * Otherwise there's BAD_NATIVE_WINDOW errors coming from eglCreateWindowSurface on resume
 
181
     * Ref: http://stackoverflow.com/questions/8762589/eglcreatewindowsurface-on-ics-and-switching-from-2d-to-3d
 
182
     */
 
183
    SDL_WindowData *data;
 
184
    SDL_VideoDevice *_this;
 
185
    
 
186
    if (Android_Window == NULL || Android_Window->driverdata == NULL ) {
 
187
        return;
 
188
    }
 
189
    
 
190
    _this =  SDL_GetVideoDevice();
 
191
    data = (SDL_WindowData *) Android_Window->driverdata;
 
192
    
 
193
    if (data->egl_surface != EGL_NO_SURFACE) {
 
194
        SDL_EGL_MakeCurrent(_this, NULL, NULL);
 
195
        SDL_EGL_DestroySurface(_this, data->egl_surface);
 
196
        data->egl_surface = EGL_NO_SURFACE;
 
197
    }
 
198
    
 
199
    /* GL Context handling is done in the event loop because this function is run from the Java thread */
 
200
 
 
201
}
 
202
 
 
203
void Java_org_libsdl_app_SDLActivity_nativeFlipBuffers(JNIEnv* env, jclass jcls)
 
204
{
 
205
    SDL_GL_SwapWindow(Android_Window);
 
206
}
 
207
 
 
208
/* Keydown */
152
209
void Java_org_libsdl_app_SDLActivity_onNativeKeyDown(
153
210
                                    JNIEnv* env, jclass jcls, jint keycode)
154
211
{
155
212
    Android_OnKeyDown(keycode);
156
213
}
157
214
 
158
 
// Keyup
 
215
/* Keyup */
159
216
void Java_org_libsdl_app_SDLActivity_onNativeKeyUp(
160
217
                                    JNIEnv* env, jclass jcls, jint keycode)
161
218
{
162
219
    Android_OnKeyUp(keycode);
163
220
}
164
221
 
165
 
// Keyboard Focus Lost
 
222
/* Keyboard Focus Lost */
166
223
void Java_org_libsdl_app_SDLActivity_onNativeKeyboardFocusLost(
167
224
                                    JNIEnv* env, jclass jcls)
168
225
{
171
228
}
172
229
 
173
230
 
174
 
// Touch
 
231
/* Touch */
175
232
void Java_org_libsdl_app_SDLActivity_onNativeTouch(
176
233
                                    JNIEnv* env, jclass jcls,
177
234
                                    jint touch_device_id_in, jint pointer_finger_id_in,
180
237
    Android_OnTouch(touch_device_id_in, pointer_finger_id_in, action, x, y, p);
181
238
}
182
239
 
183
 
// Accelerometer
 
240
/* Accelerometer */
184
241
void Java_org_libsdl_app_SDLActivity_onNativeAccel(
185
242
                                    JNIEnv* env, jclass jcls,
186
243
                                    jfloat x, jfloat y, jfloat z)
191
248
    bHasNewData = true;
192
249
}
193
250
 
194
 
// Low memory
 
251
/* Low memory */
195
252
void Java_org_libsdl_app_SDLActivity_nativeLowMemory(
196
253
                                    JNIEnv* env, jclass cls)
197
254
{
198
255
    SDL_SendAppEvent(SDL_APP_LOWMEMORY);
199
256
}
200
257
 
201
 
// Quit
 
258
/* Quit */
202
259
void Java_org_libsdl_app_SDLActivity_nativeQuit(
203
260
                                    JNIEnv* env, jclass cls)
204
261
{
205
 
    // Inject a SDL_QUIT event
 
262
    /* Inject a SDL_QUIT event */
206
263
    SDL_SendQuit();
207
264
    SDL_SendAppEvent(SDL_APP_TERMINATING);
208
265
}
209
266
 
210
 
// Pause
 
267
/* Pause */
211
268
void Java_org_libsdl_app_SDLActivity_nativePause(
212
269
                                    JNIEnv* env, jclass cls)
213
270
{
223
280
    SDL_SendAppEvent(SDL_APP_DIDENTERBACKGROUND);
224
281
}
225
282
 
226
 
// Resume
 
283
/* Resume */
227
284
void Java_org_libsdl_app_SDLActivity_nativeResume(
228
285
                                    JNIEnv* env, jclass cls)
229
286
{
317
374
    return s_active > 0;    
318
375
}
319
376
 
320
 
 
321
 
SDL_bool Android_JNI_CreateContext(int majorVersion, int minorVersion,
322
 
                                int red, int green, int blue, int alpha,
323
 
                                int buffer, int depth, int stencil,
324
 
                                int buffers, int samples)
325
 
{
326
 
    JNIEnv *env = Android_JNI_GetEnv();
327
 
 
328
 
    jint attribs[] = {
329
 
        EGL_RED_SIZE, red,
330
 
        EGL_GREEN_SIZE, green,
331
 
        EGL_BLUE_SIZE, blue,
332
 
        EGL_ALPHA_SIZE, alpha,
333
 
        EGL_BUFFER_SIZE, buffer,
334
 
        EGL_DEPTH_SIZE, depth,
335
 
        EGL_STENCIL_SIZE, stencil,
336
 
        EGL_SAMPLE_BUFFERS, buffers,
337
 
        EGL_SAMPLES, samples,
338
 
        EGL_RENDERABLE_TYPE, (majorVersion == 1 ? EGL_OPENGL_ES_BIT : EGL_OPENGL_ES2_BIT),
339
 
        EGL_NONE
340
 
    };
341
 
    int len = SDL_arraysize(attribs);
342
 
 
343
 
    jintArray array;
344
 
 
345
 
    array = (*env)->NewIntArray(env, len);
346
 
    (*env)->SetIntArrayRegion(env, array, 0, len, attribs);
347
 
 
348
 
    jboolean success = (*env)->CallStaticBooleanMethod(env, mActivityClass, midCreateGLContext, majorVersion, minorVersion, array);
349
 
 
350
 
    (*env)->DeleteLocalRef(env, array);
351
 
 
352
 
    return success ? SDL_TRUE : SDL_FALSE;
353
 
}
354
 
 
355
 
SDL_bool Android_JNI_DeleteContext(void)
356
 
{
357
 
    /* There's only one context, so no parameter for now */
358
 
    JNIEnv *env = Android_JNI_GetEnv();
359
 
    (*env)->CallStaticVoidMethod(env, mActivityClass, midDeleteGLContext);
360
 
    return SDL_TRUE;
 
377
ANativeWindow* Android_JNI_GetNativeWindow(void)
 
378
{
 
379
    ANativeWindow* anw;
 
380
    jobject s;
 
381
    JNIEnv *env = Android_JNI_GetEnv();
 
382
 
 
383
    s = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetNativeSurface);
 
384
    anw = ANativeWindow_fromSurface(env, s);
 
385
    (*env)->DeleteLocalRef(env, s);
 
386
  
 
387
    return anw;
361
388
}
362
389
 
363
390
void Android_JNI_SwapWindow()
441
468
    return 1;
442
469
}
443
470
 
444
 
//
445
 
// Audio support
446
 
//
 
471
/*
 
472
 * Audio support
 
473
 */
447
474
static jboolean audioBuffer16Bit = JNI_FALSE;
448
475
static jboolean audioBufferStereo = JNI_FALSE;
449
476
static jobject audioBuffer = NULL;
541
568
    }
542
569
}
543
570
 
544
 
// Test for an exception and call SDL_SetError with its detail if one occurs
545
 
// If the parameter silent is truthy then SDL_SetError() will not be called.
 
571
/* Test for an exception and call SDL_SetError with its detail if one occurs */
 
572
/* If the parameter silent is truthy then SDL_SetError() will not be called. */
546
573
static bool Android_JNI_ExceptionOccurred(bool silent)
547
574
{
548
575
    SDL_assert(LocalReferenceHolder_IsActive());
552
579
    if (exception != NULL) {
553
580
        jmethodID mid;
554
581
 
555
 
        // Until this happens most JNI operations have undefined behaviour
 
582
        /* Until this happens most JNI operations have undefined behaviour */
556
583
        (*mEnv)->ExceptionClear(mEnv);
557
584
 
558
585
        if (!silent) {
608
635
    fileNameJString = (jstring)ctx->hidden.androidio.fileNameRef;
609
636
    ctx->hidden.androidio.position = 0;
610
637
 
611
 
    // context = SDLActivity.getContext();
 
638
    /* context = SDLActivity.getContext(); */
612
639
    mid = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
613
640
            "getContext","()Landroid/content/Context;");
614
641
    context = (*mEnv)->CallStaticObjectMethod(mEnv, mActivityClass, mid);
615
642
 
616
643
 
617
 
    // assetManager = context.getAssets();
 
644
    /* assetManager = context.getAssets(); */
618
645
    mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, context),
619
646
            "getAssets", "()Landroid/content/res/AssetManager;");
620
647
    assetManager = (*mEnv)->CallObjectMethod(mEnv, context, mid);
647
674
    ctx->hidden.androidio.fd = (*mEnv)->GetIntField(mEnv, fd, descriptor);
648
675
    ctx->hidden.androidio.assetFileDescriptorRef = (*mEnv)->NewGlobalRef(mEnv, inputStream);
649
676
 
650
 
    // Seek to the correct offset in the file.
 
677
    /* Seek to the correct offset in the file. */
651
678
    lseek(ctx->hidden.androidio.fd, (off_t)ctx->hidden.androidio.offset, SEEK_SET);
652
679
 
653
680
    if (false) {
654
681
fallback:
655
 
        // Disabled log message because of spam on the Nexus 7
656
 
        //__android_log_print(ANDROID_LOG_DEBUG, "SDL", "Falling back to legacy InputStream method for opening file");
 
682
        /* Disabled log message because of spam on the Nexus 7 */
 
683
        /* __android_log_print(ANDROID_LOG_DEBUG, "SDL", "Falling back to legacy InputStream method for opening file"); */
657
684
 
658
685
        /* Try the old method using InputStream */
659
686
        ctx->hidden.androidio.assetFileDescriptorRef = NULL;
660
687
 
661
 
        // inputStream = assetManager.open(<filename>);
 
688
        /* inputStream = assetManager.open(<filename>); */
662
689
        mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, assetManager),
663
690
                "open", "(Ljava/lang/String;I)Ljava/io/InputStream;");
664
 
        inputStream = (*mEnv)->CallObjectMethod(mEnv, assetManager, mid, fileNameJString, 1 /*ACCESS_RANDOM*/);
 
691
        inputStream = (*mEnv)->CallObjectMethod(mEnv, assetManager, mid, fileNameJString, 1 /* ACCESS_RANDOM */);
665
692
        if (Android_JNI_ExceptionOccurred(false)) {
666
693
            goto failure;
667
694
        }
668
695
 
669
696
        ctx->hidden.androidio.inputStreamRef = (*mEnv)->NewGlobalRef(mEnv, inputStream);
670
697
 
671
 
        // Despite all the visible documentation on [Asset]InputStream claiming
672
 
        // that the .available() method is not guaranteed to return the entire file
673
 
        // size, comments in <sdk>/samples/<ver>/ApiDemos/src/com/example/ ...
674
 
        // android/apis/content/ReadAsset.java imply that Android's
675
 
        // AssetInputStream.available() /will/ always return the total file size
676
 
 
677
 
        // size = inputStream.available();
 
698
        /* Despite all the visible documentation on [Asset]InputStream claiming
 
699
         * that the .available() method is not guaranteed to return the entire file
 
700
         * size, comments in <sdk>/samples/<ver>/ApiDemos/src/com/example/ ...
 
701
         * android/apis/content/ReadAsset.java imply that Android's
 
702
         * AssetInputStream.available() /will/ always return the total file size
 
703
        */
 
704
        
 
705
        /* size = inputStream.available(); */
678
706
        mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
679
707
                "available", "()I");
680
708
        ctx->hidden.androidio.size = (long)(*mEnv)->CallIntMethod(mEnv, inputStream, mid);
682
710
            goto failure;
683
711
        }
684
712
 
685
 
        // readableByteChannel = Channels.newChannel(inputStream);
 
713
        /* readableByteChannel = Channels.newChannel(inputStream); */
686
714
        channels = (*mEnv)->FindClass(mEnv, "java/nio/channels/Channels");
687
715
        mid = (*mEnv)->GetStaticMethodID(mEnv, channels,
688
716
                "newChannel",
696
724
        ctx->hidden.androidio.readableByteChannelRef =
697
725
            (*mEnv)->NewGlobalRef(mEnv, readableByteChannel);
698
726
 
699
 
        // Store .read id for reading purposes
 
727
        /* Store .read id for reading purposes */
700
728
        mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, readableByteChannel),
701
729
                "read", "(Ljava/nio/ByteBuffer;)I");
702
730
        ctx->hidden.androidio.readMethod = mid;
762
790
 
763
791
    if (ctx->hidden.androidio.assetFileDescriptorRef) {
764
792
        size_t bytesMax = size * maxnum;
765
 
        if (ctx->hidden.androidio.size != -1 /*UNKNOWN_LENGTH*/ && ctx->hidden.androidio.position + bytesMax > ctx->hidden.androidio.size) {
 
793
        if (ctx->hidden.androidio.size != -1 /* UNKNOWN_LENGTH */ && ctx->hidden.androidio.position + bytesMax > ctx->hidden.androidio.size) {
766
794
            bytesMax = ctx->hidden.androidio.size - ctx->hidden.androidio.position;
767
795
        }
768
796
        size_t result = read(ctx->hidden.androidio.fd, buffer, bytesMax );
792
820
        jobject byteBuffer = (*mEnv)->NewDirectByteBuffer(mEnv, buffer, bytesRemaining);
793
821
 
794
822
        while (bytesRemaining > 0) {
795
 
            // result = readableByteChannel.read(...);
 
823
            /* result = readableByteChannel.read(...); */
796
824
            int result = (*mEnv)->CallIntMethod(mEnv, readableByteChannel, readMethod, byteBuffer);
797
825
 
798
826
            if (Android_JNI_ExceptionOccurred(false)) {
850
878
        else {
851
879
            jobject inputStream = (jobject)ctx->hidden.androidio.inputStreamRef;
852
880
 
853
 
            // inputStream.close();
 
881
            /* inputStream.close(); */
854
882
            jmethodID mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
855
883
                    "close", "()V");
856
884
            (*mEnv)->CallVoidMethod(mEnv, inputStream, mid);
881
909
    if (ctx->hidden.androidio.assetFileDescriptorRef) {
882
910
        switch (whence) {
883
911
            case RW_SEEK_SET:
884
 
                if (ctx->hidden.androidio.size != -1 /*UNKNOWN_LENGTH*/ && offset > ctx->hidden.androidio.size) offset = ctx->hidden.androidio.size;
 
912
                if (ctx->hidden.androidio.size != -1 /* UNKNOWN_LENGTH */ && offset > ctx->hidden.androidio.size) offset = ctx->hidden.androidio.size;
885
913
                offset += ctx->hidden.androidio.offset;
886
914
                break;
887
915
            case RW_SEEK_CUR:
888
916
                offset += ctx->hidden.androidio.position;
889
 
                if (ctx->hidden.androidio.size != -1 /*UNKNOWN_LENGTH*/ && offset > ctx->hidden.androidio.size) offset = ctx->hidden.androidio.size;
 
917
                if (ctx->hidden.androidio.size != -1 /* UNKNOWN_LENGTH */ && offset > ctx->hidden.androidio.size) offset = ctx->hidden.androidio.size;
890
918
                offset += ctx->hidden.androidio.offset;
891
919
                break;
892
920
            case RW_SEEK_END:
929
957
        if (movement > 0) {
930
958
            unsigned char buffer[4096];
931
959
 
932
 
            // The easy case where we're seeking forwards
 
960
            /* The easy case where we're seeking forwards */
933
961
            while (movement > 0) {
934
962
                Sint64 amount = sizeof (buffer);
935
963
                if (amount > movement) {
937
965
                }
938
966
                size_t result = Android_JNI_FileRead(ctx, buffer, 1, amount);
939
967
                if (result <= 0) {
940
 
                    // Failed to read/skip the required amount, so fail
 
968
                    /* Failed to read/skip the required amount, so fail */
941
969
                    return -1;
942
970
                }
943
971
 
945
973
            }
946
974
 
947
975
        } else if (movement < 0) {
948
 
            // We can't seek backwards so we have to reopen the file and seek
949
 
            // forwards which obviously isn't very efficient
 
976
            /* We can't seek backwards so we have to reopen the file and seek */
 
977
            /* forwards which obviously isn't very efficient */
950
978
            Internal_Android_JNI_FileClose(ctx, false);
951
979
            Internal_Android_JNI_FileOpen(ctx);
952
980
            Android_JNI_FileSeek(ctx, newPosition, RW_SEEK_SET);
962
990
    return Internal_Android_JNI_FileClose(ctx, true);
963
991
}
964
992
 
965
 
// returns a new global reference which needs to be released later
 
993
/* returns a new global reference which needs to be released later */
966
994
static jobject Android_JNI_GetSystemServiceObject(const char* name)
967
995
{
968
996
    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1062
1090
}
1063
1091
 
1064
1092
 
1065
 
// returns 0 on success or -1 on error (others undefined then)
1066
 
// returns truthy or falsy value in plugged, charged and battery
1067
 
// returns the value in seconds and percent or -1 if not available
 
1093
/* returns 0 on success or -1 on error (others undefined then)
 
1094
 * returns truthy or falsy value in plugged, charged and battery
 
1095
 * returns the value in seconds and percent or -1 if not available
 
1096
 */
1068
1097
int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seconds, int* percent)
1069
1098
{
1070
1099
    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
1112
1141
    (*env)->DeleteLocalRef(env, bname);
1113
1142
 
1114
1143
    if (plugged) {
1115
 
        GET_INT_EXTRA(plug, "plugged") // == BatteryManager.EXTRA_PLUGGED (API 5)
 
1144
        GET_INT_EXTRA(plug, "plugged") /* == BatteryManager.EXTRA_PLUGGED (API 5) */
1116
1145
        if (plug == -1) {
1117
1146
            LocalReferenceHolder_Cleanup(&refs);
1118
1147
            return -1;
1119
1148
        }
1120
 
        // 1 == BatteryManager.BATTERY_PLUGGED_AC
1121
 
        // 2 == BatteryManager.BATTERY_PLUGGED_USB
 
1149
        /* 1 == BatteryManager.BATTERY_PLUGGED_AC */
 
1150
        /* 2 == BatteryManager.BATTERY_PLUGGED_USB */
1122
1151
        *plugged = (0 < plug) ? 1 : 0;
1123
1152
    }
1124
1153
 
1125
1154
    if (charged) {
1126
 
        GET_INT_EXTRA(status, "status") // == BatteryManager.EXTRA_STATUS (API 5)
 
1155
        GET_INT_EXTRA(status, "status") /* == BatteryManager.EXTRA_STATUS (API 5) */
1127
1156
        if (status == -1) {
1128
1157
            LocalReferenceHolder_Cleanup(&refs);
1129
1158
            return -1;
1130
1159
        }
1131
 
        // 5 == BatteryManager.BATTERY_STATUS_FULL
 
1160
        /* 5 == BatteryManager.BATTERY_STATUS_FULL */
1132
1161
        *charged = (status == 5) ? 1 : 0;
1133
1162
    }
1134
1163
 
1135
1164
    if (battery) {
1136
 
        GET_BOOL_EXTRA(present, "present") // == BatteryManager.EXTRA_PRESENT (API 5)
 
1165
        GET_BOOL_EXTRA(present, "present") /* == BatteryManager.EXTRA_PRESENT (API 5) */
1137
1166
        *battery = present ? 1 : 0;
1138
1167
    }
1139
1168
 
1140
1169
    if (seconds) {
1141
 
        *seconds = -1; // not possible
 
1170
        *seconds = -1; /* not possible */
1142
1171
    }
1143
1172
 
1144
1173
    if (percent) {
1145
 
        GET_INT_EXTRA(level, "level") // == BatteryManager.EXTRA_LEVEL (API 5)
1146
 
        GET_INT_EXTRA(scale, "scale") // == BatteryManager.EXTRA_SCALE (API 5)
 
1174
        GET_INT_EXTRA(level, "level") /* == BatteryManager.EXTRA_LEVEL (API 5) */
 
1175
        GET_INT_EXTRA(scale, "scale") /* == BatteryManager.EXTRA_SCALE (API 5) */
1147
1176
        if ((level == -1) || (scale == -1)) {
1148
1177
            LocalReferenceHolder_Cleanup(&refs);
1149
1178
            return -1;
1157
1186
    return 0;
1158
1187
}
1159
1188
 
1160
 
// sends message to be handled on the UI event dispatch thread
 
1189
/* returns number of found touch devices as return value and ids in parameter ids */
 
1190
int Android_JNI_GetTouchDeviceIds(int **ids) {
 
1191
    JNIEnv *env = Android_JNI_GetEnv();
 
1192
    jint sources = 4098; /* == InputDevice.SOURCE_TOUCHSCREEN */
 
1193
    jmethodID mid = (*env)->GetStaticMethodID(env, mActivityClass, "inputGetInputDeviceIds", "(I)[I");
 
1194
    jintArray array = (jintArray) (*env)->CallStaticObjectMethod(env, mActivityClass, mid, sources);
 
1195
    int number = 0;
 
1196
    *ids = NULL;
 
1197
    if (array) {
 
1198
        number = (int) (*env)->GetArrayLength(env, array);
 
1199
        if (0 < number) {
 
1200
            jint* elements = (*env)->GetIntArrayElements(env, array, NULL);
 
1201
            if (elements) {
 
1202
                int i;
 
1203
                *ids = SDL_malloc(number * sizeof (**ids));
 
1204
                for (i = 0; i < number; ++i) { /* not assuming sizeof (jint) == sizeof (int) */
 
1205
                    (*ids)[i] = elements[i];
 
1206
                }
 
1207
                (*env)->ReleaseIntArrayElements(env, array, elements, JNI_ABORT);
 
1208
            }
 
1209
        }
 
1210
        (*env)->DeleteLocalRef(env, array);
 
1211
    }
 
1212
    return number;
 
1213
}
 
1214
 
 
1215
/* sends message to be handled on the UI event dispatch thread */
1161
1216
int Android_JNI_SendMessage(int command, int param)
1162
1217
{
1163
1218
    JNIEnv *env = Android_JNI_GetEnv();
1192
1247
 
1193
1248
void Android_JNI_HideTextInput()
1194
1249
{
1195
 
    // has to match Activity constant
 
1250
    /* has to match Activity constant */
1196
1251
    const int COMMAND_TEXTEDIT_HIDE = 3;
1197
1252
    Android_JNI_SendMessage(COMMAND_TEXTEDIT_HIDE, 0);
1198
1253
}
1199
1254
 
 
1255
/*
1200
1256
//////////////////////////////////////////////////////////////////////////////
1201
1257
//
1202
1258
// Functions exposed to SDL applications in SDL_system.h
1203
 
//
 
1259
//////////////////////////////////////////////////////////////////////////////
 
1260
*/
1204
1261
 
1205
1262
void *SDL_AndroidGetJNIEnv()
1206
1263
{
1220
1277
        return NULL;
1221
1278
    }
1222
1279
 
1223
 
    // return SDLActivity.getContext();
 
1280
    /* return SDLActivity.getContext(); */
1224
1281
    mid = (*env)->GetStaticMethodID(env, mActivityClass,
1225
1282
            "getContext","()Landroid/content/Context;");
1226
1283
    return (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
1244
1301
            return NULL;
1245
1302
        }
1246
1303
 
1247
 
        // context = SDLActivity.getContext();
 
1304
        /* context = SDLActivity.getContext(); */
1248
1305
        mid = (*env)->GetStaticMethodID(env, mActivityClass,
1249
1306
                "getContext","()Landroid/content/Context;");
1250
1307
        context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
1251
1308
 
1252
 
        // fileObj = context.getFilesDir();
 
1309
        /* fileObj = context.getFilesDir(); */
1253
1310
        mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context),
1254
1311
                "getFilesDir", "()Ljava/io/File;");
1255
1312
        fileObject = (*env)->CallObjectMethod(env, context, mid);
1259
1316
            return NULL;
1260
1317
        }
1261
1318
 
1262
 
        // path = fileObject.getAbsolutePath();
 
1319
        /* path = fileObject.getAbsolutePath(); */
1263
1320
        mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, fileObject),
1264
1321
                "getAbsolutePath", "()Ljava/lang/String;");
1265
1322
        pathString = (jstring)(*env)->CallObjectMethod(env, fileObject, mid);
1295
1352
 
1296
1353
    state = (*env)->GetStringUTFChars(env, stateString, NULL);
1297
1354
 
1298
 
    // Print an info message so people debugging know the storage state
 
1355
    /* Print an info message so people debugging know the storage state */
1299
1356
    __android_log_print(ANDROID_LOG_INFO, "SDL", "external storage state: %s", state);
1300
1357
 
1301
1358
    if (SDL_strcmp(state, "mounted") == 0) {
1330
1387
            return NULL;
1331
1388
        }
1332
1389
 
1333
 
        // context = SDLActivity.getContext();
 
1390
        /* context = SDLActivity.getContext(); */
1334
1391
        mid = (*env)->GetStaticMethodID(env, mActivityClass,
1335
1392
                "getContext","()Landroid/content/Context;");
1336
1393
        context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
1337
1394
 
1338
 
        // fileObj = context.getExternalFilesDir();
 
1395
        /* fileObj = context.getExternalFilesDir(); */
1339
1396
        mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context),
1340
1397
                "getExternalFilesDir", "(Ljava/lang/String;)Ljava/io/File;");
1341
1398
        fileObject = (*env)->CallObjectMethod(env, context, mid, NULL);
1345
1402
            return NULL;
1346
1403
        }
1347
1404
 
1348
 
        // path = fileObject.getAbsolutePath();
 
1405
        /* path = fileObject.getAbsolutePath(); */
1349
1406
        mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, fileObject),
1350
1407
                "getAbsolutePath", "()Ljava/lang/String;");
1351
1408
        pathString = (jstring)(*env)->CallObjectMethod(env, fileObject, mid);