master 850cbdfa1be 1/2: Update to Android 17

Po Lu via Mailing list for Emacs changes <[email protected]> Thu, 2 Jul 2026 08:16:34 -0400 (EDT)
Newsgroups gmane.emacs.diffs
Message-ID <[email protected]>
branch: master
commit 850cbdfa1be89f6ede45d304fb3792d1043ef2fa
Author: Po Lu <[email protected]>
Commit: Po Lu <[email protected]>

    Update to Android 17
    
    * configure.ac (emacs_cv_android_x_or_later): Rename from
    `emacs_cv_android_w_or_later', and test for attributes of
    Android 17.
    
    * doc/emacs/android.texi (Android Environment): Document new
    permission `ACCESS_LOCAL_NETWORK'.
    
    * java/AndroidManifest.xml.in: Declare permission
    android.permission.ACCESS_LOCAL_NETWORK to re-enable Emacs to
    access local network devices.  Update `targetSdkVersion' to 37.
    
    * java/INSTALL: Document new build-time requirements and
    compatibility with recent build-tools releases.
    
    * java/org/gnu/emacs/EmacsFillPolygon.java (perform): Use
    non-deprecated variant of `Path#computeBounds'.
    
    * src/android-asset.h (struct AAsset): <bytes_read>: New field.
    (AAssetManager_open): Clear exceptions if no asset fd could be
    created.
    (android_asset_read_internal): Cast `buffer' to (jbyte *).
    Record number of bytes read from the InputStream.
    (AAsset_seek): Attempt to satisfy seek operations which do not
    modify the file pointer.
---
 configure.ac                             |  6 ++--
 doc/emacs/android.texi                   |  2 ++
 etc/NEWS                                 |  9 ++++++
 java/AndroidManifest.xml.in              |  6 +++-
 java/INSTALL                             | 18 +++++-------
 java/org/gnu/emacs/EmacsFillPolygon.java | 10 ++-----
 src/android-asset.h                      | 48 ++++++++++++++++++++++++++------
 7 files changed, 68 insertions(+), 31 deletions(-)

diff --git a/configure.ac b/configure.ac
index 8112f37e9ba..f19ba664aac 100644
--- a/configure.ac
+++ b/configure.ac
@@ -966,7 +966,7 @@ a valid path to android.jar.  See config.log for more details.])
   fi
 
   AC_CACHE_CHECK([whether android.jar is new enough],
-    [emacs_cv_android_w_or_later],
+    [emacs_cv_android_x_or_later],
     AS_IF([rm -f conftest.class
 cat << EOF > conftest.java
 
@@ -974,7 +974,7 @@ import android.os.Build;
 
 class conftest
 {
-  private static int test = Build.VERSION_CODES.BAKLAVA;
+  private static int test = Build.VERSION_CODES.CINNAMON_BUN;
 }
 
 EOF
@@ -985,7 +985,7 @@ EOF
 
   if test "$emacs_cv_android_w_or_later" = "no"; then
     AC_MSG_ERROR([Emacs must be built with an android.jar file produced for \
-Android 16 (BAKLAVA) or later.])
+Android 17 (CINNAMON_BUN) or later.])
   fi
 
   dnl See if the Java compiler supports the `--release' option which
diff --git a/doc/emacs/android.texi b/doc/emacs/android.texi
index bc596d766ff..7fb68fe03ea 100644
--- a/doc/emacs/android.texi
+++ b/doc/emacs/android.texi
@@ -529,6 +529,8 @@ version of Android installed:
 @item
 @code{android.permission.ACCESS_LOCATION_EXTRA_COMMANDS}
 @item
+@code{android.permission.ACCESS_LOCAL_NETWORK}
+@item
 @code{android.permission.ACCESS_NETWORK_STATE}
 @item
 @code{android.permission.ACCESS_NOTIFICATION_POLICY}
diff --git a/etc/NEWS b/etc/NEWS
index 5db066a7466..f27ae108ccf 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -231,6 +231,15 @@ method call returns with a D-Bus error; the error is passed as argument.
 
 * Changes in Emacs 32.1 on Non-Free Operating Systems
 
++++
+*** Emacs has been updated to target Android 17.
+
+Emacs has been updated to require the SDK for Android 17 during
+compilation, and to target that version of the operating system.  A
+corollary of this change is that on Android 17 and later systems, it
+must be granted permission to access nearby devices from Settings in
+order to connect to hosts on local networks.
+
 
 ----------------------------------------------------------------------
 This file is part of GNU Emacs.
diff --git a/java/AndroidManifest.xml.in b/java/AndroidManifest.xml.in
index 10e121134e4..9ec1f181811 100644
--- a/java/AndroidManifest.xml.in
+++ b/java/AndroidManifest.xml.in
@@ -206,8 +206,12 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>. -->
 
   <uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE"/>
 
+  <!-- Under Android 17 or later to access local network devices.  -->
+
+  <uses-permission android:name="android.permission.ACCESS_LOCAL_NETWORK"/>
+
   <uses-sdk android:minSdkVersion="@ANDROID_MIN_SDK@"
-	    android:targetSdkVersion="36"/>
+	    android:targetSdkVersion="37"/>
 
   <application android:name="org.gnu.emacs.EmacsApplication"
 	       android:label="Emacs"
diff --git a/java/INSTALL b/java/INSTALL
index f0263037d22..4ad0ffb226c 100644
--- a/java/INSTALL
+++ b/java/INSTALL
@@ -39,7 +39,7 @@ script like so:
 Replacing the paths in the command line above with:
 
   - the path to the `android.jar' headers which come with the Android
-    SDK.  They must correspond to Android version 16 (API level 36).
+    SDK.  They must correspond to Android version 17 (API level 37).
 
   - the path to the C compiler in the Android NDK, for the kind of CPU
     you are building Emacs to run on.
@@ -85,15 +85,10 @@ whose headers have been installed.  Each of these directories in turn
 includes the android.jar archive for that version of Android, also
 necessary for compiling Emacs.
 
-It is imperative that Emacs is compiled using the headers for the
-exact API level that it is written for.  This is currently API level
-35, so the correct android.jar archive is located within a directory
-whose name begins with `android-35'.  Minor revisions to the headers
-are inconsequential towards the Emacs compilation process; if there is
-a directory named `android-35-extN' (where N represents a revision to
-the Android SDK), whether you provide `configure' with that
-directory's android.jar or the android.jar contained within the
-directory named `android-35' is of no special importance.
+It is imperative that Emacs is compiled using the headers for the exact
+API level that it is written for.  This is currently API level 37, so
+the correct android.jar archive is located within a directory whose name
+begins with `android-37.0' or `android-37.1'.
 
 The ndk directory contains one subdirectory for each version of the
 Android NDK installed.  This directory in turn contains the C and C++
@@ -116,7 +111,8 @@ DEX format employed by Android.  There is one subdirectory for each
 version of the build tools, but the version you opt for is not of
 paramount significance: if your version does not work, configure will
 protest, so install a newer one.  We anticipate that most recent
-releases will work, such as those from the 35.0.x and 36.0.x series.
+releases will work, such as those from the 35.0.x, 36.0.x, and 37.0.x
+series.
 
 
 BUILDING WITH OLD NDK VERSIONS
diff --git a/java/org/gnu/emacs/EmacsFillPolygon.java b/java/org/gnu/emacs/EmacsFillPolygon.java
index f960e309eec..a544107daa2 100644
--- a/java/org/gnu/emacs/EmacsFillPolygon.java
+++ b/java/org/gnu/emacs/EmacsFillPolygon.java
@@ -64,14 +64,10 @@ public final class EmacsFillPolygon
     /* Compute the damage rectangle.  */
     rectF = new RectF (0, 0, 0, 0);
 
-    /* computeBounds (IZ) is deprecated but the incompetence of
-       Android's release management has caused its replacement to be
-       omitted from published header files.  */
-
-    /* if (Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM) */
+    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.BAKLAVA)
       path.computeBounds (rectF, true);
-    /* else
-       path.computeBounds (rectF); */
+    else
+       path.computeBounds (rectF);
 
     rect = new Rect ((int) Math.floor (rectF.left),
 		     (int) Math.floor (rectF.top),
diff --git a/src/android-asset.h b/src/android-asset.h
index a531c66a610..01fcd46886e 100644
--- a/src/android-asset.h
+++ b/src/android-asset.h
@@ -72,6 +72,10 @@ struct android_asset
   /* The length of the asset, or -1.  */
   jlong length;
 
+  /* The number of bytes which have already been read from this
+     asset.  */
+  jlong bytes_read;
+
   /* The asset file descriptor and input stream.  */
   jobject fd, stream;
 
@@ -250,6 +254,10 @@ AAssetManager_open (AAssetManager *manager, const char *c_name,
     }
   else /* if (name) */
     {
+      /* If no file descriptor was returned, more recent Android
+	 releases will probably have signaled an exception.  */
+      (*(manager->env))->ExceptionClear (manager->env);
+
       /* Pop the local frame and return name.  */
       name = (*(manager->env))->NewGlobalRef (manager->env, name);
 
@@ -279,7 +287,7 @@ AAssetManager_open (AAssetManager *manager, const char *c_name,
   return NULL;
 }
 
-static AAsset *
+static void
 AAsset_close (AAsset *asset)
 {
   JNIEnv *env;
@@ -341,8 +349,7 @@ android_asset_create_stream (AAsset *asset)
       return 1;
     }
 
-  asset->stream
-    = (*env)->NewGlobalRef (env, stream);
+  asset->stream = (*env)->NewGlobalRef (env, stream);
 
   if (!asset->stream)
     {
@@ -415,7 +422,8 @@ android_asset_read_internal (AAsset *asset, int nbytes, char *buffer)
 
       /* Finally write out the amount that was read.  */
       bytes_read = MIN (bytes_read, nbytes);
-      (*env)->GetByteArrayRegion (env, stash, 0, bytes_read, buffer);
+      (*env)->GetByteArrayRegion (env, stash, 0, bytes_read,
+				  (jbyte *) buffer);
 
       buffer += bytes_read;
       total += bytes_read;
@@ -426,6 +434,7 @@ android_asset_read_internal (AAsset *asset, int nbytes, char *buffer)
   assert (nbytes >= 0);
 
  out:
+  asset->bytes_read += total;
   (*env)->ExceptionClear (env);
   (*env)->DeleteLocalRef (env, stash);
   return total;
@@ -433,6 +442,7 @@ android_asset_read_internal (AAsset *asset, int nbytes, char *buffer)
  out_errno:
   /* Return an error indication if an exception arises while the file
      is being read.  */
+  asset->bytes_read += total;
   (*env)->ExceptionClear (env);
   (*env)->DeleteLocalRef (env, stash);
   errno = EIO;
@@ -459,11 +469,9 @@ AAsset_getLength (AAsset *asset)
 static char *
 AAsset_getBuffer (AAsset *asset)
 {
-  long length;
+  long length = AAsset_getLength (asset);
   char *buffer;
 
-  length = AAsset_getLength (asset);
-
   if (!length)
     return NULL;
 
@@ -472,8 +480,7 @@ AAsset_getBuffer (AAsset *asset)
   if (!buffer)
     return NULL;
 
-  if (android_asset_read_internal (asset, length, buffer)
-      != length)
+  if (android_asset_read_internal (asset, length, buffer) != length)
     {
       free (buffer);
       return NULL;
@@ -492,6 +499,29 @@ AAsset_read (AAsset *asset, void *buffer, size_t size)
 static off_t
 AAsset_seek (AAsset *asset, off_t offset, int whence)
 {
+  /* It is necessary to attempt to satisfy calls to `seek' to identify
+     the current offset or which do not actually move the file pointer,
+     in the interests of scenarios where, e.g., Finsert_file_contents is
+     called with BEG set to 0.  */
+
+  switch (whence)
+    {
+    case SEEK_SET:
+      if (offset == asset->bytes_read)
+	return (off_t) asset->bytes_read;
+
+    case SEEK_CUR:
+      if (offset == 0)
+	return (off_t) asset->bytes_read;
+
+    case SEEK_END:
+      if (offset == 0 && (asset->bytes_read == asset->length))
+	return (off_t) asset->bytes_read;
+
+    default:
+      break;
+    }
+
   /* Java InputStreams don't support seeking at all.  */
   errno = ESPIPE;
   return -1;