1 /* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
2
3 Copyright (C) 2023 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or (at
10 your option) any later version.
11
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
19
20 package org.gnu.emacs;
21
22 import android.content.res.AssetManager;
23
24 import android.graphics.Bitmap;
25
26 import android.view.inputmethod.ExtractedText;
27 import android.view.inputmethod.ExtractedTextRequest;
28 import android.view.inputmethod.SurroundingText;
29 import android.view.inputmethod.TextSnapshot;
30
31 public final class EmacsNative
32 {
33 /* List of native libraries that must be loaded during class
34 initialization. */
35 private static final String[] libraryDeps;
36
37
38 /* Like `dup' in C. */
39 public static native int dup (int fd);
40
41 /* Obtain the fingerprint of this build of Emacs. The fingerprint
42 can be used to determine the dump file name. */
43 public static native String getFingerprint ();
44
45 /* Set certain parameters before initializing Emacs.
46
47 assetManager must be the asset manager associated with the
48 context that is loading Emacs. It is saved and remains for the
49 remainder the lifetime of the Emacs process.
50
51 filesDir must be the package's data storage location for the
52 current Android user.
53
54 libDir must be the package's data storage location for native
55 libraries. It is used as PATH.
56
57 cacheDir must be the package's cache directory. It is used as
58 the `temporary-file-directory'.
59
60 pixelDensityX and pixelDensityY are the DPI values that will be
61 used by Emacs.
62
63 scaledDensity is the DPI value used to translate point sizes to
64 pixel sizes when loading fonts.
65
66 classPath must be the classpath of this app_process process, or
67 NULL.
68
69 emacsService must be the EmacsService singleton, or NULL.
70
71 apiLevel is the version of Android being run. */
72 public static native void setEmacsParams (AssetManager assetManager,
73 String filesDir,
74 String libDir,
75 String cacheDir,
76 float pixelDensityX,
77 float pixelDensityY,
78 float scaledDensity,
79 String classPath,
80 EmacsService emacsService,
81 int apiLevel);
82
83 /* Initialize Emacs with the argument array ARGV. Each argument
84 must contain a NULL terminated string, or else the behavior is
85 undefined.
86
87 DUMPFILE is the dump file to use, or NULL if Emacs is to load
88 loadup.el itself. */
89 public static native void initEmacs (String argv[], String dumpFile);
90
91 /* Abort and generate a native core dump. */
92 public static native void emacsAbort ();
93
94 /* Set Vquit_flag to t, resulting in Emacs quitting as soon as
95 possible. */
96 public static native void quit ();
97
98 /* Send an ANDROID_CONFIGURE_NOTIFY event. The values of all the
99 functions below are the serials of the events sent. */
100 public static native long sendConfigureNotify (short window, long time,
101 int x, int y, int width,
102 int height);
103
104 /* Send an ANDROID_KEY_PRESS event. */
105 public static native long sendKeyPress (short window, long time, int state,
106 int keyCode, int unicodeChar);
107
108 /* Send an ANDROID_KEY_RELEASE event. */
109 public static native long sendKeyRelease (short window, long time, int state,
110 int keyCode, int unicodeChar);
111
112 /* Send an ANDROID_FOCUS_IN event. */
113 public static native long sendFocusIn (short window, long time);
114
115 /* Send an ANDROID_FOCUS_OUT event. */
116 public static native long sendFocusOut (short window, long time);
117
118 /* Send an ANDROID_WINDOW_ACTION event. */
119 public static native long sendWindowAction (short window, int action);
120
121 /* Send an ANDROID_ENTER_NOTIFY event. */
122 public static native long sendEnterNotify (short window, int x, int y,
123 long time);
124
125 /* Send an ANDROID_LEAVE_NOTIFY event. */
126 public static native long sendLeaveNotify (short window, int x, int y,
127 long time);
128
129 /* Send an ANDROID_MOTION_NOTIFY event. */
130 public static native long sendMotionNotify (short window, int x, int y,
131 long time);
132
133 /* Send an ANDROID_BUTTON_PRESS event. */
134 public static native long sendButtonPress (short window, int x, int y,
135 long time, int state,
136 int button);
137
138 /* Send an ANDROID_BUTTON_RELEASE event. */
139 public static native long sendButtonRelease (short window, int x, int y,
140 long time, int state,
141 int button);
142
143 /* Send an ANDROID_TOUCH_DOWN event. */
144 public static native long sendTouchDown (short window, int x, int y,
145 long time, int pointerID,
146 int flags);
147
148 /* Send an ANDROID_TOUCH_UP event. */
149 public static native long sendTouchUp (short window, int x, int y,
150 long time, int pointerID,
151 int flags);
152
153 /* Send an ANDROID_TOUCH_MOVE event. */
154 public static native long sendTouchMove (short window, int x, int y,
155 long time, int pointerID,
156 int flags);
157
158 /* Send an ANDROID_WHEEL event. */
159 public static native long sendWheel (short window, int x, int y,
160 long time, int state,
161 float xDelta, float yDelta);
162
163 /* Send an ANDROID_ICONIFIED event. */
164 public static native long sendIconified (short window);
165
166 /* Send an ANDROID_DEICONIFIED event. */
167 public static native long sendDeiconified (short window);
168
169 /* Send an ANDROID_CONTEXT_MENU event. */
170 public static native long sendContextMenu (short window, int menuEventID,
171 int menuEventSerial);
172
173 /* Send an ANDROID_EXPOSE event. */
174 public static native long sendExpose (short window, int x, int y,
175 int width, int height);
176
177 /* Return the file name associated with the specified file
178 descriptor, or NULL if there is none. */
179 public static native byte[] getProcName (int fd);
180
181 /* Notice that the Emacs thread will now start waiting for the main
182 thread's looper to respond. */
183 public static native void beginSynchronous ();
184
185 /* Notice that the Emacs thread will has finished waiting for the
186 main thread's looper to respond. */
187 public static native void endSynchronous ();
188
189 /* Prevent deadlocks while reliably allowing queries from the Emacs
190 thread to the main thread to complete by waiting for a query to
191 start from the main thread, then answer it; assume that a query
192 is certain to start shortly. */
193 public static native void answerQuerySpin ();
194
195 /* Return whether or not KEYCODE_VOLUME_DOWN, KEYCODE_VOLUME_UP and
196 KEYCODE_VOLUME_MUTE should be forwarded to Emacs. */
197 public static native boolean shouldForwardMultimediaButtons ();
198
199 /* Initialize the current thread, by blocking signals that do not
200 interest it. */
201 public static native void setupSystemThread ();
202
203
204
205 /* Input connection functions. These mostly correspond to their
206 counterparts in Android's InputConnection. */
207
208 public static native void beginBatchEdit (short window);
209 public static native void endBatchEdit (short window);
210 public static native void commitCompletion (short window, String text,
211 int position);
212 public static native void commitText (short window, String text,
213 int position);
214 public static native void deleteSurroundingText (short window,
215 int leftLength,
216 int rightLength);
217 public static native void finishComposingText (short window);
218 public static native String getSelectedText (short window, int flags);
219 public static native String getTextAfterCursor (short window, int length,
220 int flags);
221 public static native String getTextBeforeCursor (short window, int length,
222 int flags);
223 public static native void setComposingText (short window, String text,
224 int newCursorPosition);
225 public static native void setComposingRegion (short window, int start,
226 int end);
227 public static native void setSelection (short window, int start, int end);
228 public static native void performEditorAction (short window,
229 int editorAction);
230 public static native void performContextMenuAction (short window,
231 int contextMenuAction);
232 public static native ExtractedText getExtractedText (short window,
233 ExtractedTextRequest req,
234 int flags);
235 public static native void requestSelectionUpdate (short window);
236 public static native void requestCursorUpdates (short window, int mode);
237 public static native void clearInputFlags (short window);
238 public static native SurroundingText getSurroundingText (short window,
239 int left, int right,
240 int flags);
241 public static native TextSnapshot takeSnapshot (short window);
242
243
244 /* Return the current value of the selection, or -1 upon
245 failure. */
246 public static native int[] getSelection (short window);
247
248
249 /* Graphics functions used as a replacement for potentially buggy
250 Android APIs. */
251
252 public static native void blitRect (Bitmap src, Bitmap dest, int x1,
253 int y1, int x2, int y2);
254
255 /* Increment the generation ID of the specified BITMAP, forcing its
256 texture to be re-uploaded to the GPU. */
257
258 public static native void notifyPixelsChanged (Bitmap bitmap);
259
260
261 /* Functions used to synchronize document provider access with the
262 main thread. */
263
264 /* Wait for a call to `safPostRequest' while also reading async
265 input.
266
267 If asynchronous input arrives and sets Vquit_flag, return 1. */
268 public static native int safSyncAndReadInput ();
269
270 /* Wait for a call to `safPostRequest'. */
271 public static native void safSync ();
272
273 /* Post the semaphore used to await the completion of SAF
274 operations. */
275 public static native void safPostRequest ();
276
277 /* Detect and return FD is writable. FD may be truncated to 0 bytes
278 in the process. */
279 public static native boolean ftruncate (int fd);
280
281 static
282 {
283 /* Older versions of Android cannot link correctly with shared
284 libraries that link with other shared libraries built along
285 Emacs unless all requisite shared libraries are explicitly
286 loaded from Java.
287
288 Every time you add a new shared library dependency to Emacs,
289 please add it here as well. */
290
291 libraryDeps = new String[] { "png_emacs", "selinux_emacs",
292 "crypto_emacs", "pcre_emacs",
293 "packagelistparser_emacs",
294 "gnutls_emacs", "gmp_emacs",
295 "nettle_emacs", "p11-kit_emacs",
296 "tasn1_emacs", "hogweed_emacs",
297 "jansson_emacs", "jpeg_emacs",
298 "tiff_emacs", "xml2_emacs",
299 "icuuc_emacs",
300 "tree-sitter_emacs", };
301
302 for (String dependency : libraryDeps)
303 {
304 try
305 {
306 System.loadLibrary (dependency);
307 }
308 catch (UnsatisfiedLinkError exception)
309 {
310 /* Ignore this exception. */
311 }
312 }
313
314 System.loadLibrary ("emacs");
315 };
316 };