diff options
| author | Po Lu | 2023-01-19 22:19:06 +0800 |
|---|---|---|
| committer | Po Lu | 2023-01-19 22:19:06 +0800 |
| commit | a496509cedb17109d0e6297a74e2ff8ed526333c (patch) | |
| tree | 46f3db2be263de7074675a5188796e25f21d4888 /src/android.c | |
| parent | 6253e7e74249c7cdfa86723f0b91a1d207cb143e (diff) | |
| download | emacs-a496509cedb17109d0e6297a74e2ff8ed526333c.tar.gz emacs-a496509cedb17109d0e6297a74e2ff8ed526333c.zip | |
Update Android port
* .gitignore: Add new files.
* INSTALL.android: Explain how to build Emacs for ancient
versions of Android.
* admin/merge-gnulib (GNULIB_MODULES): Add getdelim.
* build-aux/config.guess (timestamp, version):
* build-aux/config.sub (timestamp, version): Autoupdate.
* configure.ac (BUILD_DETAILS, ANDROID_MIN_SDK):
(ANDROID_STUBIFY): Allow specifying CFLAGS via ANDROID_CFLAGS.
Add new configure tests for Android API version when not
explicitly specified.
* doc/emacs/android.texi (Android): Add reference to ``Other
Input Devices''.
(Android File System): Remove restrictions on directory-files on
the assets directory.
* doc/emacs/emacs.texi (Top): Add Other Input Devices to menu.
* doc/emacs/input.texi (Other Input Devices): New node.
* doc/lispref/commands.texi (Touchscreen Events): Document
changes to touchscreen input events.
* doc/lispref/frames.texi (Pop-Up Menus): Likewise.
* etc/NEWS: Announce changes.
* java/Makefile.in: Use lib-src/asset-directory-tool to generate
an `directory-tree' file placed in /assets.
* java/debug.sh: Large adjustments to support Android 2.2 and
later.
* java/org/gnu/emacs/EmacsContextMenu.java (inflateMenuItems):
* java/org/gnu/emacs/EmacsCopyArea.java (perform):
* java/org/gnu/emacs/EmacsDialog.java (toAlertDialog):
* java/org/gnu/emacs/EmacsDrawLine.java (perform):
* java/org/gnu/emacs/EmacsDrawRectangle.java (perform):
* java/org/gnu/emacs/EmacsDrawable.java (EmacsDrawable):
* java/org/gnu/emacs/EmacsFillPolygon.java (perform):
* java/org/gnu/emacs/EmacsFillRectangle.java (perform):
* java/org/gnu/emacs/EmacsGC.java (EmacsGC):
* java/org/gnu/emacs/EmacsPixmap.java (EmacsPixmap):
(destroyHandle):
* java/org/gnu/emacs/EmacsSdk7FontDriver.java (draw): Avoid
redundant canvas saves and restores.
* java/org/gnu/emacs/EmacsService.java (run):
* java/org/gnu/emacs/EmacsView.java (EmacsView):
(handleDirtyBitmap):
* java/org/gnu/emacs/EmacsWindow.java (changeWindowBackground)
(EmacsWindow): Make compatible with Android 2.2 and later.
* lib-src/Makefile.in (DONT_INSTALL): Add asset-directory-tool
on Android.:(asset-directory-tool{EXEEXT}): New target.
* lib-src/asset-directory-tool.c (struct directory_tree, xmalloc)
(main_1, main_2, main): New file.
* lib, m4: Merge from gnulib. This will be reverted before
merging to master.
* lisp/button.el (button-map):
(push-button):
* lisp/frame.el (display-popup-menus-p): Improve touchscreen
support.
* lisp/subr.el (event-start):
(event-end): Handle touchscreen events.
* lisp/touch-screen.el (touch-screen-handle-timeout):
(touch-screen-handle-point-update):
(touch-screen-handle-point-up):
(touch-screen-track-tap):
(touch-screen-track-drag):
(touch-screen-drag-mode-line-1):
(touch-screen-drag-mode-line): New functions.
([mode-line touchscreen-begin]):
([bottom-divider touchscreen-begin]): Bind new events.
* lisp/wid-edit.el (widget-event-point):
(widget-keymap):
(widget-event-start):
(widget-button--check-and-call-button):
(widget-button-click): Improve touchscreen support.
* src/alloc.c (make_lisp_symbol): Avoid ICE on Android NDK GCC.
(mark_pinned_symbols): Likewise.
* src/android.c (struct android_emacs_window): New struct.
(window_class): New variable.
(android_run_select_thread): Add workaround for Android platform
bug.
(android_extract_long, android_scan_directory_tree): New
functions.
(android_file_access_p): Use those functions instead.
(android_init_emacs_window): New function.
(android_init_emacs_gc_class): Update signature of `markDirty'.
(android_change_gc, android_set_clip_rectangles): Tell the GC
whether or not clip rects were dirtied.
(android_swap_buffers): Do not look up method every time.
(struct android_dir): Adjust for new directory tree lookup.
(android_opendir, android_readdir, android_closedir): Likewise.
(android_four_corners_bilinear): Fix coding style.
(android_ftruncate): New function.
* src/android.h: Update prototypes. Replace ftruncate with
android_ftruncate when necessary.
* src/androidterm.c (handle_one_android_event): Pacify GCC. Fix
touch screen tool bar bug.
* src/emacs.c (using_utf8): Fix compilation error.
* src/fileio.c (Ffile_system_info): Return Qnil when fsusage.o
is not built.
* src/filelock.c (BOOT_TIME_FILE): Fix definition for Android.
* src/frame.c (Fx_parse_geometry): Fix uninitialized variable
uses.
* src/keyboard.c (lispy_function_keys): Fix `back'.
* src/menu.c (x_popup_menu_1): Handle touch screen events.
(Fx_popup_menu): Document changes.
* src/sfnt.c (main): Improve tests.
* src/sfntfont-android.c (sfntfont_android_put_glyphs): Fix
minor problem.
(init_sfntfont_android): Check for
HAVE_DECL_ANDROID_GET_DEVICE_API_LEVEL.
* src/sfntfont.c (struct sfnt_font_desc): New fields `adstyle'
and `languages'.
(sfnt_parse_style): Append tokens to adstyle.
(sfnt_parse_languages): New function.
(sfnt_enum_font_1): Parse supported languages and adstyle.
(sfntfont_list_1): Handle new fields.
(sfntfont_text_extents): Fix uninitialized variable use.
(syms_of_sfntfont, mark_sfntfont): Adjust accordingly.
Diffstat (limited to 'src/android.c')
| -rw-r--r-- | src/android.c | 569 |
1 files changed, 455 insertions, 114 deletions
diff --git a/src/android.c b/src/android.c index cfb79045c0b..eb9c404f1a3 100644 --- a/src/android.c +++ b/src/android.c | |||
| @@ -54,6 +54,9 @@ bool android_init_gui; | |||
| 54 | #include <android/log.h> | 54 | #include <android/log.h> |
| 55 | 55 | ||
| 56 | #include <linux/ashmem.h> | 56 | #include <linux/ashmem.h> |
| 57 | #include <linux/unistd.h> | ||
| 58 | |||
| 59 | #include <sys/syscall.h> | ||
| 57 | 60 | ||
| 58 | #define ANDROID_THROW(env, class, msg) \ | 61 | #define ANDROID_THROW(env, class, msg) \ |
| 59 | ((*(env))->ThrowNew ((env), (*(env))->FindClass ((env), class), msg)) | 62 | ((*(env))->ThrowNew ((env), (*(env))->FindClass ((env), class), msg)) |
| @@ -114,6 +117,12 @@ struct android_emacs_drawable | |||
| 114 | jmethodID damage_rect; | 117 | jmethodID damage_rect; |
| 115 | }; | 118 | }; |
| 116 | 119 | ||
| 120 | struct android_emacs_window | ||
| 121 | { | ||
| 122 | jclass class; | ||
| 123 | jmethodID swap_buffers; | ||
| 124 | }; | ||
| 125 | |||
| 117 | /* The asset manager being used. */ | 126 | /* The asset manager being used. */ |
| 118 | static AAssetManager *asset_manager; | 127 | static AAssetManager *asset_manager; |
| 119 | 128 | ||
| @@ -181,6 +190,9 @@ static struct android_graphics_point point_class; | |||
| 181 | /* Various methods associated with the EmacsDrawable class. */ | 190 | /* Various methods associated with the EmacsDrawable class. */ |
| 182 | static struct android_emacs_drawable drawable_class; | 191 | static struct android_emacs_drawable drawable_class; |
| 183 | 192 | ||
| 193 | /* Various methods associated with the EmacsWindow class. */ | ||
| 194 | static struct android_emacs_window window_class; | ||
| 195 | |||
| 184 | 196 | ||
| 185 | 197 | ||
| 186 | /* Event handling functions. Events are stored on a (circular) queue | 198 | /* Event handling functions. Events are stored on a (circular) queue |
| @@ -247,10 +259,21 @@ android_run_select_thread (void *data) | |||
| 247 | 259 | ||
| 248 | sigfillset (&signals); | 260 | sigfillset (&signals); |
| 249 | 261 | ||
| 262 | #if __ANDROID_API__ < 16 | ||
| 263 | /* sigprocmask must be used instead of pthread_sigmask due to a bug | ||
| 264 | in Android versions earlier than 16. It only affects the calling | ||
| 265 | thread on Android anyhow. */ | ||
| 266 | |||
| 267 | if (sigprocmask (SIG_BLOCK, &signals, NULL)) | ||
| 268 | __android_log_print (ANDROID_LOG_FATAL, __func__, | ||
| 269 | "sigprocmask: %s", | ||
| 270 | strerror (errno)); | ||
| 271 | #else | ||
| 250 | if (pthread_sigmask (SIG_BLOCK, &signals, NULL)) | 272 | if (pthread_sigmask (SIG_BLOCK, &signals, NULL)) |
| 251 | __android_log_print (ANDROID_LOG_FATAL, __func__, | 273 | __android_log_print (ANDROID_LOG_FATAL, __func__, |
| 252 | "pthread_sigmask: %s", | 274 | "pthread_sigmask: %s", |
| 253 | strerror (errno)); | 275 | strerror (errno)); |
| 276 | #endif | ||
| 254 | 277 | ||
| 255 | sigdelset (&signals, SIGUSR1); | 278 | sigdelset (&signals, SIGUSR1); |
| 256 | sigemptyset (&waitset); | 279 | sigemptyset (&waitset); |
| @@ -292,6 +315,8 @@ android_run_select_thread (void *data) | |||
| 292 | still be locked, so this must come before. */ | 315 | still be locked, so this must come before. */ |
| 293 | sem_post (&android_pselect_sem); | 316 | sem_post (&android_pselect_sem); |
| 294 | } | 317 | } |
| 318 | |||
| 319 | return NULL; | ||
| 295 | } | 320 | } |
| 296 | 321 | ||
| 297 | static void | 322 | static void |
| @@ -538,6 +563,200 @@ android_run_debug_thread (void *data) | |||
| 538 | 563 | ||
| 539 | 564 | ||
| 540 | 565 | ||
| 566 | /* Asset directory handling functions. ``directory-tree'' is a file in | ||
| 567 | the root of the assets directory describing its contents. | ||
| 568 | |||
| 569 | See lib-src/asset-directory-tool for more details. */ | ||
| 570 | |||
| 571 | /* The Android directory tree. */ | ||
| 572 | static const char *directory_tree; | ||
| 573 | |||
| 574 | /* The size of the directory tree. */ | ||
| 575 | static size_t directory_tree_size; | ||
| 576 | |||
| 577 | /* Read an unaligned (32-bit) long from the address POINTER. */ | ||
| 578 | |||
| 579 | static unsigned int | ||
| 580 | android_extract_long (char *pointer) | ||
| 581 | { | ||
| 582 | unsigned int number; | ||
| 583 | |||
| 584 | memcpy (&number, pointer, sizeof number); | ||
| 585 | return number; | ||
| 586 | } | ||
| 587 | |||
| 588 | /* Scan to the file FILE in the asset directory tree. Return a | ||
| 589 | pointer to the end of that file (immediately before any children) | ||
| 590 | in the directory tree, or NULL if that file does not exist. | ||
| 591 | |||
| 592 | If returning non-NULL, also return the offset to the end of the | ||
| 593 | last subdirectory or file in *LIMIT_RETURN. LIMIT_RETURN may be | ||
| 594 | NULL. | ||
| 595 | |||
| 596 | FILE must have less than 11 levels of nesting. If it ends with a | ||
| 597 | trailing slash, then NULL will be returned if it is not actually a | ||
| 598 | directory. */ | ||
| 599 | |||
| 600 | static const char * | ||
| 601 | android_scan_directory_tree (char *file, size_t *limit_return) | ||
| 602 | { | ||
| 603 | char *token, *saveptr, *copy, *copy1, *start, *max, *limit; | ||
| 604 | size_t token_length, ntokens, i; | ||
| 605 | char *tokens[10]; | ||
| 606 | |||
| 607 | USE_SAFE_ALLOCA; | ||
| 608 | |||
| 609 | /* Skip past the 5 byte header. */ | ||
| 610 | start = (char *) directory_tree + 5; | ||
| 611 | |||
| 612 | /* Figure out the current limit. */ | ||
| 613 | limit = (char *) directory_tree + directory_tree_size; | ||
| 614 | |||
| 615 | /* Now, split `file' into tokens, with the delimiter being the file | ||
| 616 | name separator. Look for the file and seek past it. */ | ||
| 617 | |||
| 618 | ntokens = 0; | ||
| 619 | saveptr = NULL; | ||
| 620 | copy = copy1 = xstrdup (file); | ||
| 621 | memset (tokens, 0, sizeof tokens); | ||
| 622 | |||
| 623 | while ((token = strtok_r (copy, "/", &saveptr))) | ||
| 624 | { | ||
| 625 | copy = NULL; | ||
| 626 | |||
| 627 | /* Make sure ntokens is within bounds. */ | ||
| 628 | if (ntokens == ARRAYELTS (tokens)) | ||
| 629 | { | ||
| 630 | xfree (copy1); | ||
| 631 | goto fail; | ||
| 632 | } | ||
| 633 | |||
| 634 | tokens[ntokens] = SAFE_ALLOCA (strlen (token) + 1); | ||
| 635 | memcpy (tokens[ntokens], token, strlen (token) + 1); | ||
| 636 | ntokens++; | ||
| 637 | } | ||
| 638 | |||
| 639 | /* Free the copy created for strtok_r. */ | ||
| 640 | xfree (copy1); | ||
| 641 | |||
| 642 | /* If there are no tokens, just return the start of the directory | ||
| 643 | tree. */ | ||
| 644 | if (!ntokens) | ||
| 645 | { | ||
| 646 | SAFE_FREE (); | ||
| 647 | |||
| 648 | /* Subtract the initial header bytes. */ | ||
| 649 | if (limit_return) | ||
| 650 | *limit_return = directory_tree_size - 5; | ||
| 651 | |||
| 652 | return start; | ||
| 653 | } | ||
| 654 | |||
| 655 | /* Loop through tokens, indexing the directory tree each time. */ | ||
| 656 | |||
| 657 | for (i = 0; i < ntokens; ++i) | ||
| 658 | { | ||
| 659 | token = tokens[i]; | ||
| 660 | |||
| 661 | /* Figure out how many bytes to compare. */ | ||
| 662 | token_length = strlen (token); | ||
| 663 | |||
| 664 | again: | ||
| 665 | |||
| 666 | /* If this would be past the directory, return NULL. */ | ||
| 667 | if (start + token_length > limit) | ||
| 668 | goto fail; | ||
| 669 | |||
| 670 | /* Now compare the file name. */ | ||
| 671 | if (!memcmp (start, token, token_length)) | ||
| 672 | { | ||
| 673 | /* They probably match. Find the NULL byte. It must be | ||
| 674 | either one byte past start + token_length, with the last | ||
| 675 | byte a trailing slash (indicating that it is a | ||
| 676 | directory), or just start + token_length. Return 4 bytes | ||
| 677 | past the next NULL byte. */ | ||
| 678 | |||
| 679 | max = memchr (start, 0, limit - start); | ||
| 680 | |||
| 681 | if (max != start + token_length | ||
| 682 | && !(max == start + token_length + 1 | ||
| 683 | && *(max - 1) == '/')) | ||
| 684 | goto false_positive; | ||
| 685 | |||
| 686 | /* Return it if it exists and is in range, and this is the | ||
| 687 | last token. Otherwise, set it as start and the limit as | ||
| 688 | start + the offset and continue the loop. */ | ||
| 689 | |||
| 690 | if (max && max + 5 <= limit) | ||
| 691 | { | ||
| 692 | if (i < ntokens - 1) | ||
| 693 | { | ||
| 694 | start = max + 5; | ||
| 695 | limit = ((char *) directory_tree | ||
| 696 | + android_extract_long (max + 1)); | ||
| 697 | |||
| 698 | /* Make sure limit is still in range. */ | ||
| 699 | if (limit > directory_tree + directory_tree_size | ||
| 700 | || start > directory_tree + directory_tree_size) | ||
| 701 | goto fail; | ||
| 702 | |||
| 703 | continue; | ||
| 704 | } | ||
| 705 | |||
| 706 | /* Now see if max is not a directory and file is. If | ||
| 707 | file is a directory, then return NULL. */ | ||
| 708 | if (*(max - 1) != '/' && file[strlen (file) - 1] == '/') | ||
| 709 | max = NULL; | ||
| 710 | else | ||
| 711 | { | ||
| 712 | /* Figure out the limit. */ | ||
| 713 | if (limit_return) | ||
| 714 | *limit_return = android_extract_long (max + 1); | ||
| 715 | |||
| 716 | /* Go to the end of this file. */ | ||
| 717 | max += 5; | ||
| 718 | } | ||
| 719 | |||
| 720 | SAFE_FREE (); | ||
| 721 | return max; | ||
| 722 | } | ||
| 723 | |||
| 724 | /* Return NULL otherwise. */ | ||
| 725 | __android_log_print (ANDROID_LOG_WARN, __func__, | ||
| 726 | "could not scan to end of directory tree" | ||
| 727 | ": %s", file); | ||
| 728 | goto fail; | ||
| 729 | } | ||
| 730 | |||
| 731 | false_positive: | ||
| 732 | |||
| 733 | /* No match was found. Set start to the next sibling and try | ||
| 734 | again. */ | ||
| 735 | |||
| 736 | start = memchr (start, 0, limit - start); | ||
| 737 | |||
| 738 | if (!start || start + 5 > limit) | ||
| 739 | goto fail; | ||
| 740 | |||
| 741 | start = ((char *) directory_tree | ||
| 742 | + android_extract_long (start + 1)); | ||
| 743 | |||
| 744 | /* Make sure start is still in bounds. */ | ||
| 745 | |||
| 746 | if (start > limit) | ||
| 747 | goto fail; | ||
| 748 | |||
| 749 | /* Continue the loop. */ | ||
| 750 | goto again; | ||
| 751 | } | ||
| 752 | |||
| 753 | fail: | ||
| 754 | SAFE_FREE (); | ||
| 755 | return NULL; | ||
| 756 | } | ||
| 757 | |||
| 758 | |||
| 759 | |||
| 541 | /* Intercept USER_FULL_NAME and return something that makes sense if | 760 | /* Intercept USER_FULL_NAME and return something that makes sense if |
| 542 | pw->pw_gecos is NULL. */ | 761 | pw->pw_gecos is NULL. */ |
| 543 | 762 | ||
| @@ -624,10 +843,6 @@ android_fstatat (int dirfd, const char *restrict pathname, | |||
| 624 | bool | 843 | bool |
| 625 | android_file_access_p (const char *name, int amode) | 844 | android_file_access_p (const char *name, int amode) |
| 626 | { | 845 | { |
| 627 | AAsset *asset; | ||
| 628 | AAssetDir *directory; | ||
| 629 | int length; | ||
| 630 | |||
| 631 | if (!asset_manager) | 846 | if (!asset_manager) |
| 632 | return false; | 847 | return false; |
| 633 | 848 | ||
| @@ -637,50 +852,11 @@ android_file_access_p (const char *name, int amode) | |||
| 637 | /* /assets always exists. */ | 852 | /* /assets always exists. */ |
| 638 | return true; | 853 | return true; |
| 639 | 854 | ||
| 640 | /* Check if the asset exists by opening it. Suboptimal! */ | 855 | /* Check if the file exists by looking in the ``directory tree'' |
| 641 | asset = AAssetManager_open (asset_manager, name, | 856 | asset generated during the build process. This is used |
| 642 | AASSET_MODE_UNKNOWN); | 857 | instead of the AAsset functions, because the latter are |
| 643 | 858 | buggy and treat directories inconsistently. */ | |
| 644 | if (!asset) | 859 | return android_scan_directory_tree ((char *) name, NULL) != NULL; |
| 645 | { | ||
| 646 | /* See if it's a directory as well. To open a directory | ||
| 647 | with the asset manager, the trailing slash (if specified) | ||
| 648 | must be removed. */ | ||
| 649 | directory = AAssetManager_openDir (asset_manager, name); | ||
| 650 | |||
| 651 | if (directory) | ||
| 652 | { | ||
| 653 | /* Make sure the directory actually has files in it. */ | ||
| 654 | |||
| 655 | if (!AAssetDir_getNextFileName (directory)) | ||
| 656 | { | ||
| 657 | AAssetDir_close (directory); | ||
| 658 | errno = ENOENT; | ||
| 659 | return false; | ||
| 660 | } | ||
| 661 | |||
| 662 | AAssetDir_close (directory); | ||
| 663 | return true; | ||
| 664 | } | ||
| 665 | |||
| 666 | errno = ENOENT; | ||
| 667 | return false; | ||
| 668 | } | ||
| 669 | |||
| 670 | AAsset_close (asset); | ||
| 671 | |||
| 672 | /* If NAME is a directory name, but it was a regular file, set | ||
| 673 | errno to ENOTDIR and return false. This is to behave like | ||
| 674 | faccessat. */ | ||
| 675 | |||
| 676 | length = strlen (name); | ||
| 677 | if (name[length - 1] == '/') | ||
| 678 | { | ||
| 679 | errno = ENOTDIR; | ||
| 680 | return false; | ||
| 681 | } | ||
| 682 | |||
| 683 | return true; | ||
| 684 | } | 860 | } |
| 685 | 861 | ||
| 686 | return false; | 862 | return false; |
| @@ -908,8 +1084,13 @@ android_get_home_directory (void) | |||
| 908 | 1084 | ||
| 909 | /* JNI functions called by Java. */ | 1085 | /* JNI functions called by Java. */ |
| 910 | 1086 | ||
| 1087 | #ifdef __clang__ | ||
| 911 | #pragma clang diagnostic push | 1088 | #pragma clang diagnostic push |
| 912 | #pragma clang diagnostic ignored "-Wmissing-prototypes" | 1089 | #pragma clang diagnostic ignored "-Wmissing-prototypes" |
| 1090 | #else | ||
| 1091 | #pragma GCC diagnostic push | ||
| 1092 | #pragma GCC diagnostic ignored "-Wmissing-prototypes" | ||
| 1093 | #endif | ||
| 913 | 1094 | ||
| 914 | JNIEXPORT void JNICALL | 1095 | JNIEXPORT void JNICALL |
| 915 | NATIVE_NAME (setEmacsParams) (JNIEnv *env, jobject object, | 1096 | NATIVE_NAME (setEmacsParams) (JNIEnv *env, jobject object, |
| @@ -923,6 +1104,7 @@ NATIVE_NAME (setEmacsParams) (JNIEnv *env, jobject object, | |||
| 923 | int pipefd[2]; | 1104 | int pipefd[2]; |
| 924 | pthread_t thread; | 1105 | pthread_t thread; |
| 925 | const char *java_string; | 1106 | const char *java_string; |
| 1107 | AAsset *asset; | ||
| 926 | 1108 | ||
| 927 | /* This may be called from multiple threads. setEmacsParams should | 1109 | /* This may be called from multiple threads. setEmacsParams should |
| 928 | only ever be called once. */ | 1110 | only ever be called once. */ |
| @@ -943,6 +1125,33 @@ NATIVE_NAME (setEmacsParams) (JNIEnv *env, jobject object, | |||
| 943 | /* Set the asset manager. */ | 1125 | /* Set the asset manager. */ |
| 944 | asset_manager = AAssetManager_fromJava (env, local_asset_manager); | 1126 | asset_manager = AAssetManager_fromJava (env, local_asset_manager); |
| 945 | 1127 | ||
| 1128 | /* Initialize the directory tree. */ | ||
| 1129 | asset = AAssetManager_open (asset_manager, "directory-tree", | ||
| 1130 | AASSET_MODE_BUFFER); | ||
| 1131 | |||
| 1132 | if (!asset) | ||
| 1133 | { | ||
| 1134 | __android_log_print (ANDROID_LOG_FATAL, __func__, | ||
| 1135 | "Failed to open directory tree"); | ||
| 1136 | emacs_abort (); | ||
| 1137 | } | ||
| 1138 | |||
| 1139 | directory_tree = AAsset_getBuffer (asset); | ||
| 1140 | |||
| 1141 | if (!directory_tree) | ||
| 1142 | emacs_abort (); | ||
| 1143 | |||
| 1144 | /* Now figure out how big the directory tree is, and compare the | ||
| 1145 | first few bytes. */ | ||
| 1146 | directory_tree_size = AAsset_getLength (asset); | ||
| 1147 | if (directory_tree_size < 5 | ||
| 1148 | || memcmp (directory_tree, "EMACS", 5)) | ||
| 1149 | { | ||
| 1150 | __android_log_print (ANDROID_LOG_FATAL, __func__, | ||
| 1151 | "Directory tree has bad magic"); | ||
| 1152 | emacs_abort (); | ||
| 1153 | } | ||
| 1154 | |||
| 946 | /* Hold a VM reference to the asset manager to prevent the native | 1155 | /* Hold a VM reference to the asset manager to prevent the native |
| 947 | object from being deleted. */ | 1156 | object from being deleted. */ |
| 948 | (*env)->NewGlobalRef (env, local_asset_manager); | 1157 | (*env)->NewGlobalRef (env, local_asset_manager); |
| @@ -1199,6 +1408,36 @@ android_init_emacs_drawable (void) | |||
| 1199 | #undef FIND_METHOD | 1408 | #undef FIND_METHOD |
| 1200 | } | 1409 | } |
| 1201 | 1410 | ||
| 1411 | static void | ||
| 1412 | android_init_emacs_window (void) | ||
| 1413 | { | ||
| 1414 | jclass old; | ||
| 1415 | |||
| 1416 | window_class.class | ||
| 1417 | = (*android_java_env)->FindClass (android_java_env, | ||
| 1418 | "org/gnu/emacs/EmacsWindow"); | ||
| 1419 | eassert (window_class.class); | ||
| 1420 | |||
| 1421 | old = window_class.class; | ||
| 1422 | window_class.class | ||
| 1423 | = (jclass) (*android_java_env)->NewGlobalRef (android_java_env, | ||
| 1424 | (jobject) old); | ||
| 1425 | ANDROID_DELETE_LOCAL_REF (old); | ||
| 1426 | |||
| 1427 | if (!window_class.class) | ||
| 1428 | emacs_abort (); | ||
| 1429 | |||
| 1430 | #define FIND_METHOD(c_name, name, signature) \ | ||
| 1431 | window_class.c_name \ | ||
| 1432 | = (*android_java_env)->GetMethodID (android_java_env, \ | ||
| 1433 | window_class.class, \ | ||
| 1434 | name, signature); \ | ||
| 1435 | assert (window_class.c_name); | ||
| 1436 | |||
| 1437 | FIND_METHOD (swap_buffers, "swapBuffers", "()V"); | ||
| 1438 | #undef FIND_METHOD | ||
| 1439 | } | ||
| 1440 | |||
| 1202 | extern JNIEXPORT void JNICALL | 1441 | extern JNIEXPORT void JNICALL |
| 1203 | NATIVE_NAME (initEmacs) (JNIEnv *env, jobject object, jarray argv) | 1442 | NATIVE_NAME (initEmacs) (JNIEnv *env, jobject object, jarray argv) |
| 1204 | { | 1443 | { |
| @@ -1232,6 +1471,7 @@ NATIVE_NAME (initEmacs) (JNIEnv *env, jobject object, jarray argv) | |||
| 1232 | android_init_emacs_pixmap (); | 1471 | android_init_emacs_pixmap (); |
| 1233 | android_init_graphics_point (); | 1472 | android_init_graphics_point (); |
| 1234 | android_init_emacs_drawable (); | 1473 | android_init_emacs_drawable (); |
| 1474 | android_init_emacs_window (); | ||
| 1235 | 1475 | ||
| 1236 | /* Set HOME to the app data directory. */ | 1476 | /* Set HOME to the app data directory. */ |
| 1237 | setenv ("HOME", android_files_dir, 1); | 1477 | setenv ("HOME", android_files_dir, 1); |
| @@ -1545,7 +1785,11 @@ NATIVE_NAME (sendContextMenu) (JNIEnv *env, jobject object, | |||
| 1545 | android_write_event (&event); | 1785 | android_write_event (&event); |
| 1546 | } | 1786 | } |
| 1547 | 1787 | ||
| 1788 | #ifdef __clang__ | ||
| 1548 | #pragma clang diagnostic pop | 1789 | #pragma clang diagnostic pop |
| 1790 | #else | ||
| 1791 | #pragma GCC diagnostic pop | ||
| 1792 | #endif | ||
| 1549 | 1793 | ||
| 1550 | 1794 | ||
| 1551 | 1795 | ||
| @@ -1557,8 +1801,6 @@ NATIVE_NAME (sendContextMenu) (JNIEnv *env, jobject object, | |||
| 1557 | This means that every local reference must be explicitly destroyed | 1801 | This means that every local reference must be explicitly destroyed |
| 1558 | with DeleteLocalRef. A helper macro is provided to do this. */ | 1802 | with DeleteLocalRef. A helper macro is provided to do this. */ |
| 1559 | 1803 | ||
| 1560 | #define MAX_HANDLE 65535 | ||
| 1561 | |||
| 1562 | struct android_handle_entry | 1804 | struct android_handle_entry |
| 1563 | { | 1805 | { |
| 1564 | /* The type. */ | 1806 | /* The type. */ |
| @@ -1883,7 +2125,7 @@ android_init_emacs_gc_class (void) | |||
| 1883 | emacs_gc_mark_dirty | 2125 | emacs_gc_mark_dirty |
| 1884 | = (*android_java_env)->GetMethodID (android_java_env, | 2126 | = (*android_java_env)->GetMethodID (android_java_env, |
| 1885 | emacs_gc_class, | 2127 | emacs_gc_class, |
| 1886 | "markDirty", "()V"); | 2128 | "markDirty", "(Z)V"); |
| 1887 | assert (emacs_gc_mark_dirty); | 2129 | assert (emacs_gc_mark_dirty); |
| 1888 | 2130 | ||
| 1889 | old = emacs_gc_class; | 2131 | old = emacs_gc_class; |
| @@ -2011,6 +2253,9 @@ android_change_gc (struct android_gc *gc, | |||
| 2011 | struct android_gc_values *values) | 2253 | struct android_gc_values *values) |
| 2012 | { | 2254 | { |
| 2013 | jobject what, gcontext; | 2255 | jobject what, gcontext; |
| 2256 | jboolean clip_changed; | ||
| 2257 | |||
| 2258 | clip_changed = false; | ||
| 2014 | 2259 | ||
| 2015 | android_init_emacs_gc_class (); | 2260 | android_init_emacs_gc_class (); |
| 2016 | gcontext = android_resolve_handle (gc->gcontext, | 2261 | gcontext = android_resolve_handle (gc->gcontext, |
| @@ -2041,16 +2286,22 @@ android_change_gc (struct android_gc *gc, | |||
| 2041 | values->function); | 2286 | values->function); |
| 2042 | 2287 | ||
| 2043 | if (mask & ANDROID_GC_CLIP_X_ORIGIN) | 2288 | if (mask & ANDROID_GC_CLIP_X_ORIGIN) |
| 2044 | (*android_java_env)->SetIntField (android_java_env, | 2289 | { |
| 2045 | gcontext, | 2290 | (*android_java_env)->SetIntField (android_java_env, |
| 2046 | emacs_gc_clip_x_origin, | 2291 | gcontext, |
| 2047 | values->clip_x_origin); | 2292 | emacs_gc_clip_x_origin, |
| 2293 | values->clip_x_origin); | ||
| 2294 | clip_changed = true; | ||
| 2295 | } | ||
| 2048 | 2296 | ||
| 2049 | if (mask & ANDROID_GC_CLIP_Y_ORIGIN) | 2297 | if (mask & ANDROID_GC_CLIP_Y_ORIGIN) |
| 2050 | (*android_java_env)->SetIntField (android_java_env, | 2298 | { |
| 2051 | gcontext, | 2299 | (*android_java_env)->SetIntField (android_java_env, |
| 2052 | emacs_gc_clip_y_origin, | 2300 | gcontext, |
| 2053 | values->clip_y_origin); | 2301 | emacs_gc_clip_y_origin, |
| 2302 | values->clip_y_origin); | ||
| 2303 | clip_changed = true; | ||
| 2304 | } | ||
| 2054 | 2305 | ||
| 2055 | if (mask & ANDROID_GC_CLIP_MASK) | 2306 | if (mask & ANDROID_GC_CLIP_MASK) |
| 2056 | { | 2307 | { |
| @@ -2070,6 +2321,7 @@ android_change_gc (struct android_gc *gc, | |||
| 2070 | xfree (gc->clip_rects); | 2321 | xfree (gc->clip_rects); |
| 2071 | gc->clip_rects = NULL; | 2322 | gc->clip_rects = NULL; |
| 2072 | gc->num_clip_rects = -1; | 2323 | gc->num_clip_rects = -1; |
| 2324 | clip_changed = true; | ||
| 2073 | } | 2325 | } |
| 2074 | 2326 | ||
| 2075 | if (mask & ANDROID_GC_STIPPLE) | 2327 | if (mask & ANDROID_GC_STIPPLE) |
| @@ -2103,7 +2355,8 @@ android_change_gc (struct android_gc *gc, | |||
| 2103 | if (mask) | 2355 | if (mask) |
| 2104 | (*android_java_env)->CallVoidMethod (android_java_env, | 2356 | (*android_java_env)->CallVoidMethod (android_java_env, |
| 2105 | gcontext, | 2357 | gcontext, |
| 2106 | emacs_gc_mark_dirty); | 2358 | emacs_gc_mark_dirty, |
| 2359 | (jboolean) clip_changed); | ||
| 2107 | } | 2360 | } |
| 2108 | 2361 | ||
| 2109 | void | 2362 | void |
| @@ -2174,7 +2427,8 @@ android_set_clip_rectangles (struct android_gc *gc, int clip_x_origin, | |||
| 2174 | 2427 | ||
| 2175 | (*android_java_env)->CallVoidMethod (android_java_env, | 2428 | (*android_java_env)->CallVoidMethod (android_java_env, |
| 2176 | gcontext, | 2429 | gcontext, |
| 2177 | emacs_gc_mark_dirty); | 2430 | emacs_gc_mark_dirty, |
| 2431 | (jboolean) true); | ||
| 2178 | 2432 | ||
| 2179 | /* Cache the clip rectangles on the C side for | 2433 | /* Cache the clip rectangles on the C side for |
| 2180 | sfntfont-android.c. */ | 2434 | sfntfont-android.c. */ |
| @@ -2327,18 +2581,15 @@ android_swap_buffers (struct android_swap_info *swap_info, | |||
| 2327 | int num_windows) | 2581 | int num_windows) |
| 2328 | { | 2582 | { |
| 2329 | jobject window; | 2583 | jobject window; |
| 2330 | jmethodID swap_buffers; | ||
| 2331 | int i; | 2584 | int i; |
| 2332 | 2585 | ||
| 2333 | swap_buffers = android_lookup_method ("org/gnu/emacs/EmacsWindow", | ||
| 2334 | "swapBuffers", "()V"); | ||
| 2335 | |||
| 2336 | for (i = 0; i < num_windows; ++i) | 2586 | for (i = 0; i < num_windows; ++i) |
| 2337 | { | 2587 | { |
| 2338 | window = android_resolve_handle (swap_info[i].swap_window, | 2588 | window = android_resolve_handle (swap_info[i].swap_window, |
| 2339 | ANDROID_HANDLE_WINDOW); | 2589 | ANDROID_HANDLE_WINDOW); |
| 2340 | (*android_java_env)->CallVoidMethod (android_java_env, | 2590 | (*android_java_env)->CallVoidMethod (android_java_env, |
| 2341 | window, swap_buffers); | 2591 | window, |
| 2592 | window_class.swap_buffers); | ||
| 2342 | } | 2593 | } |
| 2343 | } | 2594 | } |
| 2344 | 2595 | ||
| @@ -3555,11 +3806,17 @@ android_sync (void) | |||
| 3555 | 3806 | ||
| 3556 | 3807 | ||
| 3557 | 3808 | ||
| 3809 | #if __ANDROID_API__ >= 17 | ||
| 3810 | |||
| 3558 | #undef faccessat | 3811 | #undef faccessat |
| 3559 | 3812 | ||
| 3560 | /* Replace the system faccessat with one which understands AT_EACCESS. | 3813 | /* Replace the system faccessat with one which understands AT_EACCESS. |
| 3561 | Android's faccessat simply fails upon using AT_EACCESS, so repalce | 3814 | Android's faccessat simply fails upon using AT_EACCESS, so repalce |
| 3562 | it with zero here. This isn't caught during configuration. */ | 3815 | it with zero here. This isn't caught during configuration. |
| 3816 | |||
| 3817 | This replacement is only done when building for Android 17 or | ||
| 3818 | later, because earlier versions use the gnulib replacement that | ||
| 3819 | lacks these issues. */ | ||
| 3563 | 3820 | ||
| 3564 | int | 3821 | int |
| 3565 | faccessat (int dirfd, const char *pathname, int mode, int flags) | 3822 | faccessat (int dirfd, const char *pathname, int mode, int flags) |
| @@ -3572,6 +3829,8 @@ faccessat (int dirfd, const char *pathname, int mode, int flags) | |||
| 3572 | return real_faccessat (dirfd, pathname, mode, flags & ~AT_EACCESS); | 3829 | return real_faccessat (dirfd, pathname, mode, flags & ~AT_EACCESS); |
| 3573 | } | 3830 | } |
| 3574 | 3831 | ||
| 3832 | #endif /* __ANDROID_API__ < 16 */ | ||
| 3833 | |||
| 3575 | 3834 | ||
| 3576 | 3835 | ||
| 3577 | /* Directory listing emulation. */ | 3836 | /* Directory listing emulation. */ |
| @@ -3581,8 +3840,11 @@ struct android_dir | |||
| 3581 | /* The real DIR *, if it exists. */ | 3840 | /* The real DIR *, if it exists. */ |
| 3582 | DIR *dir; | 3841 | DIR *dir; |
| 3583 | 3842 | ||
| 3584 | /* Otherwise, the AAssetDir. */ | 3843 | /* Otherwise, the pointer to the directory in directory_tree. */ |
| 3585 | void *asset_dir; | 3844 | char *asset_dir; |
| 3845 | |||
| 3846 | /* And the end of the files in asset_dir. */ | ||
| 3847 | char *asset_limit; | ||
| 3586 | }; | 3848 | }; |
| 3587 | 3849 | ||
| 3588 | /* Like opendir. However, return an asset directory if NAME points to | 3850 | /* Like opendir. However, return an asset directory if NAME points to |
| @@ -3592,8 +3854,9 @@ struct android_dir * | |||
| 3592 | android_opendir (const char *name) | 3854 | android_opendir (const char *name) |
| 3593 | { | 3855 | { |
| 3594 | struct android_dir *dir; | 3856 | struct android_dir *dir; |
| 3595 | AAssetDir *asset_dir; | 3857 | char *asset_dir; |
| 3596 | const char *asset_name; | 3858 | const char *asset_name; |
| 3859 | size_t limit; | ||
| 3597 | 3860 | ||
| 3598 | asset_name = android_get_asset_name (name); | 3861 | asset_name = android_get_asset_name (name); |
| 3599 | 3862 | ||
| @@ -3601,8 +3864,9 @@ android_opendir (const char *name) | |||
| 3601 | directory. */ | 3864 | directory. */ |
| 3602 | if (asset_manager && asset_name) | 3865 | if (asset_manager && asset_name) |
| 3603 | { | 3866 | { |
| 3604 | asset_dir = AAssetManager_openDir (asset_manager, | 3867 | asset_dir |
| 3605 | asset_name); | 3868 | = (char *) android_scan_directory_tree ((char *) asset_name, |
| 3869 | &limit); | ||
| 3606 | 3870 | ||
| 3607 | if (!asset_dir) | 3871 | if (!asset_dir) |
| 3608 | { | 3872 | { |
| @@ -3613,6 +3877,20 @@ android_opendir (const char *name) | |||
| 3613 | dir = xmalloc (sizeof *dir); | 3877 | dir = xmalloc (sizeof *dir); |
| 3614 | dir->dir = NULL; | 3878 | dir->dir = NULL; |
| 3615 | dir->asset_dir = asset_dir; | 3879 | dir->asset_dir = asset_dir; |
| 3880 | dir->asset_limit = (char *) directory_tree + limit; | ||
| 3881 | |||
| 3882 | /* Make sure dir->asset_limit is within bounds. It is a limit, | ||
| 3883 | and as such can be exactly one byte past directory_tree. */ | ||
| 3884 | if (dir->asset_limit > directory_tree + directory_tree_size) | ||
| 3885 | { | ||
| 3886 | xfree (dir); | ||
| 3887 | __android_log_print (ANDROID_LOG_VERBOSE, __func__, | ||
| 3888 | "Invalid dir tree, limit %zu, size %zu\n", | ||
| 3889 | limit, directory_tree_size); | ||
| 3890 | dir = NULL; | ||
| 3891 | errno = EACCES; | ||
| 3892 | } | ||
| 3893 | |||
| 3616 | return dir; | 3894 | return dir; |
| 3617 | } | 3895 | } |
| 3618 | 3896 | ||
| @@ -3636,23 +3914,55 @@ struct dirent * | |||
| 3636 | android_readdir (struct android_dir *dir) | 3914 | android_readdir (struct android_dir *dir) |
| 3637 | { | 3915 | { |
| 3638 | static struct dirent dirent; | 3916 | static struct dirent dirent; |
| 3639 | const char *filename; | 3917 | const char *last; |
| 3640 | 3918 | ||
| 3641 | if (dir->asset_dir) | 3919 | if (dir->asset_dir) |
| 3642 | { | 3920 | { |
| 3643 | filename = AAssetDir_getNextFileName (dir->asset_dir); | 3921 | /* There are no more files to read. */ |
| 3644 | errno = 0; | 3922 | if (dir->asset_dir >= dir->asset_limit) |
| 3923 | return NULL; | ||
| 3924 | |||
| 3925 | /* Otherwise, scan forward looking for the next NULL byte. */ | ||
| 3926 | last = memchr (dir->asset_dir, 0, | ||
| 3927 | dir->asset_limit - dir->asset_dir); | ||
| 3928 | |||
| 3929 | /* No more NULL bytes remain. */ | ||
| 3930 | if (!last) | ||
| 3931 | return NULL; | ||
| 3932 | |||
| 3933 | /* Forward last past the NULL byte. */ | ||
| 3934 | last++; | ||
| 3645 | 3935 | ||
| 3646 | if (!filename) | 3936 | /* Make sure it is still within the directory tree. */ |
| 3937 | if (last >= directory_tree + directory_tree_size) | ||
| 3647 | return NULL; | 3938 | return NULL; |
| 3648 | 3939 | ||
| 3940 | /* Now, fill in the dirent with the name. */ | ||
| 3649 | memset (&dirent, 0, sizeof dirent); | 3941 | memset (&dirent, 0, sizeof dirent); |
| 3650 | dirent.d_ino = 0; | 3942 | dirent.d_ino = 0; |
| 3651 | dirent.d_off = 0; | 3943 | dirent.d_off = 0; |
| 3652 | dirent.d_reclen = sizeof dirent; | 3944 | dirent.d_reclen = sizeof dirent; |
| 3653 | dirent.d_type = DT_UNKNOWN; | 3945 | dirent.d_type = DT_UNKNOWN; |
| 3654 | strncpy (dirent.d_name, filename, | 3946 | |
| 3655 | sizeof dirent.d_name - 1); | 3947 | /* Note that dir->asset_dir is actually a NULL terminated |
| 3948 | string. */ | ||
| 3949 | memcpy (dirent.d_name, dir->asset_dir, | ||
| 3950 | MIN (sizeof dirent.d_name, | ||
| 3951 | last - dir->asset_dir)); | ||
| 3952 | dirent.d_name[sizeof dirent.d_name - 1] = '\0'; | ||
| 3953 | |||
| 3954 | /* Strip off the trailing slash, if any. */ | ||
| 3955 | if (dirent.d_name[MIN (sizeof dirent.d_name, | ||
| 3956 | last - dir->asset_dir) | ||
| 3957 | - 2] == '/') | ||
| 3958 | dirent.d_name[MIN (sizeof dirent.d_name, | ||
| 3959 | last - dir->asset_dir) | ||
| 3960 | - 2] = '\0'; | ||
| 3961 | |||
| 3962 | /* Finally, forward dir->asset_dir to the file past last. */ | ||
| 3963 | dir->asset_dir = ((char *) directory_tree | ||
| 3964 | + android_extract_long ((char *) last)); | ||
| 3965 | |||
| 3656 | return &dirent; | 3966 | return &dirent; |
| 3657 | } | 3967 | } |
| 3658 | 3968 | ||
| @@ -3666,8 +3976,9 @@ android_closedir (struct android_dir *dir) | |||
| 3666 | { | 3976 | { |
| 3667 | if (dir->dir) | 3977 | if (dir->dir) |
| 3668 | closedir (dir->dir); | 3978 | closedir (dir->dir); |
| 3669 | else | 3979 | |
| 3670 | AAssetDir_close (dir->asset_dir); | 3980 | /* There is no need to close anything else, as the directory tree |
| 3981 | lies in statically allocated memory. */ | ||
| 3671 | 3982 | ||
| 3672 | xfree (dir); | 3983 | xfree (dir); |
| 3673 | } | 3984 | } |
| @@ -3795,40 +4106,40 @@ android_four_corners_bilinear (unsigned int tl, unsigned int tr, | |||
| 3795 | unsigned int bl, unsigned int br, | 4106 | unsigned int bl, unsigned int br, |
| 3796 | int distx, int disty) | 4107 | int distx, int disty) |
| 3797 | { | 4108 | { |
| 3798 | int distxy, distxiy, distixy, distixiy; | 4109 | int distxy, distxiy, distixy, distixiy; |
| 3799 | uint32_t f, r; | 4110 | uint32_t f, r; |
| 3800 | 4111 | ||
| 3801 | distxy = distx * disty; | 4112 | distxy = distx * disty; |
| 3802 | distxiy = (distx << 8) - distxy; | 4113 | distxiy = (distx << 8) - distxy; |
| 3803 | distixy = (disty << 8) - distxy; | 4114 | distixy = (disty << 8) - distxy; |
| 3804 | distixiy = (256 * 256 - (disty << 8) | 4115 | distixiy = (256 * 256 - (disty << 8) |
| 3805 | - (distx << 8) + distxy); | 4116 | - (distx << 8) + distxy); |
| 3806 | 4117 | ||
| 3807 | /* Red */ | 4118 | /* Red */ |
| 3808 | r = ((tl & 0x000000ff) * distixiy + (tr & 0x000000ff) * distxiy | 4119 | r = ((tl & 0x000000ff) * distixiy + (tr & 0x000000ff) * distxiy |
| 3809 | + (bl & 0x000000ff) * distixy + (br & 0x000000ff) * distxy); | 4120 | + (bl & 0x000000ff) * distixy + (br & 0x000000ff) * distxy); |
| 3810 | 4121 | ||
| 3811 | /* Green */ | 4122 | /* Green */ |
| 3812 | f = ((tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy | 4123 | f = ((tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy |
| 3813 | + (bl & 0x0000ff00) * distixy + (br & 0x0000ff00) * distxy); | 4124 | + (bl & 0x0000ff00) * distixy + (br & 0x0000ff00) * distxy); |
| 3814 | r |= f & 0xff000000; | 4125 | r |= f & 0xff000000; |
| 3815 | 4126 | ||
| 3816 | /* Now do the upper two components. */ | 4127 | /* Now do the upper two components. */ |
| 3817 | tl >>= 16; | 4128 | tl >>= 16; |
| 3818 | tr >>= 16; | 4129 | tr >>= 16; |
| 3819 | bl >>= 16; | 4130 | bl >>= 16; |
| 3820 | br >>= 16; | 4131 | br >>= 16; |
| 3821 | r >>= 16; | 4132 | r >>= 16; |
| 3822 | 4133 | ||
| 3823 | /* Blue */ | 4134 | /* Blue */ |
| 3824 | f = ((tl & 0x000000ff) * distixiy + (tr & 0x000000ff) * distxiy | 4135 | f = ((tl & 0x000000ff) * distixiy + (tr & 0x000000ff) * distxiy |
| 3825 | + (bl & 0x000000ff) * distixy + (br & 0x000000ff) * distxy); | 4136 | + (bl & 0x000000ff) * distixy + (br & 0x000000ff) * distxy); |
| 3826 | r |= f & 0x00ff0000; | 4137 | r |= f & 0x00ff0000; |
| 3827 | 4138 | ||
| 3828 | /* Alpha */ | 4139 | /* Alpha */ |
| 3829 | f = ((tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy | 4140 | f = ((tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy |
| 3830 | + (bl & 0x0000ff00) * distixy + (br & 0x0000ff00) * distxy); | 4141 | + (bl & 0x0000ff00) * distixy + (br & 0x0000ff00) * distxy); |
| 3831 | r |= f & 0xff000000; | 4142 | r |= f & 0xff000000; |
| 3832 | 4143 | ||
| 3833 | return r; | 4144 | return r; |
| 3834 | } | 4145 | } |
| @@ -4010,6 +4321,36 @@ android_project_image_nearest (struct android_image *image, | |||
| 4010 | } | 4321 | } |
| 4011 | } | 4322 | } |
| 4012 | 4323 | ||
| 4324 | |||
| 4325 | |||
| 4326 | /* System call wrappers for stuff missing in bionic. */ | ||
| 4327 | |||
| 4328 | #ifndef HAVE_FTRUNCATE | ||
| 4329 | |||
| 4330 | /* ftruncate wrapper for Android, for systems without ftruncate in the | ||
| 4331 | C library. | ||
| 4332 | |||
| 4333 | Such systems are always 32 bit systems, since Android 21 and later | ||
| 4334 | all support ftruncate. In addition, ARM and MIPS require registers | ||
| 4335 | used to store long long parameters to be aligned to an even | ||
| 4336 | register pair. */ | ||
| 4337 | |||
| 4338 | int | ||
| 4339 | android_ftruncate (int fd, off_t length) | ||
| 4340 | { | ||
| 4341 | int rc; | ||
| 4342 | |||
| 4343 | #if defined __arm__ || defined __mips__ | ||
| 4344 | return syscall (SYS_ftruncate64, fd, 0, | ||
| 4345 | (unsigned int) (length & 0xffffffff), | ||
| 4346 | (unsigned int) (length >> 32)); | ||
| 4347 | #else | ||
| 4348 | return syscall (SYS_ftruncate64, fd, length); | ||
| 4349 | #endif | ||
| 4350 | } | ||
| 4351 | |||
| 4352 | #endif | ||
| 4353 | |||
| 4013 | #else /* ANDROID_STUBIFY */ | 4354 | #else /* ANDROID_STUBIFY */ |
| 4014 | 4355 | ||
| 4015 | /* X emulation functions for Android. */ | 4356 | /* X emulation functions for Android. */ |