]> git.eshelyaron.com Git - emacs.git/commitdiff
Move Android port internals documentation to admin/notes
authorPo Lu <luangruo@yahoo.com>
Sun, 3 Sep 2023 02:04:44 +0000 (10:04 +0800)
committerPo Lu <luangruo@yahoo.com>
Sun, 3 Sep 2023 02:05:15 +0000 (10:05 +0800)
* admin/notes/java: New file.  Move most of its contents from
README, and introduce a section on compatibility.

* java/README: Move internals to admin/notes/java.

admin/notes/java [new file with mode: 0644]
java/README

diff --git a/admin/notes/java b/admin/notes/java
new file mode 100644 (file)
index 0000000..125ac0a
--- /dev/null
@@ -0,0 +1,1097 @@
+Installation instructions for Android
+Copyright (C) 2023 Free Software Foundation, Inc.
+See the end of the file for license conditions.
+
+\f
+
+OVERVIEW OF JAVA
+
+Emacs developers do not know Java, and there is no reason they should
+have to.  Thus, the code in this directory is confined to what is
+strictly necessary to support Emacs, and only uses a subset of Java
+written in a way that is easily understandable to C programmers.
+
+Java is required because the entire Android runtime is based around
+Java, and there is no way to write an Android program which runs
+without Java.
+
+This text exists to prime other Emacs developers, already familar with
+C, on the basic architecture of the Android port, and to teach them
+how to read and write the Java code found in this directory.
+
+Java is an object oriented language with automatic memory management
+compiled down to bytecode, which is then subject to interpretation by
+a Java virtual machine.
+
+What that means, is that:
+
+struct emacs_window
+{
+  int some_fields;
+  int of_emacs_window;
+};
+
+static void
+do_something_with_emacs_window (struct emacs_window *a, int n)
+{
+  a->some_fields = a->of_emacs_window + n;
+}
+
+would be written:
+
+public class EmacsWindow
+{
+  public int someFields;
+  public int ofEmacsWindow;
+
+  public void
+  doSomething (int n)
+  {
+    someFields = ofEmacsWindow + n;
+  }
+}
+
+and instead of doing:
+
+do_something_with_emacs_window (my_window, 1);
+
+you say:
+
+myWindow.doSomething (1);
+
+In addition to functions associated with an object of a given class
+(such as EmacsWindow), Java also has two other kinds of functions.
+
+The first are so-called ``static'' functions (the static means
+something entirely different from what it does in C.)
+
+A static function, while still having to be defined within a class,
+can be called without any object.  Instead of the object, you write
+the name of the Java class within which it is defined. For example,
+the following C code:
+
+int
+multiply_a_with_b_and_then_add_c (int a, int b, int c)
+{
+  return a * b + c;
+}
+
+would be:
+
+public class EmacsSomething
+{
+  public static int
+  multiplyAWithBAndThenAddC (int a, int b, int c)
+  {
+    return a * b + c;
+  }
+};
+
+Then, instead of calling:
+
+int foo;
+
+foo = multiply_a_with_b_then_add_c (1, 2, 3);
+
+you say:
+
+int foo;
+
+foo = EmacsSomething.multiplyAWithBAndThenAddC (1, 2, 3);
+
+In Java, ``static'' does not mean that the function is only used
+within its compilation unit!  Instead, the ``private'' qualifier is
+used to mean more or less the same thing:
+
+static void
+this_procedure_is_only_used_within_this_file (void)
+{
+  do_something ();
+}
+
+becomes
+
+public class EmacsSomething
+{
+  private static void
+  thisProcedureIsOnlyUsedWithinThisClass ()
+  {
+
+  }
+}
+
+the other kind are called ``constructors''.  They are functions that
+must be called to allocate memory to hold a class:
+
+public class EmacsFoo
+{
+  int bar;
+
+  public
+  EmacsFoo (int tokenA, int tokenB)
+  {
+    bar = tokenA + tokenB;
+  }
+}
+
+now, the following statement:
+
+EmacsFoo foo;
+
+foo = new EmacsFoo (1, 2);
+
+becomes more or less equivalent to the following C code:
+
+struct emacs_foo
+{
+  int bar;
+};
+
+struct emacs_foo *
+make_emacs_foo (int token_a, int token_b)
+{
+  struct emacs_foo *foo;
+
+  foo = xmalloc (sizeof *foo);
+  foo->bar = token_a + token_b;
+
+  return foo;
+}
+
+/* ... */
+
+struct emacs_foo *foo;
+
+foo = make_emacs_foo (1, 2);
+
+A class may have any number of constructors, or no constructors at
+all, in which case the compiler inserts an empty constructor.
+
+\f
+
+Sometimes, you will see Java code that looks like this:
+
+    allFiles = filesDirectory.listFiles (new FileFilter () {
+       @Override
+       public boolean
+       accept (File file)
+       {
+         return (!file.isDirectory ()
+                 && file.getName ().endsWith (".pdmp"));
+       }
+      });
+
+This is Java's version of GCC's nested function extension.  The major
+difference is that the nested function may still be called even after
+it goes out of scope, and always retains a reference to the class and
+local variables around where it was called.
+
+Being an object-oriented language, Java also allows defining that a
+class ``extends'' another class.  The following C code:
+
+struct a
+{
+  long thirty_two;
+};
+
+struct b
+{
+  struct a a;
+  long long sixty_four;
+};
+
+extern void do_something (struct a *);
+
+void
+my_function (struct b *b)
+{
+  do_something (&b->a);
+}
+
+is roughly equivalent to the following Java code, split into two
+files:
+
+  A.java
+
+public class A
+{
+  int thirtyTwo;
+
+  public void
+  doSomething ()
+  {
+    etcEtcEtc ();
+  }
+};
+
+  B.java
+
+public class B extends A
+{
+  long sixty_four;
+
+  public static void
+  myFunction (B b)
+  {
+    b.doSomething ();
+  }
+}
+
+the Java runtime has transformed the call to ``b.doSomething'' to
+``((A) b).doSomething''.
+
+However, Java also allows overriding this behavior, by specifying the
+@Override keyword:
+
+public class B extends A
+{
+  long sixty_four;
+
+  @Override
+  public void
+  doSomething ()
+  {
+    Something.doSomethingTwo ();
+    super.doSomething ();
+  }
+}
+
+now, any call to ``doSomething'' on a ``B'' created using ``new B ()''
+will end up calling ``Something.doSomethingTwo'', before calling back
+to ``A.doSomething''.  This override also applies in reverse; that is
+to say, even if you write:
+
+  ((A) b).doSomething ();
+
+B's version of doSomething will still be called, if ``b'' was created
+using ``new B ()''.
+
+This mechanism is used extensively throughout the Java language and
+Android windowing APIs.
+
+Elsewhere, you will encounter Java code that defines arrays:
+
+public class EmacsFrobinicator
+{
+  public static void
+  emacsFrobinicate (int something)
+  {
+    int[] primesFromSomething;
+
+    primesFromSomething = new int[numberOfPrimes];
+    /* ... */
+  }
+}
+
+Java arrays are similar to C arrays in that they can not grow.  But
+they are very much unlike C arrays in that they are always references
+(as opposed to decaying into pointers in only some situations), and
+contain information about their length.
+
+If another function named ``frobinicate1'' takes an array as an
+argument, then it need not take the length of the array.
+
+Instead, it may simply iterate over the array like so:
+
+int i, k;
+
+for (i = 0; i < array.length; ++i)
+  {
+    k = array[i];
+
+    Whatever.doSomethingWithK (k);
+  }
+
+The syntax used to define arrays is also slightly different.  As
+arrays are always references, there is no way for you to tell the
+runtime to allocate an array of size N in a structure (class.)
+
+Instead, if you need an array of that size, you must declare a field
+with the type of the array, and allocate the array inside the class's
+constructor, like so:
+
+public class EmacsArrayContainer
+{
+  public int[] myArray;
+
+  public
+  EmacsArrayContainer ()
+  {
+    myArray = new array[10];
+  }
+}
+
+while in C, you could just have written:
+
+struct emacs_array_container
+{
+  int my_array[10];
+};
+
+or, possibly even better,
+
+typedef int emacs_array_container[10];
+
+Alas, Java has no equivalent of `typedef'.
+
+Like in C, Java string literals are delimited by double quotes.
+Unlike C, however, strings are not NULL-terminated arrays of
+characters, but a distinct type named ``String''.  They store their
+own length, characters in Java's 16-bit ``char'' type, and are capable
+of holding NULL bytes.
+
+Instead of writing:
+
+wchar_t character;
+extern char *s;
+size_t s;
+
+  for (/* determine n, s in a loop.  */)
+    s += mbstowc (&character, s, n);
+
+or:
+
+const char *byte;
+
+for (byte = my_string; *byte; ++byte)
+  /* do something with *byte.  */;
+
+or perhaps even:
+
+size_t length, i;
+char foo;
+
+length = strlen (my_string);
+
+for (i = 0; i < length; ++i)
+  foo = my_string[i];
+
+you write:
+
+char foo;
+int i;
+
+for (i = 0; i < myString.length (); ++i)
+  foo = myString.charAt (0);
+
+Java also has stricter rules on what can be used as a truth value in a
+conditional.  While in C, any non-zero value is true, Java requires
+that every truth value be of the boolean type ``boolean''.
+
+What this means is that instead of simply writing:
+
+  if (foo || bar)
+
+where foo can either be 1 or 0, and bar can either be NULL or a
+pointer to something, you must explicitly write:
+
+  if (foo != 0 || bar != null)
+
+in Java.
+
+JAVA NATIVE INTERFACE
+
+Java also provides an interface for C code to interface with Java.
+
+C functions exported from a shared library become static Java
+functions within a class, like so:
+
+public class EmacsNative
+{
+  /* Obtain the fingerprint of this build of Emacs.  The fingerprint
+     can be used to determine the dump file name.  */
+  public static native String getFingerprint ();
+
+  /* Set certain parameters before initializing Emacs.
+
+     assetManager must be the asset manager associated with the
+     context that is loading Emacs.  It is saved and remains for the
+     remainder the lifetime of the Emacs process.
+
+     filesDir must be the package's data storage location for the
+     current Android user.
+
+     libDir must be the package's data storage location for native
+     libraries.         It is used as PATH.
+
+     cacheDir must be the package's cache directory.  It is used as
+     the `temporary-file-directory'.
+
+     pixelDensityX and pixelDensityY are the DPI values that will be
+     used by Emacs.
+
+     classPath must be the classpath of this app_process process, or
+     NULL.
+
+     emacsService must be the EmacsService singleton, or NULL. */
+  public static native void setEmacsParams (AssetManager assetManager,
+                                           String filesDir,
+                                           String libDir,
+                                           String cacheDir,
+                                           float pixelDensityX,
+                                           float pixelDensityY,
+                                           String classPath,
+                                           EmacsService emacsService);
+}
+
+Where the corresponding C functions are located in android.c, and
+loaded by the special invocation:
+
+  static
+  {
+    System.loadLibrary ("emacs");
+  };
+
+where ``static'' defines a section of code which will be run upon the
+object (containing class) being loaded.  This is like:
+
+  __attribute__((constructor))
+
+on systems where shared object constructors are supported.
+
+See http://docs.oracle.com/en/java/javase/19/docs/specs/jni/intro.html
+for more details.
+
+\f
+
+OVERVIEW OF ANDROID
+
+When the Android system starts an application, it does not actually
+call the application's ``main'' function.  It may not even start the
+application's process if one is already running.
+
+Instead, Android is organized around components.  When the user opens
+the ``Emacs'' icon, the Android system looks up and starts the
+component associated with the ``Emacs'' icon.  In this case, the
+component is called an activity, and is declared in
+the AndroidManifest.xml in this directory:
+
+    <activity android:name="org.gnu.emacs.EmacsActivity"
+             android:launchMode="singleTop"
+             android:windowSoftInputMode="adjustResize"
+             android:exported="true"
+             android:configChanges="orientation|screenSize|screenLayout|keyboardHidden">
+      <intent-filter>
+       <action android:name="android.intent.action.MAIN" />
+       <category android:name="android.intent.category.DEFAULT" />
+       <category android:name="android.intent.category.LAUNCHER" />
+      </intent-filter>
+    </activity>
+
+This tells Android to start the activity defined in ``EmacsActivity''
+(defined in org/gnu/emacs/EmacsActivity.java), a class extending the
+Android class ``Activity''.
+
+To do so, the Android system creates an instance of ``EmacsActivity''
+and the window system window associated with it, and eventually calls:
+
+  Activity activity;
+
+  activity.onCreate (...);
+
+But which ``onCreate'' is really called?
+It is actually the ``onCreate'' defined in EmacsActivity.java, as
+it overrides the ``onCreate'' defined in Android's own Activity class:
+
+  @Override
+  public void
+  onCreate (Bundle savedInstanceState)
+  {
+    FrameLayout.LayoutParams params;
+    Intent intent;
+
+Then, this is what happens step-by-step within the ``onCreate''
+function:
+
+    /* See if Emacs should be started with -Q. */
+    intent = getIntent ();
+    EmacsService.needDashQ
+      = intent.getBooleanExtra ("org.gnu.emacs.START_DASH_Q",
+                               false);
+
+Here, Emacs obtains the intent (a request to start a component) which
+was used to start Emacs, and sets a special flag if it contains a
+request for Emacs to start with the ``-Q'' command-line argument.
+
+    /* Set the theme to one without a title bar.  */
+
+    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
+      setTheme (android.R.style.Theme_DeviceDefault_NoActionBar);
+    else
+      setTheme (android.R.style.Theme_NoTitleBar);
+
+Next, Emacs sets an appropriate theme for the activity's associated
+window decorations.
+
+    params = new FrameLayout.LayoutParams (LayoutParams.MATCH_PARENT,
+                                          LayoutParams.MATCH_PARENT);
+
+    /* Make the frame layout.  */
+    layout = new FrameLayout (this);
+    layout.setLayoutParams (params);
+
+    /* Set it as the content view.  */
+    setContentView (layout);
+
+Then, Emacs creates a ``FrameLayout'', a widget that holds a single
+other widget, and makes it the activity's ``content view''.
+
+The activity itself is a ``FrameLayout'', so the ``layout parameters''
+here apply to the FrameLayout itself, and not its children.
+
+    /* Maybe start the Emacs service if necessary.  */
+    EmacsService.startEmacsService (this);
+
+And after that, Emacs calls the static function ``startEmacsService'',
+defined in the class ``EmacsService''. This starts the Emacs service
+component if necessary.
+
+    /* Add this activity to the list of available activities.  */
+    EmacsWindowAttachmentManager.MANAGER.registerWindowConsumer (this);
+
+    super.onCreate (savedInstanceState);
+
+Finally, Emacs registers that this activity is now ready to receive
+top-level frames (windows) created from Lisp.
+
+Activities come and go, but Emacs has to stay running in the mean
+time.  Thus, Emacs also defines a ``service'', which is a long-running
+component that the Android system allows to run in the background.
+
+Let us go back and review the definition of ``startEmacsService'':
+
+  public static void
+  startEmacsService (Context context)
+  {
+    if (EmacsService.SERVICE == null)
+      {
+       if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
+         /* Start the Emacs service now.  */
+         context.startService (new Intent (context,
+                                           EmacsService.class));
+       else
+         /* Display the permanant notification and start Emacs as a
+            foreground service.  */
+         context.startForegroundService (new Intent (context,
+                                                     EmacsService.class));
+      }
+  }
+
+If ``EmacsService.SERVICE'' does not yet exist, what this does is to
+tell the ``context'' (the equivalent of an Xlib Display *) to start a
+service defined by the class ``EmacsService''. Eventually, this
+results in ``EmacsService.onCreate'' being called:
+
+  @Override
+  public void
+  onCreate ()
+  {
+    AssetManager manager;
+    Context app_context;
+    String filesDir, libDir, cacheDir, classPath;
+    double pixelDensityX;
+    double pixelDensityY;
+
+Here is what this function does, step-by-step:
+
+    SERVICE = this;
+
+First, it sets the special static variable ``SERVICE'' to ``this'',
+which is a pointer to the ``EmacsService' object that was created.
+
+    handler = new Handler (Looper.getMainLooper ());
+
+Next, it creates a ``Handler'' object for the ``main looper''.
+This is a helper structure which allows executing code on the Android
+user interface thread.
+
+    manager = getAssets ();
+    app_context = getApplicationContext ();
+    metrics = getResources ().getDisplayMetrics ();
+    pixelDensityX = metrics.xdpi;
+    pixelDensityY = metrics.ydpi;
+
+Finally, it obtains:
+
+  - the asset manager, which is used to retrieve assets packaged
+    into the Emacs application package.
+
+  - the application context, used to obtain application specific
+    information.
+
+  - the display metrics, and from them, the X and Y densities in dots
+    per inch.
+
+Then, inside a ``try'' block:
+
+    try
+      {
+       /* Configure Emacs with the asset manager and other necessary
+          parameters.  */
+       filesDir = app_context.getFilesDir ().getCanonicalPath ();
+       libDir = getLibraryDirectory ();
+       cacheDir = app_context.getCacheDir ().getCanonicalPath ();
+
+It obtains the names of the Emacs home, shared library, and temporary
+file directories.
+
+       /* Now provide this application's apk file, so a recursive
+          invocation of app_process (through android-emacs) can
+          find EmacsNoninteractive.  */
+       classPath = getApkFile ();
+
+The name of the Emacs application package.
+
+       Log.d (TAG, "Initializing Emacs, where filesDir = " + filesDir
+              + ", libDir = " + libDir + ", and classPath = " + classPath);
+
+Prints a debug message to the Android system log with this
+information.
+
+       EmacsNative.setEmacsParams (manager, filesDir, libDir,
+                                   cacheDir, (float) pixelDensityX,
+                                   (float) pixelDensityY,
+                                   classPath, this);
+
+And calls the native function ``setEmacsParams'' (defined in
+android.c) to configure Emacs with this information.
+
+       /* Start the thread that runs Emacs.  */
+       thread = new EmacsThread (this, needDashQ);
+       thread.start ();
+
+Then, it allocates an ``EmacsThread'' object, and starts that thread.
+Inside that thread is where Emacs's C code runs.
+
+      }
+    catch (IOException exception)
+      {
+       EmacsNative.emacsAbort ();
+       return;
+
+And here is the purpose of the ``try'' block.  Functions related to
+file names in Java will signal errors of various types upon failure.
+
+This ``catch'' block means that the Java virtual machine will abort
+execution of the contents of the ``try'' block as soon as an error of
+type ``IOException'' is encountered, and begin executing the contents
+of the ``catch'' block.
+
+Any failure of that type here is a crash, and
+``EmacsNative.emacsAbort'' is called to quickly abort the process to
+get a useful backtrace.
+      }
+  }
+
+Now, let us look at the definition of the class ``EmacsThread'', found
+in org/gnu/emacs/EmacsThread.java:
+
+public class EmacsThread extends Thread
+{
+  /* Whether or not Emacs should be started -Q.         */
+  private boolean startDashQ;
+
+  public
+  EmacsThread (EmacsService service, boolean startDashQ)
+  {
+    super ("Emacs main thread");
+    this.startDashQ = startDashQ;
+  }
+
+  @Override
+  public void
+  run ()
+  {
+    String args[];
+
+    if (!startDashQ)
+      args = new String[] { "libandroid-emacs.so", };
+    else
+      args = new String[] { "libandroid-emacs.so", "-Q", };
+
+    /* Run the native code now.         */
+    EmacsNative.initEmacs (args, EmacsApplication.dumpFileName);
+  }
+};
+
+The class itself defines a single field, ``startDashQ'', a constructor
+with an unused argument of the type ``EmacsService'' (which is useful
+while debugging) and a flag ``startDashQ'', and a single function
+``run'', overriding the same function in the class ``Thread''.
+
+When ``thread.start'' is called, the Java virtual machine creates a
+new thread, and then calls the function ``run'' within that thread.
+
+This function then computes a suitable argument vector, and calls
+``EmacsNative.initEmacs'' (defined in android.c), which then calls a
+modified version of the regular Emacs ``main'' function.
+
+At that point, Emacs initialization proceeds as usual:
+Vinitial_window_system is set, loadup.el calls `normal-top-level',
+which calls `command-line', and finally
+`window-system-initialization', which initializes the `android'
+terminal interface as usual.
+
+What happens here is the same as on other platforms.  Now, here is
+what happens when the initial frame is created: Fx_create_frame calls
+`android_create_frame_window' to create a top level window:
+
+static void
+android_create_frame_window (struct frame *f)
+{
+  struct android_set_window_attributes attributes;
+  enum android_window_value_mask attribute_mask;
+
+  attributes.background_pixel = FRAME_BACKGROUND_PIXEL (f);
+  attribute_mask = ANDROID_CW_BACK_PIXEL;
+
+  block_input ();
+  FRAME_ANDROID_WINDOW (f)
+    = android_create_window (FRAME_DISPLAY_INFO (f)->root_window,
+                            f->left_pos,
+                            f->top_pos,
+                            FRAME_PIXEL_WIDTH (f),
+                            FRAME_PIXEL_HEIGHT (f),
+                            attribute_mask, &attributes);
+  unblock_input ();
+}
+
+This calls the function `android_create_window' with some arguments
+whose meanings are identical to the arguments to `XCreateWindow'.
+
+Here is the definition of `android_create_window', in android.c:
+
+android_window
+android_create_window (android_window parent, int x, int y,
+                      int width, int height,
+                      enum android_window_value_mask value_mask,
+                      struct android_set_window_attributes *attrs)
+{
+  static jclass class;
+  static jmethodID constructor;
+  jobject object, parent_object, old;
+  android_window window;
+  android_handle prev_max_handle;
+  bool override_redirect;
+
+What does it do? First, some context:
+
+At any time, there can be at most 65535 Java objects referred to by
+the rest of Emacs through the Java native interface.  Each such object
+is assigned a ``handle'' (similar to an XID on X) and given a unique
+type.  The function `android_resolve_handle' returns the JNI `jobject'
+associated with a given handle.
+
+  parent_object = android_resolve_handle (parent, ANDROID_HANDLE_WINDOW);
+
+Here, it is being used to look up the `jobject' associated with the
+`parent' handle.
+
+  prev_max_handle = max_handle;
+  window = android_alloc_id ();
+
+Next, `max_handle' is saved, and a new handle is allocated for
+`window'.
+
+  if (!window)
+    error ("Out of window handles!");
+
+An error is signalled if Emacs runs out of available handles.
+
+  if (!class)
+    {
+      class = (*android_java_env)->FindClass (android_java_env,
+                                             "org/gnu/emacs/EmacsWindow");
+      assert (class != NULL);
+
+Then, if this initialization has not yet been completed, Emacs
+proceeds to find the Java class named ``EmacsWindow''.
+
+      constructor
+       = (*android_java_env)->GetMethodID (android_java_env, class, "<init>",
+                                           "(SLorg/gnu/emacs/EmacsWindow;"
+                                           "IIIIZ)V");
+      assert (constructor != NULL);
+
+And it tries to look up the constructor, which should take seven
+arguments:
+
+  S                                    - a short.  (the handle ID)
+  Lorg/gnu/Emacs/EmacsWindow;          - an instance of the EmacsWindow
+                                         class.  (the parent)
+  IIII                                 - four ints.  (the window geometry.)
+  Z                                    - a boolean.  (whether or not the
+                                         window is override-redirect; see
+                                         XChangeWindowAttributes.)
+
+      old = class;
+      class = (*android_java_env)->NewGlobalRef (android_java_env, class);
+      (*android_java_env)->ExceptionClear (android_java_env);
+      ANDROID_DELETE_LOCAL_REF (old);
+
+Next, it saves a global reference to the class and deletes the local
+reference.  Global references will never be deallocated by the Java
+virtual machine as long as they still exist.
+
+      if (!class)
+       memory_full (0);
+    }
+
+  /* N.B. that ANDROID_CW_OVERRIDE_REDIRECT can only be set at window
+     creation time.  */
+  override_redirect = ((value_mask
+                       & ANDROID_CW_OVERRIDE_REDIRECT)
+                      && attrs->override_redirect);
+
+  object = (*android_java_env)->NewObject (android_java_env, class,
+                                          constructor, (jshort) window,
+                                          parent_object, (jint) x, (jint) y,
+                                          (jint) width, (jint) height,
+                                          (jboolean) override_redirect);
+
+Then, it creates an instance of the ``EmacsWindow'' class with the
+appropriate arguments and previously determined constructor.
+
+  if (!object)
+    {
+      (*android_java_env)->ExceptionClear (android_java_env);
+
+      max_handle = prev_max_handle;
+      memory_full (0);
+
+If creating the object fails, Emacs clears the ``pending exception''
+and signals that it is out of memory.
+    }
+
+  android_handles[window].type = ANDROID_HANDLE_WINDOW;
+  android_handles[window].handle
+    = (*android_java_env)->NewGlobalRef (android_java_env,
+                                        object);
+  (*android_java_env)->ExceptionClear (android_java_env);
+  ANDROID_DELETE_LOCAL_REF (object);
+
+Otherwise, it associates a new global reference to the object with the
+handle, and deletes the local reference returned from the JNI
+NewObject function.
+
+  if (!android_handles[window].handle)
+    memory_full (0);
+
+If allocating the global reference fails, Emacs signals that it is out
+of memory.
+
+  android_change_window_attributes (window, value_mask, attrs);
+  return window;
+
+Otherwise, it applies the specified window attributes and returns the
+handle of the new window.
+}
+
+\f
+
+DRAWABLES, CURSORS AND HANDLES
+
+Each widget created by Emacs corresponds to a single ``window'', which
+has its own backing store.  This arrangement is quite similar to X.
+
+C code does not directly refer to the EmacsView widgets that implement
+the UI logic behind windows.  Instead, its handles refer to
+EmacsWindow structures, which contain the state necessary to interact
+with the widgets in an orderly and synchronized manner.
+
+Like X, both pixmaps and windows are drawable resources, and the same
+graphics operations can be applied to both.  Thus, a separate
+EmacsPixmap structure is used to wrap around Android Bitmap resources,
+and the Java-level graphics operation functions are capable of
+operating on them both.
+
+Finally, graphics contexts are maintained on both the C and Java
+levels; the C state recorded in `struct android_gc' is kept in sync
+with the Java state in the GContext handle's corresponding EmacsGC
+structure, and cursors are used through handles that refer to
+EmacsCursor structures that hold system PointerIcons.
+
+In all cases, the interfaces provided are identical to X.
+
+\f
+
+EVENT LOOP
+
+In a typical Android application, the event loop is managed by the
+operating system, and callbacks (implemented through overriding
+separate functions in widgets) are run by the event loop wherever
+necessary.  The thread which runs the event loop is also the only
+thread capable of creating and manipulating widgets and activities,
+and is referred to as the ``UI thread''.
+
+These callbacks are used by Emacs to write representations of X-like
+events to a separate event queue, which are then read from Emacs's own
+event loop running in a separate thread.  This is accomplished through
+replacing `select' by a function which waits for the event queue to be
+occupied, in addition to any file descriptors that `select' would
+normally wait for.
+
+Conversely, Emacs's event loop sometimes needs to send events to the
+UI thread.  These events are implemented as tiny fragments of code,
+which are run as they are received by the main thread.
+
+A typical example is `displayToast', which is implemented in
+EmacsService.java:
+
+  public void
+  displayToast (final String string)
+  {
+    runOnUiThread (new Runnable () {
+       @Override
+       public void
+       run ()
+       {
+         Toast toast;
+
+         toast = Toast.makeText (getApplicationContext (),
+                                 string, Toast.LENGTH_SHORT);
+         toast.show ();
+       }
+      });
+  }
+
+Here, the variable `string' is used by a nested function.  This nested
+function contains a copy of that variable, and is run on the main
+thread using the function `runOnUiThread', in order to display a short
+status message on the display.
+
+When Emacs needs to wait for the nested function to finish, it uses a
+mechanism implemented in `syncRunnable'.  This mechanism first calls a
+deadlock avoidance mechanism, then runs a nested function on the UI
+thread, which is expected to signal itself as a condition variable
+upon completion.  It is typically used to allocate resources that can
+only be allocated from the UI thread, or to obtain non-thread-safe
+information.  The following function is an example; it returns a new
+EmacsView widget corresponding to the provided window:
+
+  public EmacsView
+  getEmacsView (final EmacsWindow window, final int visibility,
+               final boolean isFocusedByDefault)
+  {
+    Runnable runnable;
+    final EmacsHolder<EmacsView> view;
+
+    view = new EmacsHolder<EmacsView> ();
+
+    runnable = new Runnable () {
+       public void
+       run ()
+       {
+         synchronized (this)
+           {
+             view.thing = new EmacsView (window);
+             view.thing.setVisibility (visibility);
+
+             /* The following function is only present on Android 26
+                or later.  */
+             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
+               view.thing.setFocusedByDefault (isFocusedByDefault);
+
+             notify ();
+           }
+       }
+      };
+
+    syncRunnable (runnable);
+    return view.thing;
+  }
+
+As no value can be directly returned from the nested function, a
+separate container object is used to hold the result after the
+function finishes execution.  Note the type name inside the angle
+brackets: this type is substituted into the class definition as it is
+used; a definition such as:
+
+public class Foo<T>
+{
+  T bar;
+};
+
+can not be used alone:
+
+  Foo holder; /* Error! */
+
+but must have a type specified:
+
+  Foo<Object> holder;
+
+in which case the effective definition is:
+
+public class Foo
+{
+  Object bar;
+};
+
+\f
+
+COMPATIBILITY
+
+There are three variables set within every Android application that
+extert influence over the set of Android systems it supports, and the
+measures it must take to function faithfully on each of those systems:
+the minimum API level, compile SDK version and target API level.
+
+The minimum API level is the earliest version of Android that is
+permitted to install and run the application.  For Emacs, this is
+established by detecting the __ANDROID_API__ preprocessor macro
+defined within the Android C compiler.
+
+Before Java code executes any Android API calls that are not present
+within Android 2.2 (API level 8), the lowest API level supported by
+Emacs as a whole, it must first check the value of the:
+
+  Build.VERSION.SDK_INT
+
+variable, which is always set to the API level of the system Emacs is
+presently installed within.  For example, before calling
+`dispatchKeyEventFromInputMethod', a function absent from Android 6.0
+(API level 23) or earlier, check:
+
+    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
+      view.imManager.dispatchKeyEventFromInputMethod (view, key);
+    else
+      {
+
+where `N' is a constant defined to 24.
+
+The compile SDK version is the version of the Android SDK headers Java
+code is compiled against.  Because Java does not provide conditional
+compilation constructs, Emacs can't be compiled with any version of
+these headers other than the version mentioned in `java/INSTALL', but
+the headers used do not affect the set of supported systems provided
+that the version checks illustrated above are performed where
+necessary.
+
+The target API level is a number within java/AndroidManifest.xml.in
+the system refers to when deciding whether to enable
+backwards-incompatible modifications to the behavior of various system
+APIs.  For any given Android version, backwards incompatible changes
+in that version will be disabled for applications whose target API
+levels don't exceed its own.
+
+The target API should nevertheless be updated to match every major
+Android update, as Google has stated their intentions to prohibit
+users from installing applications targeting ``out-of-date'' versions
+of Android, though this threat has hitherto been made good on.
+
+\f
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
index e518e9fbb2f637ee11e9cea02f3b211b7f60876a..a909cdd22ef503a6b8fe00b93b70bbbb0e0e1036 100644 (file)
@@ -22,1027 +22,6 @@ Please keep the Java code indented with tabs and formatted according
 to the rules for C code in the GNU coding standards.  Always use
 C-style comments.
 
-======================================================================
-
-OVERVIEW OF JAVA
-
-Emacs developers do not know Java, and there is no reason they should
-have to.  Thus, the code in this directory is confined to what is
-strictly necessary to support Emacs, and only uses a subset of Java
-written in a way that is easily understandable to C programmers.
-
-Java is required because the entire Android runtime is based around
-Java, and there is no way to write an Android program which runs
-without Java.
-
-This text exists to prime other Emacs developers, already familar with
-C, on the basic architecture of the Android port, and to teach them
-how to read and write the Java code found in this directory.
-
-Java is an object oriented language with automatic memory management
-compiled down to bytecode, which is then subject to interpretation by
-a Java virtual machine.
-
-What that means, is that:
-
-struct emacs_window
-{
-  int some_fields;
-  int of_emacs_window;
-};
-
-static void
-do_something_with_emacs_window (struct emacs_window *a, int n)
-{
-  a->some_fields = a->of_emacs_window + n;
-}
-
-would be written:
-
-public class EmacsWindow
-{
-  public int someFields;
-  public int ofEmacsWindow;
-
-  public void
-  doSomething (int n)
-  {
-    someFields = ofEmacsWindow + n;
-  }
-}
-
-and instead of doing:
-
-do_something_with_emacs_window (my_window, 1);
-
-you say:
-
-myWindow.doSomething (1);
-
-In addition to functions associated with an object of a given class
-(such as EmacsWindow), Java also has two other kinds of functions.
-
-The first are so-called ``static'' functions (the static means
-something entirely different from what it does in C.)
-
-A static function, while still having to be defined within a class,
-can be called without any object.  Instead of the object, you write
-the name of the Java class within which it is defined. For example,
-the following C code:
-
-int
-multiply_a_with_b_and_then_add_c (int a, int b, int c)
-{
-  return a * b + c;
-}
-
-would be:
-
-public class EmacsSomething
-{
-  public static int
-  multiplyAWithBAndThenAddC (int a, int b, int c)
-  {
-    return a * b + c;
-  }
-};
-
-Then, instead of calling:
-
-int foo;
-
-foo = multiply_a_with_b_then_add_c (1, 2, 3);
-
-you say:
-
-int foo;
-
-foo = EmacsSomething.multiplyAWithBAndThenAddC (1, 2, 3);
-
-In Java, ``static'' does not mean that the function is only used
-within its compilation unit!  Instead, the ``private'' qualifier is
-used to mean more or less the same thing:
-
-static void
-this_procedure_is_only_used_within_this_file (void)
-{
-  do_something ();
-}
-
-becomes
-
-public class EmacsSomething
-{
-  private static void
-  thisProcedureIsOnlyUsedWithinThisClass ()
-  {
-
-  }
-}
-
-the other kind are called ``constructors''.  They are functions that
-must be called to allocate memory to hold a class:
-
-public class EmacsFoo
-{
-  int bar;
-
-  public
-  EmacsFoo (int tokenA, int tokenB)
-  {
-    bar = tokenA + tokenB;
-  }
-}
-
-now, the following statement:
-
-EmacsFoo foo;
-
-foo = new EmacsFoo (1, 2);
-
-becomes more or less equivalent to the following C code:
-
-struct emacs_foo
-{
-  int bar;
-};
-
-struct emacs_foo *
-make_emacs_foo (int token_a, int token_b)
-{
-  struct emacs_foo *foo;
-
-  foo = xmalloc (sizeof *foo);
-  foo->bar = token_a + token_b;
-
-  return foo;
-}
-
-/* ... */
-
-struct emacs_foo *foo;
-
-foo = make_emacs_foo (1, 2);
-
-A class may have any number of constructors, or no constructors at
-all, in which case the compiler inserts an empty constructor.
-
-\f
-
-Sometimes, you will see Java code that looks like this:
-
-    allFiles = filesDirectory.listFiles (new FileFilter () {
-       @Override
-       public boolean
-       accept (File file)
-       {
-         return (!file.isDirectory ()
-                 && file.getName ().endsWith (".pdmp"));
-       }
-      });
-
-This is Java's version of GCC's nested function extension.  The major
-difference is that the nested function may still be called even after
-it goes out of scope, and always retains a reference to the class and
-local variables around where it was called.
-
-Being an object-oriented language, Java also allows defining that a
-class ``extends'' another class.  The following C code:
-
-struct a
-{
-  long thirty_two;
-};
-
-struct b
-{
-  struct a a;
-  long long sixty_four;
-};
-
-extern void do_something (struct a *);
-
-void
-my_function (struct b *b)
-{
-  do_something (&b->a);
-}
-
-is roughly equivalent to the following Java code, split into two
-files:
-
-  A.java
-
-public class A
-{
-  int thirtyTwo;
-
-  public void
-  doSomething ()
-  {
-    etcEtcEtc ();
-  }
-};
-
-  B.java
-
-public class B extends A
-{
-  long sixty_four;
-
-  public static void
-  myFunction (B b)
-  {
-    b.doSomething ();
-  }
-}
-
-the Java runtime has transformed the call to ``b.doSomething'' to
-``((A) b).doSomething''.
-
-However, Java also allows overriding this behavior, by specifying the
-@Override keyword:
-
-public class B extends A
-{
-  long sixty_four;
-
-  @Override
-  public void
-  doSomething ()
-  {
-    Something.doSomethingTwo ();
-    super.doSomething ();
-  }
-}
-
-now, any call to ``doSomething'' on a ``B'' created using ``new B ()''
-will end up calling ``Something.doSomethingTwo'', before calling back
-to ``A.doSomething''.  This override also applies in reverse; that is
-to say, even if you write:
-
-  ((A) b).doSomething ();
-
-B's version of doSomething will still be called, if ``b'' was created
-using ``new B ()''.
-
-This mechanism is used extensively throughout the Java language and
-Android windowing APIs.
-
-Elsewhere, you will encounter Java code that defines arrays:
-
-public class EmacsFrobinicator
-{
-  public static void
-  emacsFrobinicate (int something)
-  {
-    int[] primesFromSomething;
-
-    primesFromSomething = new int[numberOfPrimes];
-    /* ... */
-  }
-}
-
-Java arrays are similar to C arrays in that they can not grow.  But
-they are very much unlike C arrays in that they are always references
-(as opposed to decaying into pointers in only some situations), and
-contain information about their length.
-
-If another function named ``frobinicate1'' takes an array as an
-argument, then it need not take the length of the array.
-
-Instead, it may simply iterate over the array like so:
-
-int i, k;
-
-for (i = 0; i < array.length; ++i)
-  {
-    k = array[i];
-
-    Whatever.doSomethingWithK (k);
-  }
-
-The syntax used to define arrays is also slightly different.  As
-arrays are always references, there is no way for you to tell the
-runtime to allocate an array of size N in a structure (class.)
-
-Instead, if you need an array of that size, you must declare a field
-with the type of the array, and allocate the array inside the class's
-constructor, like so:
-
-public class EmacsArrayContainer
-{
-  public int[] myArray;
-
-  public
-  EmacsArrayContainer ()
-  {
-    myArray = new array[10];
-  }
-}
-
-while in C, you could just have written:
-
-struct emacs_array_container
-{
-  int my_array[10];
-};
-
-or, possibly even better,
-
-typedef int emacs_array_container[10];
-
-Alas, Java has no equivalent of `typedef'.
-
-Like in C, Java string literals are delimited by double quotes.
-Unlike C, however, strings are not NULL-terminated arrays of
-characters, but a distinct type named ``String''.  They store their
-own length, characters in Java's 16-bit ``char'' type, and are capable
-of holding NULL bytes.
-
-Instead of writing:
-
-wchar_t character;
-extern char *s;
-size_t s;
-
-  for (/* determine n, s in a loop.  */)
-    s += mbstowc (&character, s, n);
-
-or:
-
-const char *byte;
-
-for (byte = my_string; *byte; ++byte)
-  /* do something with *byte.  */;
-
-or perhaps even:
-
-size_t length, i;
-char foo;
-
-length = strlen (my_string);
-
-for (i = 0; i < length; ++i)
-  foo = my_string[i];
-
-you write:
-
-char foo;
-int i;
-
-for (i = 0; i < myString.length (); ++i)
-  foo = myString.charAt (0);
-
-Java also has stricter rules on what can be used as a truth value in a
-conditional.  While in C, any non-zero value is true, Java requires
-that every truth value be of the boolean type ``boolean''.
-
-What this means is that instead of simply writing:
-
-  if (foo || bar)
-
-where foo can either be 1 or 0, and bar can either be NULL or a
-pointer to something, you must explicitly write:
-
-  if (foo != 0 || bar != null)
-
-in Java.
-
-JAVA NATIVE INTERFACE
-
-Java also provides an interface for C code to interface with Java.
-
-C functions exported from a shared library become static Java
-functions within a class, like so:
-
-public class EmacsNative
-{
-  /* Obtain the fingerprint of this build of Emacs.  The fingerprint
-     can be used to determine the dump file name.  */
-  public static native String getFingerprint ();
-
-  /* Set certain parameters before initializing Emacs.
-
-     assetManager must be the asset manager associated with the
-     context that is loading Emacs.  It is saved and remains for the
-     remainder the lifetime of the Emacs process.
-
-     filesDir must be the package's data storage location for the
-     current Android user.
-
-     libDir must be the package's data storage location for native
-     libraries.         It is used as PATH.
-
-     cacheDir must be the package's cache directory.  It is used as
-     the `temporary-file-directory'.
-
-     pixelDensityX and pixelDensityY are the DPI values that will be
-     used by Emacs.
-
-     classPath must be the classpath of this app_process process, or
-     NULL.
-
-     emacsService must be the EmacsService singleton, or NULL. */
-  public static native void setEmacsParams (AssetManager assetManager,
-                                           String filesDir,
-                                           String libDir,
-                                           String cacheDir,
-                                           float pixelDensityX,
-                                           float pixelDensityY,
-                                           String classPath,
-                                           EmacsService emacsService);
-}
-
-Where the corresponding C functions are located in android.c, and
-loaded by the special invocation:
-
-  static
-  {
-    System.loadLibrary ("emacs");
-  };
-
-where ``static'' defines a section of code which will be run upon the
-object (containing class) being loaded.  This is like:
-
-  __attribute__((constructor))
-
-on systems where shared object constructors are supported.
-
-See http://docs.oracle.com/en/java/javase/19/docs/specs/jni/intro.html
-for more details.
-
-\f
-
-OVERVIEW OF ANDROID
-
-When the Android system starts an application, it does not actually
-call the application's ``main'' function.  It may not even start the
-application's process if one is already running.
-
-Instead, Android is organized around components.  When the user opens
-the ``Emacs'' icon, the Android system looks up and starts the
-component associated with the ``Emacs'' icon.  In this case, the
-component is called an activity, and is declared in
-the AndroidManifest.xml in this directory:
-
-    <activity android:name="org.gnu.emacs.EmacsActivity"
-             android:launchMode="singleTop"
-             android:windowSoftInputMode="adjustResize"
-             android:exported="true"
-             android:configChanges="orientation|screenSize|screenLayout|keyboardHidden">
-      <intent-filter>
-       <action android:name="android.intent.action.MAIN" />
-       <category android:name="android.intent.category.DEFAULT" />
-       <category android:name="android.intent.category.LAUNCHER" />
-      </intent-filter>
-    </activity>
-
-This tells Android to start the activity defined in ``EmacsActivity''
-(defined in org/gnu/emacs/EmacsActivity.java), a class extending the
-Android class ``Activity''.
-
-To do so, the Android system creates an instance of ``EmacsActivity''
-and the window system window associated with it, and eventually calls:
-
-  Activity activity;
-
-  activity.onCreate (...);
-
-But which ``onCreate'' is really called?
-It is actually the ``onCreate'' defined in EmacsActivity.java, as
-it overrides the ``onCreate'' defined in Android's own Activity class:
-
-  @Override
-  public void
-  onCreate (Bundle savedInstanceState)
-  {
-    FrameLayout.LayoutParams params;
-    Intent intent;
-
-Then, this is what happens step-by-step within the ``onCreate''
-function:
-
-    /* See if Emacs should be started with -Q. */
-    intent = getIntent ();
-    EmacsService.needDashQ
-      = intent.getBooleanExtra ("org.gnu.emacs.START_DASH_Q",
-                               false);
-
-Here, Emacs obtains the intent (a request to start a component) which
-was used to start Emacs, and sets a special flag if it contains a
-request for Emacs to start with the ``-Q'' command-line argument.
-
-    /* Set the theme to one without a title bar.  */
-
-    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
-      setTheme (android.R.style.Theme_DeviceDefault_NoActionBar);
-    else
-      setTheme (android.R.style.Theme_NoTitleBar);
-
-Next, Emacs sets an appropriate theme for the activity's associated
-window decorations.
-
-    params = new FrameLayout.LayoutParams (LayoutParams.MATCH_PARENT,
-                                          LayoutParams.MATCH_PARENT);
-
-    /* Make the frame layout.  */
-    layout = new FrameLayout (this);
-    layout.setLayoutParams (params);
-
-    /* Set it as the content view.  */
-    setContentView (layout);
-
-Then, Emacs creates a ``FrameLayout'', a widget that holds a single
-other widget, and makes it the activity's ``content view''.
-
-The activity itself is a ``FrameLayout'', so the ``layout parameters''
-here apply to the FrameLayout itself, and not its children.
-
-    /* Maybe start the Emacs service if necessary.  */
-    EmacsService.startEmacsService (this);
-
-And after that, Emacs calls the static function ``startEmacsService'',
-defined in the class ``EmacsService''. This starts the Emacs service
-component if necessary.
-
-    /* Add this activity to the list of available activities.  */
-    EmacsWindowAttachmentManager.MANAGER.registerWindowConsumer (this);
-
-    super.onCreate (savedInstanceState);
-
-Finally, Emacs registers that this activity is now ready to receive
-top-level frames (windows) created from Lisp.
-
-Activities come and go, but Emacs has to stay running in the mean
-time.  Thus, Emacs also defines a ``service'', which is a long-running
-component that the Android system allows to run in the background.
-
-Let us go back and review the definition of ``startEmacsService'':
-
-  public static void
-  startEmacsService (Context context)
-  {
-    if (EmacsService.SERVICE == null)
-      {
-       if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
-         /* Start the Emacs service now.  */
-         context.startService (new Intent (context,
-                                           EmacsService.class));
-       else
-         /* Display the permanant notification and start Emacs as a
-            foreground service.  */
-         context.startForegroundService (new Intent (context,
-                                                     EmacsService.class));
-      }
-  }
-
-If ``EmacsService.SERVICE'' does not yet exist, what this does is to
-tell the ``context'' (the equivalent of an Xlib Display *) to start a
-service defined by the class ``EmacsService''. Eventually, this
-results in ``EmacsService.onCreate'' being called:
-
-  @Override
-  public void
-  onCreate ()
-  {
-    AssetManager manager;
-    Context app_context;
-    String filesDir, libDir, cacheDir, classPath;
-    double pixelDensityX;
-    double pixelDensityY;
-
-Here is what this function does, step-by-step:
-
-    SERVICE = this;
-
-First, it sets the special static variable ``SERVICE'' to ``this'',
-which is a pointer to the ``EmacsService' object that was created.
-
-    handler = new Handler (Looper.getMainLooper ());
-
-Next, it creates a ``Handler'' object for the ``main looper''.
-This is a helper structure which allows executing code on the Android
-user interface thread.
-
-    manager = getAssets ();
-    app_context = getApplicationContext ();
-    metrics = getResources ().getDisplayMetrics ();
-    pixelDensityX = metrics.xdpi;
-    pixelDensityY = metrics.ydpi;
-
-Finally, it obtains:
-
-  - the asset manager, which is used to retrieve assets packaged
-    into the Emacs application package.
-
-  - the application context, used to obtain application specific
-    information.
-
-  - the display metrics, and from them, the X and Y densities in dots
-    per inch.
-
-Then, inside a ``try'' block:
-
-    try
-      {
-       /* Configure Emacs with the asset manager and other necessary
-          parameters.  */
-       filesDir = app_context.getFilesDir ().getCanonicalPath ();
-       libDir = getLibraryDirectory ();
-       cacheDir = app_context.getCacheDir ().getCanonicalPath ();
-
-It obtains the names of the Emacs home, shared library, and temporary
-file directories.
-
-       /* Now provide this application's apk file, so a recursive
-          invocation of app_process (through android-emacs) can
-          find EmacsNoninteractive.  */
-       classPath = getApkFile ();
-
-The name of the Emacs application package.
-
-       Log.d (TAG, "Initializing Emacs, where filesDir = " + filesDir
-              + ", libDir = " + libDir + ", and classPath = " + classPath);
-
-Prints a debug message to the Android system log with this
-information.
-
-       EmacsNative.setEmacsParams (manager, filesDir, libDir,
-                                   cacheDir, (float) pixelDensityX,
-                                   (float) pixelDensityY,
-                                   classPath, this);
-
-And calls the native function ``setEmacsParams'' (defined in
-android.c) to configure Emacs with this information.
-
-       /* Start the thread that runs Emacs.  */
-       thread = new EmacsThread (this, needDashQ);
-       thread.start ();
-
-Then, it allocates an ``EmacsThread'' object, and starts that thread.
-Inside that thread is where Emacs's C code runs.
-
-      }
-    catch (IOException exception)
-      {
-       EmacsNative.emacsAbort ();
-       return;
-
-And here is the purpose of the ``try'' block.  Functions related to
-file names in Java will signal errors of various types upon failure.
-
-This ``catch'' block means that the Java virtual machine will abort
-execution of the contents of the ``try'' block as soon as an error of
-type ``IOException'' is encountered, and begin executing the contents
-of the ``catch'' block.
-
-Any failure of that type here is a crash, and
-``EmacsNative.emacsAbort'' is called to quickly abort the process to
-get a useful backtrace.
-      }
-  }
-
-Now, let us look at the definition of the class ``EmacsThread'', found
-in org/gnu/emacs/EmacsThread.java:
-
-public class EmacsThread extends Thread
-{
-  /* Whether or not Emacs should be started -Q.         */
-  private boolean startDashQ;
-
-  public
-  EmacsThread (EmacsService service, boolean startDashQ)
-  {
-    super ("Emacs main thread");
-    this.startDashQ = startDashQ;
-  }
-
-  @Override
-  public void
-  run ()
-  {
-    String args[];
-
-    if (!startDashQ)
-      args = new String[] { "libandroid-emacs.so", };
-    else
-      args = new String[] { "libandroid-emacs.so", "-Q", };
-
-    /* Run the native code now.         */
-    EmacsNative.initEmacs (args, EmacsApplication.dumpFileName);
-  }
-};
-
-The class itself defines a single field, ``startDashQ'', a constructor
-with an unused argument of the type ``EmacsService'' (which is useful
-while debugging) and a flag ``startDashQ'', and a single function
-``run'', overriding the same function in the class ``Thread''.
-
-When ``thread.start'' is called, the Java virtual machine creates a
-new thread, and then calls the function ``run'' within that thread.
-
-This function then computes a suitable argument vector, and calls
-``EmacsNative.initEmacs'' (defined in android.c), which then calls a
-modified version of the regular Emacs ``main'' function.
-
-At that point, Emacs initialization proceeds as usual:
-Vinitial_window_system is set, loadup.el calls `normal-top-level',
-which calls `command-line', and finally
-`window-system-initialization', which initializes the `android'
-terminal interface as usual.
-
-What happens here is the same as on other platforms.  Now, here is
-what happens when the initial frame is created: Fx_create_frame calls
-`android_create_frame_window' to create a top level window:
-
-static void
-android_create_frame_window (struct frame *f)
-{
-  struct android_set_window_attributes attributes;
-  enum android_window_value_mask attribute_mask;
-
-  attributes.background_pixel = FRAME_BACKGROUND_PIXEL (f);
-  attribute_mask = ANDROID_CW_BACK_PIXEL;
-
-  block_input ();
-  FRAME_ANDROID_WINDOW (f)
-    = android_create_window (FRAME_DISPLAY_INFO (f)->root_window,
-                            f->left_pos,
-                            f->top_pos,
-                            FRAME_PIXEL_WIDTH (f),
-                            FRAME_PIXEL_HEIGHT (f),
-                            attribute_mask, &attributes);
-  unblock_input ();
-}
-
-This calls the function `android_create_window' with some arguments
-whose meanings are identical to the arguments to `XCreateWindow'.
-
-Here is the definition of `android_create_window', in android.c:
-
-android_window
-android_create_window (android_window parent, int x, int y,
-                      int width, int height,
-                      enum android_window_value_mask value_mask,
-                      struct android_set_window_attributes *attrs)
-{
-  static jclass class;
-  static jmethodID constructor;
-  jobject object, parent_object, old;
-  android_window window;
-  android_handle prev_max_handle;
-  bool override_redirect;
-
-What does it do? First, some context:
-
-At any time, there can be at most 65535 Java objects referred to by
-the rest of Emacs through the Java native interface.  Each such object
-is assigned a ``handle'' (similar to an XID on X) and given a unique
-type.  The function `android_resolve_handle' returns the JNI `jobject'
-associated with a given handle.
-
-  parent_object = android_resolve_handle (parent, ANDROID_HANDLE_WINDOW);
-
-Here, it is being used to look up the `jobject' associated with the
-`parent' handle.
-
-  prev_max_handle = max_handle;
-  window = android_alloc_id ();
-
-Next, `max_handle' is saved, and a new handle is allocated for
-`window'.
-
-  if (!window)
-    error ("Out of window handles!");
-
-An error is signalled if Emacs runs out of available handles.
-
-  if (!class)
-    {
-      class = (*android_java_env)->FindClass (android_java_env,
-                                             "org/gnu/emacs/EmacsWindow");
-      assert (class != NULL);
-
-Then, if this initialization has not yet been completed, Emacs
-proceeds to find the Java class named ``EmacsWindow''.
-
-      constructor
-       = (*android_java_env)->GetMethodID (android_java_env, class, "<init>",
-                                           "(SLorg/gnu/emacs/EmacsWindow;"
-                                           "IIIIZ)V");
-      assert (constructor != NULL);
-
-And it tries to look up the constructor, which should take seven
-arguments:
-
-  S                                    - a short.  (the handle ID)
-  Lorg/gnu/Emacs/EmacsWindow;          - an instance of the EmacsWindow
-                                         class.  (the parent)
-  IIII                                 - four ints.  (the window geometry.)
-  Z                                    - a boolean.  (whether or not the
-                                         window is override-redirect; see
-                                         XChangeWindowAttributes.)
-
-      old = class;
-      class = (*android_java_env)->NewGlobalRef (android_java_env, class);
-      (*android_java_env)->ExceptionClear (android_java_env);
-      ANDROID_DELETE_LOCAL_REF (old);
-
-Next, it saves a global reference to the class and deletes the local
-reference.  Global references will never be deallocated by the Java
-virtual machine as long as they still exist.
-
-      if (!class)
-       memory_full (0);
-    }
-
-  /* N.B. that ANDROID_CW_OVERRIDE_REDIRECT can only be set at window
-     creation time.  */
-  override_redirect = ((value_mask
-                       & ANDROID_CW_OVERRIDE_REDIRECT)
-                      && attrs->override_redirect);
-
-  object = (*android_java_env)->NewObject (android_java_env, class,
-                                          constructor, (jshort) window,
-                                          parent_object, (jint) x, (jint) y,
-                                          (jint) width, (jint) height,
-                                          (jboolean) override_redirect);
-
-Then, it creates an instance of the ``EmacsWindow'' class with the
-appropriate arguments and previously determined constructor.
-
-  if (!object)
-    {
-      (*android_java_env)->ExceptionClear (android_java_env);
-
-      max_handle = prev_max_handle;
-      memory_full (0);
-
-If creating the object fails, Emacs clears the ``pending exception''
-and signals that it is out of memory.
-    }
-
-  android_handles[window].type = ANDROID_HANDLE_WINDOW;
-  android_handles[window].handle
-    = (*android_java_env)->NewGlobalRef (android_java_env,
-                                        object);
-  (*android_java_env)->ExceptionClear (android_java_env);
-  ANDROID_DELETE_LOCAL_REF (object);
-
-Otherwise, it associates a new global reference to the object with the
-handle, and deletes the local reference returned from the JNI
-NewObject function.
-
-  if (!android_handles[window].handle)
-    memory_full (0);
-
-If allocating the global reference fails, Emacs signals that it is out
-of memory.
-
-  android_change_window_attributes (window, value_mask, attrs);
-  return window;
-
-Otherwise, it applies the specified window attributes and returns the
-handle of the new window.
-}
-
-\f
-
-DRAWABLES, CURSORS AND HANDLES
-
-Each widget created by Emacs corresponds to a single ``window'', which
-has its own backing store.  This arrangement is quite similar to X.
-
-C code does not directly refer to the EmacsView widgets that implement
-the UI logic behind windows.  Instead, its handles refer to
-EmacsWindow structures, which contain the state necessary to interact
-with the widgets in an orderly and synchronized manner.
-
-Like X, both pixmaps and windows are drawable resources, and the same
-graphics operations can be applied to both.  Thus, a separate
-EmacsPixmap structure is used to wrap around Android Bitmap resources,
-and the Java-level graphics operation functions are capable of
-operating on them both.
-
-Finally, graphics contexts are maintained on both the C and Java
-levels; the C state recorded in `struct android_gc' is kept in sync
-with the Java state in the GContext handle's corresponding EmacsGC
-structure, and cursors are used through handles that refer to
-EmacsCursor structures that hold system PointerIcons.
-
-In all cases, the interfaces provided are identical to X.
-
-\f
-
-EVENT LOOP
-
-In a typical Android application, the event loop is managed by the
-operating system, and callbacks (implemented through overriding
-separate functions in widgets) are run by the event loop wherever
-necessary.  The thread which runs the event loop is also the only
-thread capable of creating and manipulating widgets and activities,
-and is referred to as the ``UI thread''.
-
-These callbacks are used by Emacs to write representations of X-like
-events to a separate event queue, which are then read from Emacs's own
-event loop running in a separate thread.  This is accomplished through
-replacing `select' by a function which waits for the event queue to be
-occupied, in addition to any file descriptors that `select' would
-normally wait for.
-
-Conversely, Emacs's event loop sometimes needs to send events to the
-UI thread.  These events are implemented as tiny fragments of code,
-which are run as they are received by the main thread.
-
-A typical example is `displayToast', which is implemented in
-EmacsService.java:
-
-  public void
-  displayToast (final String string)
-  {
-    runOnUiThread (new Runnable () {
-       @Override
-       public void
-       run ()
-       {
-         Toast toast;
-
-         toast = Toast.makeText (getApplicationContext (),
-                                 string, Toast.LENGTH_SHORT);
-         toast.show ();
-       }
-      });
-  }
-
-Here, the variable `string' is used by a nested function.  This nested
-function contains a copy of that variable, and is run on the main
-thread using the function `runOnUiThread', in order to display a short
-status message on the display.
-
-When Emacs needs to wait for the nested function to finish, it uses a
-mechanism implemented in `syncRunnable'.  This mechanism first calls a
-deadlock avoidance mechanism, then runs a nested function on the UI
-thread, which is expected to signal itself as a condition variable
-upon completion.  It is typically used to allocate resources that can
-only be allocated from the UI thread, or to obtain non-thread-safe
-information.  The following function is an example; it returns a new
-EmacsView widget corresponding to the provided window:
-
-  public EmacsView
-  getEmacsView (final EmacsWindow window, final int visibility,
-               final boolean isFocusedByDefault)
-  {
-    Runnable runnable;
-    final EmacsHolder<EmacsView> view;
-
-    view = new EmacsHolder<EmacsView> ();
-
-    runnable = new Runnable () {
-       public void
-       run ()
-       {
-         synchronized (this)
-           {
-             view.thing = new EmacsView (window);
-             view.thing.setVisibility (visibility);
-
-             /* The following function is only present on Android 26
-                or later.  */
-             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
-               view.thing.setFocusedByDefault (isFocusedByDefault);
-
-             notify ();
-           }
-       }
-      };
-
-    syncRunnable (runnable);
-    return view.thing;
-  }
-
-As no value can be directly returned from the nested function, a
-separate container object is used to hold the result after the
-function finishes execution.  Note the type name inside the angle
-brackets: this type is substituted into the class definition as it is
-used; a definition such as:
-
-public class Foo<T>
-{
-  T bar;
-};
-
-can not be used alone:
-
-  Foo holder; /* Error! */
-
-but must have a type specified:
-
-  Foo<Object> holder;
-
-in which case the effective definition is:
-
-public class Foo
-{
-  Object bar;
-};
+Refer to the file `admin/notes/java' in the toplevel directory of the
+Emacs distribution or repository for specifics regarding writing Java
+code for Emacs and the organization of the Android port.