diff options
| author | Po Lu | 2023-02-25 19:11:07 +0800 |
|---|---|---|
| committer | Po Lu | 2023-02-25 19:11:07 +0800 |
| commit | 8e4c5db193dc7baee5846520fe8b63d8bea99148 (patch) | |
| tree | 595eb65601d38b7895ae1d00ec9a71a947cd1af7 /src/android.c | |
| parent | d5cccfdc564f1486431f9674503c794df33d7fbc (diff) | |
| download | emacs-8e4c5db193dc7baee5846520fe8b63d8bea99148.tar.gz emacs-8e4c5db193dc7baee5846520fe8b63d8bea99148.zip | |
Update Android port
* doc/emacs/android.texi (Android Startup, Android File System)
(Android Environment, Android Windowing, Android
Troubleshooting): Improve documentation; fix typos.
* doc/lispref/commands.texi (Misc Events): Likewise.
* java/org/gnu/emacs/EmacsService.java (queryBattery): New
function.
* lisp/battery.el (battery-status-function): Set appropriately
for Android.
(battery-android): New function.
* src/android.c (struct android_emacs_service): New method
`query_battery'.
(android_check_content_access): Improve exception checking.
(android_init_emacs_service): Look up new method.
(android_destroy_handle, android_create_window)
(android_init_android_rect_class, android_init_emacs_gc_class)
(android_set_clip_rectangles)
(android_create_pixmap_from_bitmap_data, android_fill_polygon)
(android_get_image, android_put_image, android_bell)
(android_set_input_focus, android_raise_window)
(android_lower_window, android_query_tree, android_get_geometry)
(android_translate_coordinates, android_wc_lookup_string)
(android_damage_window, android_build_string)
(android_build_jstring, android_exception_check_1)
(android_exception_check_2): New functions.
(android_browse_url): Improve exception handling. Always use
android_exception_check and don't leak local refs.
(android_query_battery): New function.
* src/android.h (struct android_battery_state): New struct.
* src/androidfns.c (Fandroid_query_battery, syms_of_androidfns):
New function.
* src/androidfont.c (androidfont_from_lisp, DO_SYMBOL_FIELD)
(DO_CARDINAL_FIELD, androidfont_list, androidfont_match)
(androidfont_draw, androidfont_open_font)
(androidfont_close_font):
* src/androidselect.c (Fandroid_set_clipboard)
(Fandroid_get_clipboard):
* src/sfnt.c (sfnt_map_glyf_table):
* src/sfntfont.c (sfntfont_free_outline_cache)
(sfntfont_free_raster_cache, sfntfont_close): Allow font close
functions to be called twice.
Diffstat (limited to 'src/android.c')
| -rw-r--r-- | src/android.c | 239 |
1 files changed, 148 insertions, 91 deletions
diff --git a/src/android.c b/src/android.c index 9c600be6cdf..72c50c0a13c 100644 --- a/src/android.c +++ b/src/android.c | |||
| @@ -111,6 +111,7 @@ struct android_emacs_service | |||
| 111 | jmethodID reset_ic; | 111 | jmethodID reset_ic; |
| 112 | jmethodID open_content_uri; | 112 | jmethodID open_content_uri; |
| 113 | jmethodID check_content_uri; | 113 | jmethodID check_content_uri; |
| 114 | jmethodID query_battery; | ||
| 114 | }; | 115 | }; |
| 115 | 116 | ||
| 116 | struct android_emacs_pixmap | 117 | struct android_emacs_pixmap |
| @@ -1050,7 +1051,7 @@ android_check_content_access (const char *filename, int mode) | |||
| 1050 | != 0), | 1051 | != 0), |
| 1051 | (jboolean) ((mode & W_OK) | 1052 | (jboolean) ((mode & W_OK) |
| 1052 | != 0)); | 1053 | != 0)); |
| 1053 | android_exception_check (); | 1054 | android_exception_check_1 (string); |
| 1054 | ANDROID_DELETE_LOCAL_REF (string); | 1055 | ANDROID_DELETE_LOCAL_REF (string); |
| 1055 | 1056 | ||
| 1056 | return rc; | 1057 | return rc; |
| @@ -1998,6 +1999,7 @@ android_init_emacs_service (void) | |||
| 1998 | "([BZZZ)I"); | 1999 | "([BZZZ)I"); |
| 1999 | FIND_METHOD (check_content_uri, "checkContentUri", | 2000 | FIND_METHOD (check_content_uri, "checkContentUri", |
| 2000 | "([BZZ)Z"); | 2001 | "([BZZ)Z"); |
| 2002 | FIND_METHOD (query_battery, "queryBattery", "()[J"); | ||
| 2001 | #undef FIND_METHOD | 2003 | #undef FIND_METHOD |
| 2002 | } | 2004 | } |
| 2003 | 2005 | ||
| @@ -2691,11 +2693,8 @@ android_destroy_handle (android_handle handle) | |||
| 2691 | class | 2693 | class |
| 2692 | = (jclass) (*android_java_env)->NewGlobalRef (android_java_env, | 2694 | = (jclass) (*android_java_env)->NewGlobalRef (android_java_env, |
| 2693 | (jobject) class); | 2695 | (jobject) class); |
| 2694 | (*android_java_env)->ExceptionClear (android_java_env); | 2696 | android_exception_check_1 (old); |
| 2695 | ANDROID_DELETE_LOCAL_REF (old); | 2697 | ANDROID_DELETE_LOCAL_REF (old); |
| 2696 | |||
| 2697 | if (!class) | ||
| 2698 | memory_full (0); | ||
| 2699 | } | 2698 | } |
| 2700 | 2699 | ||
| 2701 | (*android_java_env)->CallVoidMethod (android_java_env, | 2700 | (*android_java_env)->CallVoidMethod (android_java_env, |
| @@ -2818,11 +2817,8 @@ android_create_window (android_window parent, int x, int y, | |||
| 2818 | 2817 | ||
| 2819 | old = class; | 2818 | old = class; |
| 2820 | class = (*android_java_env)->NewGlobalRef (android_java_env, class); | 2819 | class = (*android_java_env)->NewGlobalRef (android_java_env, class); |
| 2821 | (*android_java_env)->ExceptionClear (android_java_env); | 2820 | android_exception_check_1 (old); |
| 2822 | ANDROID_DELETE_LOCAL_REF (old); | 2821 | ANDROID_DELETE_LOCAL_REF (old); |
| 2823 | |||
| 2824 | if (!class) | ||
| 2825 | memory_full (0); | ||
| 2826 | } | 2822 | } |
| 2827 | 2823 | ||
| 2828 | /* N.B. that ANDROID_CW_OVERRIDE_REDIRECT can only be set at window | 2824 | /* N.B. that ANDROID_CW_OVERRIDE_REDIRECT can only be set at window |
| @@ -2904,11 +2900,8 @@ android_init_android_rect_class (void) | |||
| 2904 | android_rect_class | 2900 | android_rect_class |
| 2905 | = (jclass) (*android_java_env)->NewGlobalRef (android_java_env, | 2901 | = (jclass) (*android_java_env)->NewGlobalRef (android_java_env, |
| 2906 | (jobject) android_rect_class); | 2902 | (jobject) android_rect_class); |
| 2907 | (*android_java_env)->ExceptionClear (android_java_env); | 2903 | android_exception_check_1 (old); |
| 2908 | ANDROID_DELETE_LOCAL_REF (old); | 2904 | ANDROID_DELETE_LOCAL_REF (old); |
| 2909 | |||
| 2910 | if (!android_rect_class) | ||
| 2911 | memory_full (0); | ||
| 2912 | } | 2905 | } |
| 2913 | 2906 | ||
| 2914 | static void | 2907 | static void |
| @@ -2941,10 +2934,8 @@ android_init_emacs_gc_class (void) | |||
| 2941 | emacs_gc_class | 2934 | emacs_gc_class |
| 2942 | = (jclass) (*android_java_env)->NewGlobalRef (android_java_env, | 2935 | = (jclass) (*android_java_env)->NewGlobalRef (android_java_env, |
| 2943 | (jobject) emacs_gc_class); | 2936 | (jobject) emacs_gc_class); |
| 2944 | (*android_java_env)->ExceptionClear (android_java_env); | 2937 | android_exception_check_1 (old); |
| 2945 | ANDROID_DELETE_LOCAL_REF (old); | 2938 | ANDROID_DELETE_LOCAL_REF (old); |
| 2946 | if (!emacs_gc_class) | ||
| 2947 | memory_full (0); | ||
| 2948 | 2939 | ||
| 2949 | emacs_gc_foreground | 2940 | emacs_gc_foreground |
| 2950 | = (*android_java_env)->GetFieldID (android_java_env, | 2941 | = (*android_java_env)->GetFieldID (android_java_env, |
| @@ -3188,12 +3179,7 @@ android_set_clip_rectangles (struct android_gc *gc, int clip_x_origin, | |||
| 3188 | n_clip_rects, | 3179 | n_clip_rects, |
| 3189 | android_rect_class, | 3180 | android_rect_class, |
| 3190 | NULL); | 3181 | NULL); |
| 3191 | 3182 | android_exception_check (); | |
| 3192 | if (!array) | ||
| 3193 | { | ||
| 3194 | (*android_java_env)->ExceptionClear (android_java_env); | ||
| 3195 | memory_full (0); | ||
| 3196 | } | ||
| 3197 | 3183 | ||
| 3198 | for (i = 0; i < n_clip_rects; ++i) | 3184 | for (i = 0; i < n_clip_rects; ++i) |
| 3199 | { | 3185 | { |
| @@ -3207,12 +3193,10 @@ android_set_clip_rectangles (struct android_gc *gc, int clip_x_origin, | |||
| 3207 | (jint) (clip_rects[i].y | 3193 | (jint) (clip_rects[i].y |
| 3208 | + clip_rects[i].height)); | 3194 | + clip_rects[i].height)); |
| 3209 | 3195 | ||
| 3210 | if (!rect) | 3196 | /* The meaning of this call is to check whether or not an |
| 3211 | { | 3197 | allocation error happened, and to delete ARRAY and signal an |
| 3212 | (*android_java_env)->ExceptionClear (android_java_env); | 3198 | out-of-memory error if that is the case. */ |
| 3213 | ANDROID_DELETE_LOCAL_REF (array); | 3199 | android_exception_check_1 (array); |
| 3214 | memory_full (0); | ||
| 3215 | } | ||
| 3216 | 3200 | ||
| 3217 | (*android_java_env)->SetObjectArrayElement (android_java_env, | 3201 | (*android_java_env)->SetObjectArrayElement (android_java_env, |
| 3218 | array, i, rect); | 3202 | array, i, rect); |
| @@ -3511,12 +3495,7 @@ android_create_pixmap_from_bitmap_data (char *data, unsigned int width, | |||
| 3511 | /* Create the color array holding the data. */ | 3495 | /* Create the color array holding the data. */ |
| 3512 | colors = (*android_java_env)->NewIntArray (android_java_env, | 3496 | colors = (*android_java_env)->NewIntArray (android_java_env, |
| 3513 | width * height); | 3497 | width * height); |
| 3514 | 3498 | android_exception_check (); | |
| 3515 | if (!colors) | ||
| 3516 | { | ||
| 3517 | (*android_java_env)->ExceptionClear (android_java_env); | ||
| 3518 | memory_full (0); | ||
| 3519 | } | ||
| 3520 | 3499 | ||
| 3521 | SAFE_NALLOCA (region, sizeof *region, width); | 3500 | SAFE_NALLOCA (region, sizeof *region, width); |
| 3522 | 3501 | ||
| @@ -3666,12 +3645,7 @@ android_fill_polygon (android_drawable drawable, struct android_gc *gc, | |||
| 3666 | npoints, | 3645 | npoints, |
| 3667 | point_class.class, | 3646 | point_class.class, |
| 3668 | NULL); | 3647 | NULL); |
| 3669 | 3648 | android_exception_check (); | |
| 3670 | if (!array) | ||
| 3671 | { | ||
| 3672 | (*android_java_env)->ExceptionClear (android_java_env); | ||
| 3673 | memory_full (0); | ||
| 3674 | } | ||
| 3675 | 3649 | ||
| 3676 | for (i = 0; i < npoints; ++i) | 3650 | for (i = 0; i < npoints; ++i) |
| 3677 | { | 3651 | { |
| @@ -3680,13 +3654,7 @@ android_fill_polygon (android_drawable drawable, struct android_gc *gc, | |||
| 3680 | point_class.constructor, | 3654 | point_class.constructor, |
| 3681 | (jint) points[i].x, | 3655 | (jint) points[i].x, |
| 3682 | (jint) points[i].y); | 3656 | (jint) points[i].y); |
| 3683 | 3657 | android_exception_check_1 (array); | |
| 3684 | if (!point) | ||
| 3685 | { | ||
| 3686 | (*android_java_env)->ExceptionClear (android_java_env); | ||
| 3687 | ANDROID_DELETE_LOCAL_REF (array); | ||
| 3688 | memory_full (0); | ||
| 3689 | } | ||
| 3690 | 3658 | ||
| 3691 | (*android_java_env)->SetObjectArrayElement (android_java_env, | 3659 | (*android_java_env)->SetObjectArrayElement (android_java_env, |
| 3692 | array, i, point); | 3660 | array, i, point); |
| @@ -3978,12 +3946,9 @@ android_get_image (android_drawable handle, | |||
| 3978 | bitmap = (*android_java_env)->CallObjectMethod (android_java_env, | 3946 | bitmap = (*android_java_env)->CallObjectMethod (android_java_env, |
| 3979 | drawable, | 3947 | drawable, |
| 3980 | drawable_class.get_bitmap); | 3948 | drawable_class.get_bitmap); |
| 3981 | if (!bitmap) | 3949 | android_exception_check (); |
| 3982 | { | ||
| 3983 | (*android_java_env)->ExceptionClear (android_java_env); | ||
| 3984 | memory_full (0); | ||
| 3985 | } | ||
| 3986 | 3950 | ||
| 3951 | /* Clear the bitmap info structure. */ | ||
| 3987 | memset (&bitmap_info, 0, sizeof bitmap_info); | 3952 | memset (&bitmap_info, 0, sizeof bitmap_info); |
| 3988 | 3953 | ||
| 3989 | /* The NDK doc seems to imply this function can fail but doesn't say | 3954 | /* The NDK doc seems to imply this function can fail but doesn't say |
| @@ -4115,12 +4080,9 @@ android_put_image (android_pixmap handle, struct android_image *image) | |||
| 4115 | bitmap = (*android_java_env)->CallObjectMethod (android_java_env, | 4080 | bitmap = (*android_java_env)->CallObjectMethod (android_java_env, |
| 4116 | drawable, | 4081 | drawable, |
| 4117 | drawable_class.get_bitmap); | 4082 | drawable_class.get_bitmap); |
| 4118 | if (!bitmap) | 4083 | android_exception_check (); |
| 4119 | { | ||
| 4120 | (*android_java_env)->ExceptionClear (android_java_env); | ||
| 4121 | memory_full (0); | ||
| 4122 | } | ||
| 4123 | 4084 | ||
| 4085 | /* Clear the bitmap info structure. */ | ||
| 4124 | memset (&bitmap_info, 0, sizeof bitmap_info); | 4086 | memset (&bitmap_info, 0, sizeof bitmap_info); |
| 4125 | 4087 | ||
| 4126 | /* The NDK doc seems to imply this function can fail but doesn't say | 4088 | /* The NDK doc seems to imply this function can fail but doesn't say |
| @@ -4196,6 +4158,7 @@ android_bell (void) | |||
| 4196 | (*android_java_env)->CallVoidMethod (android_java_env, | 4158 | (*android_java_env)->CallVoidMethod (android_java_env, |
| 4197 | emacs_service, | 4159 | emacs_service, |
| 4198 | service_class.ring_bell); | 4160 | service_class.ring_bell); |
| 4161 | android_exception_check (); | ||
| 4199 | } | 4162 | } |
| 4200 | 4163 | ||
| 4201 | void | 4164 | void |
| @@ -4210,6 +4173,7 @@ android_set_input_focus (android_window handle, unsigned long time) | |||
| 4210 | 4173 | ||
| 4211 | (*android_java_env)->CallVoidMethod (android_java_env, window, | 4174 | (*android_java_env)->CallVoidMethod (android_java_env, window, |
| 4212 | make_input_focus, (jlong) time); | 4175 | make_input_focus, (jlong) time); |
| 4176 | android_exception_check (); | ||
| 4213 | } | 4177 | } |
| 4214 | 4178 | ||
| 4215 | void | 4179 | void |
| @@ -4224,6 +4188,7 @@ android_raise_window (android_window handle) | |||
| 4224 | 4188 | ||
| 4225 | (*android_java_env)->CallVoidMethod (android_java_env, window, | 4189 | (*android_java_env)->CallVoidMethod (android_java_env, window, |
| 4226 | raise); | 4190 | raise); |
| 4191 | android_exception_check (); | ||
| 4227 | } | 4192 | } |
| 4228 | 4193 | ||
| 4229 | void | 4194 | void |
| @@ -4238,6 +4203,7 @@ android_lower_window (android_window handle) | |||
| 4238 | 4203 | ||
| 4239 | (*android_java_env)->CallVoidMethod (android_java_env, window, | 4204 | (*android_java_env)->CallVoidMethod (android_java_env, window, |
| 4240 | lower); | 4205 | lower); |
| 4206 | android_exception_check (); | ||
| 4241 | } | 4207 | } |
| 4242 | 4208 | ||
| 4243 | int | 4209 | int |
| @@ -4259,11 +4225,7 @@ android_query_tree (android_window handle, android_window *root_return, | |||
| 4259 | emacs_service, | 4225 | emacs_service, |
| 4260 | service_class.query_tree, | 4226 | service_class.query_tree, |
| 4261 | window); | 4227 | window); |
| 4262 | if (!array) | 4228 | android_exception_check (); |
| 4263 | { | ||
| 4264 | (*android_java_env)->ExceptionClear (android_java_env); | ||
| 4265 | memory_full (0); | ||
| 4266 | } | ||
| 4267 | 4229 | ||
| 4268 | /* The first element of the array is the parent window. The rest | 4230 | /* The first element of the array is the parent window. The rest |
| 4269 | are the children. */ | 4231 | are the children. */ |
| @@ -4315,11 +4277,7 @@ android_get_geometry (android_window handle, | |||
| 4315 | = (*android_java_env)->CallObjectMethod (android_java_env, | 4277 | = (*android_java_env)->CallObjectMethod (android_java_env, |
| 4316 | window, | 4278 | window, |
| 4317 | get_geometry); | 4279 | get_geometry); |
| 4318 | if (!window_geometry) | 4280 | android_exception_check (); |
| 4319 | { | ||
| 4320 | (*android_java_env)->ExceptionClear (android_java_env); | ||
| 4321 | memory_full (0); | ||
| 4322 | } | ||
| 4323 | 4281 | ||
| 4324 | /* window_geometry is an array containing x, y, width and | 4282 | /* window_geometry is an array containing x, y, width and |
| 4325 | height. border_width is always 0 on Android. */ | 4283 | height. border_width is always 0 on Android. */ |
| @@ -4380,12 +4338,7 @@ android_translate_coordinates (android_window src, int x, | |||
| 4380 | = (*android_java_env)->CallObjectMethod (android_java_env, | 4338 | = (*android_java_env)->CallObjectMethod (android_java_env, |
| 4381 | window, method, | 4339 | window, method, |
| 4382 | (jint) x, (jint) y); | 4340 | (jint) x, (jint) y); |
| 4383 | 4341 | android_exception_check (); | |
| 4384 | if (!coordinates) | ||
| 4385 | { | ||
| 4386 | (*android_java_env)->ExceptionClear (android_java_env); | ||
| 4387 | memory_full (0); | ||
| 4388 | } | ||
| 4389 | 4342 | ||
| 4390 | /* The array must contain two elements: X, Y translated to the root | 4343 | /* The array must contain two elements: X, Y translated to the root |
| 4391 | window. */ | 4344 | window. */ |
| @@ -4396,6 +4349,8 @@ android_translate_coordinates (android_window src, int x, | |||
| 4396 | /* Obtain the coordinates from the array. */ | 4349 | /* Obtain the coordinates from the array. */ |
| 4397 | ints = (*android_java_env)->GetIntArrayElements (android_java_env, | 4350 | ints = (*android_java_env)->GetIntArrayElements (android_java_env, |
| 4398 | coordinates, NULL); | 4351 | coordinates, NULL); |
| 4352 | android_exception_check_1 (coordinates); | ||
| 4353 | |||
| 4399 | *root_x = ints[0]; | 4354 | *root_x = ints[0]; |
| 4400 | *root_y = ints[1]; | 4355 | *root_y = ints[1]; |
| 4401 | 4356 | ||
| @@ -4492,7 +4447,7 @@ android_wc_lookup_string (android_key_pressed_event *event, | |||
| 4492 | /* Now return this input method string. */ | 4447 | /* Now return this input method string. */ |
| 4493 | characters = (*android_java_env)->GetStringChars (android_java_env, | 4448 | characters = (*android_java_env)->GetStringChars (android_java_env, |
| 4494 | string, NULL); | 4449 | string, NULL); |
| 4495 | android_exception_check (); | 4450 | android_exception_check_1 (string); |
| 4496 | 4451 | ||
| 4497 | /* Figure out how big the string is. */ | 4452 | /* Figure out how big the string is. */ |
| 4498 | size = (*android_java_env)->GetStringLength (android_java_env, | 4453 | size = (*android_java_env)->GetStringLength (android_java_env, |
| @@ -4517,7 +4472,6 @@ android_wc_lookup_string (android_key_pressed_event *event, | |||
| 4517 | 4472 | ||
| 4518 | (*android_java_env)->ReleaseStringChars (android_java_env, string, | 4473 | (*android_java_env)->ReleaseStringChars (android_java_env, string, |
| 4519 | characters); | 4474 | characters); |
| 4520 | android_exception_check (); | ||
| 4521 | ANDROID_DELETE_LOCAL_REF (string); | 4475 | ANDROID_DELETE_LOCAL_REF (string); |
| 4522 | } | 4476 | } |
| 4523 | } | 4477 | } |
| @@ -4604,17 +4558,14 @@ android_damage_window (android_drawable handle, | |||
| 4604 | + damage->width), | 4558 | + damage->width), |
| 4605 | (jint) (damage->y | 4559 | (jint) (damage->y |
| 4606 | + damage->height)); | 4560 | + damage->height)); |
| 4607 | if (!rect) | 4561 | android_exception_check (); |
| 4608 | { | ||
| 4609 | (*android_java_env)->ExceptionClear (android_java_env); | ||
| 4610 | memory_full (0); | ||
| 4611 | } | ||
| 4612 | 4562 | ||
| 4613 | /* Post the damage to the drawable. */ | 4563 | /* Post the damage to the drawable. */ |
| 4614 | (*android_java_env)->CallVoidMethod (android_java_env, | 4564 | (*android_java_env)->CallVoidMethod (android_java_env, |
| 4615 | drawable, | 4565 | drawable, |
| 4616 | drawable_class.damage_rect, | 4566 | drawable_class.damage_rect, |
| 4617 | rect); | 4567 | rect); |
| 4568 | android_exception_check_1 (rect); | ||
| 4618 | ANDROID_DELETE_LOCAL_REF (rect); | 4569 | ANDROID_DELETE_LOCAL_REF (rect); |
| 4619 | } | 4570 | } |
| 4620 | 4571 | ||
| @@ -5114,11 +5065,7 @@ android_build_string (Lisp_Object text) | |||
| 5114 | not really of consequence. */ | 5065 | not really of consequence. */ |
| 5115 | string = (*android_java_env)->NewStringUTF (android_java_env, | 5066 | string = (*android_java_env)->NewStringUTF (android_java_env, |
| 5116 | SSDATA (encoded)); | 5067 | SSDATA (encoded)); |
| 5117 | if (!string) | 5068 | android_exception_check (); |
| 5118 | { | ||
| 5119 | (*android_java_env)->ExceptionClear (android_java_env); | ||
| 5120 | memory_full (0); | ||
| 5121 | } | ||
| 5122 | 5069 | ||
| 5123 | return string; | 5070 | return string; |
| 5124 | } | 5071 | } |
| @@ -5132,15 +5079,45 @@ android_build_jstring (const char *text) | |||
| 5132 | 5079 | ||
| 5133 | string = (*android_java_env)->NewStringUTF (android_java_env, | 5080 | string = (*android_java_env)->NewStringUTF (android_java_env, |
| 5134 | text); | 5081 | text); |
| 5135 | if (!string) | 5082 | android_exception_check (); |
| 5136 | { | ||
| 5137 | (*android_java_env)->ExceptionClear (android_java_env); | ||
| 5138 | memory_full (0); | ||
| 5139 | } | ||
| 5140 | 5083 | ||
| 5141 | return string; | 5084 | return string; |
| 5142 | } | 5085 | } |
| 5143 | 5086 | ||
| 5087 | |||
| 5088 | |||
| 5089 | /* Exception checking functions. Most JNI functions which allocate | ||
| 5090 | memory return NULL upon failure; they also set the JNI | ||
| 5091 | environment's pending exception to an OutOfMemoryError. | ||
| 5092 | |||
| 5093 | These functions check for such errors and call memory_full wherever | ||
| 5094 | appropriate. Three variants are provided: one which releases no | ||
| 5095 | local references, one which releases a single local reference | ||
| 5096 | before calling memory_full, and one which releases two local | ||
| 5097 | references. | ||
| 5098 | |||
| 5099 | Typically, you use these functions by calling them immediately | ||
| 5100 | after a JNI function which allocates memory, passing it any local | ||
| 5101 | references that are already valid but are not used after leaving | ||
| 5102 | the current scope. For example, to allocate foo and then make | ||
| 5103 | global_foo its global reference, and then release foo, you write: | ||
| 5104 | |||
| 5105 | jobject foo, global_foo; | ||
| 5106 | |||
| 5107 | foo = (*android_java_env)->New...; | ||
| 5108 | android_exception_check (); | ||
| 5109 | |||
| 5110 | global_foo = (*android_java_env)->NewGlobalRef (..., foo); | ||
| 5111 | android_exception_check_1 (foo); | ||
| 5112 | ANDROID_DELETE_LOCAL_REF (foo); | ||
| 5113 | |||
| 5114 | where the first android_exception_check ensures that foo has been | ||
| 5115 | allocated correctly, while the call to android_exception_check_1, | ||
| 5116 | and the call to ANDROID_DELETE_LOCAL_REF afterwards, together | ||
| 5117 | ensure the same of global_foo, and also that foo is released both | ||
| 5118 | if global_foo cannot be allocated, and after the global reference | ||
| 5119 | is created. */ | ||
| 5120 | |||
| 5144 | /* Check for JNI exceptions and call memory_full in that | 5121 | /* Check for JNI exceptions and call memory_full in that |
| 5145 | situation. */ | 5122 | situation. */ |
| 5146 | 5123 | ||
| @@ -5159,6 +5136,47 @@ android_exception_check (void) | |||
| 5159 | } | 5136 | } |
| 5160 | } | 5137 | } |
| 5161 | 5138 | ||
| 5139 | /* Check for JNI exceptions. If there is one such exception, clear | ||
| 5140 | it, then delete the local reference to OBJECT and call | ||
| 5141 | memory_full. */ | ||
| 5142 | |||
| 5143 | void | ||
| 5144 | android_exception_check_1 (jobject object) | ||
| 5145 | { | ||
| 5146 | if ((*android_java_env)->ExceptionCheck (android_java_env)) | ||
| 5147 | { | ||
| 5148 | __android_log_print (ANDROID_LOG_WARN, __func__, | ||
| 5149 | "Possible out of memory error." | ||
| 5150 | " The Java exception follows: "); | ||
| 5151 | /* Describe exactly what went wrong. */ | ||
| 5152 | (*android_java_env)->ExceptionDescribe (android_java_env); | ||
| 5153 | (*android_java_env)->ExceptionClear (android_java_env); | ||
| 5154 | ANDROID_DELETE_LOCAL_REF (object); | ||
| 5155 | memory_full (0); | ||
| 5156 | } | ||
| 5157 | } | ||
| 5158 | |||
| 5159 | /* Like android_exception_check_one, except it takes more than one | ||
| 5160 | local reference argument. */ | ||
| 5161 | |||
| 5162 | void | ||
| 5163 | android_exception_check_2 (jobject object, jobject object1) | ||
| 5164 | { | ||
| 5165 | if ((*android_java_env)->ExceptionCheck (android_java_env)) | ||
| 5166 | { | ||
| 5167 | __android_log_print (ANDROID_LOG_WARN, __func__, | ||
| 5168 | "Possible out of memory error." | ||
| 5169 | " The Java exception follows: "); | ||
| 5170 | /* Describe exactly what went wrong. */ | ||
| 5171 | (*android_java_env)->ExceptionDescribe (android_java_env); | ||
| 5172 | (*android_java_env)->ExceptionClear (android_java_env); | ||
| 5173 | ANDROID_DELETE_LOCAL_REF (object); | ||
| 5174 | ANDROID_DELETE_LOCAL_REF (object1); | ||
| 5175 | memory_full (0); | ||
| 5176 | } | ||
| 5177 | } | ||
| 5178 | |||
| 5179 | |||
| 5162 | 5180 | ||
| 5163 | 5181 | ||
| 5164 | /* Native image transforms. */ | 5182 | /* Native image transforms. */ |
| @@ -5446,7 +5464,7 @@ android_browse_url (Lisp_Object url) | |||
| 5446 | buffer = (*android_java_env)->GetStringUTFChars (android_java_env, | 5464 | buffer = (*android_java_env)->GetStringUTFChars (android_java_env, |
| 5447 | (jstring) value, | 5465 | (jstring) value, |
| 5448 | NULL); | 5466 | NULL); |
| 5449 | android_exception_check (); | 5467 | android_exception_check_1 (string); |
| 5450 | 5468 | ||
| 5451 | /* Otherwise, build the string describing the error. */ | 5469 | /* Otherwise, build the string describing the error. */ |
| 5452 | tem = build_string_from_utf8 (buffer); | 5470 | tem = build_string_from_utf8 (buffer); |
| @@ -5490,6 +5508,45 @@ android_get_current_api_level (void) | |||
| 5490 | return android_api_level; | 5508 | return android_api_level; |
| 5491 | } | 5509 | } |
| 5492 | 5510 | ||
| 5511 | /* Query the status of the battery, and place it in *STATUS. | ||
| 5512 | Value is 1 if the system is too old, else 0. */ | ||
| 5513 | |||
| 5514 | int | ||
| 5515 | android_query_battery (struct android_battery_state *status) | ||
| 5516 | { | ||
| 5517 | jlongArray array; | ||
| 5518 | jlong *longs; | ||
| 5519 | |||
| 5520 | array = (*android_java_env)->CallObjectMethod (android_java_env, | ||
| 5521 | emacs_service, | ||
| 5522 | service_class.query_battery); | ||
| 5523 | android_exception_check (); | ||
| 5524 | |||
| 5525 | /* A NULL return with no exception means that battery information | ||
| 5526 | could not be obtained. */ | ||
| 5527 | |||
| 5528 | if (!array) | ||
| 5529 | return 1; | ||
| 5530 | |||
| 5531 | longs = (*android_java_env)->GetLongArrayElements (android_java_env, | ||
| 5532 | array, NULL); | ||
| 5533 | android_exception_check_1 (array); | ||
| 5534 | |||
| 5535 | status->capacity = longs[0]; | ||
| 5536 | status->charge_counter = longs[1]; | ||
| 5537 | status->current_average = longs[2]; | ||
| 5538 | status->current_now = longs[3]; | ||
| 5539 | status->remaining = longs[4]; | ||
| 5540 | status->status = longs[5]; | ||
| 5541 | |||
| 5542 | (*android_java_env)->ReleaseLongArrayElements (android_java_env, | ||
| 5543 | array, longs, | ||
| 5544 | JNI_ABORT); | ||
| 5545 | ANDROID_DELETE_LOCAL_REF (array); | ||
| 5546 | |||
| 5547 | return 0; | ||
| 5548 | } | ||
| 5549 | |||
| 5493 | 5550 | ||
| 5494 | 5551 | ||
| 5495 | /* Whether or not a query is currently being made. */ | 5552 | /* Whether or not a query is currently being made. */ |