summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--INSTALL.android37
-rw-r--r--build-aux/ndk-build-helper-1.mk2
-rw-r--r--configure.ac3
-rw-r--r--cross/ndk-build/ndk-build-shared-library.mk23
-rw-r--r--cross/ndk-build/ndk-build-static-library.mk14
-rw-r--r--cross/ndk-build/ndk-resolve.mk47
-rw-r--r--doc/emacs/android.texi45
-rw-r--r--java/Makefile.in3
-rw-r--r--java/README8
-rw-r--r--java/org/gnu/emacs/EmacsApplication.java54
-rw-r--r--java/org/gnu/emacs/EmacsNative.java4
-rw-r--r--java/org/gnu/emacs/EmacsPreferencesActivity.java27
-rw-r--r--java/org/gnu/emacs/EmacsService.java25
-rw-r--r--java/org/gnu/emacs/EmacsThread.java19
-rw-r--r--lisp/loadup.el146
-rw-r--r--lisp/net/browse-url.el22
-rw-r--r--m4/ndk-build.m42
-rw-r--r--src/android.c61
-rw-r--r--src/android.h4
-rw-r--r--src/androidselect.c20
-rw-r--r--src/emacs.c29
-rw-r--r--src/pdumper.c18
-rw-r--r--src/sfntfont-android.c7
23 files changed, 518 insertions, 102 deletions
diff --git a/INSTALL.android b/INSTALL.android
index 9abea74a55d..79366425125 100644
--- a/INSTALL.android
+++ b/INSTALL.android
@@ -148,6 +148,14 @@ work:
(You must add LOCAL_EXPORT_CFLAGS := -I$(LOCAL_PATH) before
its Android.mk includes $(BUILD_STATIC_LIBRARY))
+In addition, some Emacs dependencies provide `ndk-build' support
+themselves:
+
+ libjansson - https://github.com/akheron/jansson
+ (You must add LOCAL_EXPORT_INCLUDES := $(LOCAL_C_INCLUDES) before
+ its Android.mk includes $(BUILD_SHARED_LIBRARY), then copy
+ android/jansson_config.h to android/jansson_private_config.h.)
+
We anticipate that most untested non-trivial ndk-build dependencies
will need adjustments in Emacs to work, as the Emacs build system
which emulates ndk-build is in an extremely early state.
@@ -173,7 +181,7 @@ one awk script in build-awx, run during configure:
build-aux/ndk-module-extract.awk
-six Makefiles in cross/ndk-build,
+seven Makefiles in cross/ndk-build,
cross/ndk-build/ndk-build-shared-library.mk
cross/ndk-build/ndk-build-static-library.mk
@@ -181,6 +189,7 @@ six Makefiles in cross/ndk-build,
cross/ndk-build/ndk-clear-vars.mk
cross/ndk-build/ndk-prebuilt-shared-library.mk
cross/ndk-build/ndk-prebuilt-static-library.mk
+ cross/ndk-build/ndk-resolve.mk
and finally, two more Makefiles in cross/ndk-build, generated by
configure:
@@ -373,11 +382,27 @@ them. The name under which the module is linked is the same as the
Make target found on the sixth line of output from
build-aux/ndk-build-helper.mk.
-However, none of the Makefiles in
-cross/ndk-build/ndk-build-shared-library.mk perform any kind of
-dependency resolution! Instead, they only define rules to build
-individual modules, leaving dependency resolution up to the Makefiles
-in the `build-aux' directory.
+While the rules defined by the Makefiles in cross/ndk-build do not
+have their dependencies as prerequisites (with the assumption that the
+ndk-build.m4 and the Makefiles in build-aux have already added all of
+the necessary targets to ndk-build.mk), dependency resolution is still
+performed, as the CFLAGS and includes from dependencies must be
+appended to the module's CFLAGS.
+
+This is done by including cross/ndk-build/ndk-resolve.mk each time a
+shared or static library module is going to be built. How is this
+done?
+
+First, ndk-resolve.mk saves the LOCAL_PATH, LOCAL_STATIC_LIBRARIES,
+LOCAL_SHARED_LIBRARIES, LOCAL_EXPORT_CFLAGS and
+LOCAL_EXPORT_C_INCLUDES from the module.
+
+Next, ndk-resolve loops through the dependencies the module has
+specified, appending its CFLAGS and includes to the command line for
+the current module.
+
+Then, that process is repeated for each such dependency which has not
+already been resolved, until all dependencies have been resolved.
libpng is a very simple module, providing only a single shared object
module. This module is named libpng_emacs.so and is eventually built
diff --git a/build-aux/ndk-build-helper-1.mk b/build-aux/ndk-build-helper-1.mk
index fb8e4da2f0a..d20f7d4472f 100644
--- a/build-aux/ndk-build-helper-1.mk
+++ b/build-aux/ndk-build-helper-1.mk
@@ -33,7 +33,7 @@ NDK_$(LOCAL_MODULE)_SHARED_LIBRARIES := $(LOCAL_SHARED_LIBRARIES)
$(info Building $(build_kind))
$(info $(LOCAL_MODULE))
-$(info $(addprefix $(ANDROID_MODULE_DIRECTORY)?,$(LOCAL_SRC_FILES) $(LOCAL_SRC_FILES$(EMACS_ABI))))
+$(info $(addprefix $(ANDROID_MODULE_DIRECTORY)/,$(LOCAL_SRC_FILES) $(LOCAL_SRC_FILES$(EMACS_ABI))))
$(info $(foreach dir,$(LOCAL_EXPORT_C_INCLUDE_DIRS) $(LOCAL_EXPORT_C_INCLUDES),-I$(dir)))
$(info $(LOCAL_EXPORT_CFLAGS))
diff --git a/configure.ac b/configure.ac
index 9df4a6a073f..f3a4b4301a4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1045,6 +1045,7 @@ package will likely install on older systems but crash on startup.])
passthrough="$passthrough --with-png=$with_png"
passthrough="$passthrough --with-webp=$with_webp"
passthrough="$passthrough --with-gif=$with_gif"
+ passthrough="$passthrough --with-json=$with_json"
AS_IF([XCONFIGURE=android ANDROID_CC="$ANDROID_CC" \
ANDROID_SDK="$android_sdk" android_abi=$android_abi \
@@ -1112,6 +1113,7 @@ if test "$ANDROID" = "yes"; then
with_png=no
with_webp=no
with_gif=no
+ with_json=no
fi
with_xml2=no
@@ -1121,7 +1123,6 @@ if test "$ANDROID" = "yes"; then
with_libsystemd=no
with_cairo=no
with_imagemagick=no
- with_json=no
with_tree_sitter=no
with_xft=no
with_harfbuzz=no
diff --git a/cross/ndk-build/ndk-build-shared-library.mk b/cross/ndk-build/ndk-build-shared-library.mk
index 0d90d89e55d..c4fb523a0c1 100644
--- a/cross/ndk-build/ndk-build-shared-library.mk
+++ b/cross/ndk-build/ndk-build-shared-library.mk
@@ -44,11 +44,13 @@ ALL_OBJECT_FILES$(LOCAL_MODULE) += $(call objname,$(LOCAL_MODULE),$(basename $(1
endef
-NDK_CFLAGS_$(LOCAL_MODULE) := $(addprefix -I,$(addprefix $(LOCAL_PATH),$(LOCAL_C_INCLUDES)))
-NDK_CFLAGS_$(LOCAL_MODULE) ::= -fPIC -iquote $(LOCAL_EXPORT_CFLAGS) $(LOCAL_PATH) $(LOCAL_CFLAGS)
-NDK_LDFLAGS_$(LOCAL_MODULE) := $(LOCAL_LDLIBS)
-NDK_LDFLAGS_$(LOCAL_MODULE) := $(LOCAL_LDFLAGS)
-ALL_OBJECT_FILES_$(LOCAL_MODULE) :=
+# Make sure to not add a prefix to local includes that already specify
+# $(LOCAL_PATH).
+NDK_CFLAGS_$(LOCAL_MODULE) := $(addprefix -I,$(LOCAL_C_INCLUDES))
+NDK_CFLAGS_$(LOCAL_MODULE) += -fPIC -iquote $(LOCAL_PATH) $(LOCAL_EXPORT_CFLAGS) $(LOCAL_CFLAGS) $(LOCAL_CFLAGS$(NDK_BUILD_ARCH))
+NDK_ASFLAGS_$(LOCAL_MODULE) := $(LOCAL_ASFLAGS) $(LOCAL_ASFLAGS_$(NDK_BUILD_ARCH))
+NDK_LDFLAGS_$(LOCAL_MODULE) := $(LOCAL_LDLIBS) $(LOCAL_LDFLAGS)
+ALL_OBJECT_FILES$(LOCAL_MODULE) :=
ifeq ($(NDK_BUILD_ARCH)$(NDK_ARM_MODE),armarm)
NDK_CFLAGS ::= -marm
@@ -74,8 +76,17 @@ endif
LOCAL_MODULE_FILENAME := $(LOCAL_MODULE_FILENAME).so
+# Record this module's dependencies and exported includes and CFLAGS,
+# and then add that of its dependencies.
+
+include ndk-resolve.mk
+
# Then define rules to build all objects.
-ALL_SOURCE_FILES = $(LOCAL_SRC_FILES)
+ALL_SOURCE_FILES = $(LOCAL_SRC_FILES) $(LOCAL_SRC_FILES_$(NDK_BUILD_ARCH))
+
+# This defines all dependencies.
+ALL_OBJECT_FILES$(LOCAL_MODULE) =
+
$(foreach source,$(ALL_SOURCE_FILES),$(eval $(call single-object-target,$(source))))
# Now define the rule to build the shared library.
diff --git a/cross/ndk-build/ndk-build-static-library.mk b/cross/ndk-build/ndk-build-static-library.mk
index 1423cf243cf..2eddb215429 100644
--- a/cross/ndk-build/ndk-build-static-library.mk
+++ b/cross/ndk-build/ndk-build-static-library.mk
@@ -43,11 +43,10 @@ endif
ALL_OBJECT_FILES$(LOCAL_MODULE) += $(call objname,$(LOCAL_MODULE),$(basename $(1)))
endef
-NDK_CFLAGS_$(LOCAL_MODULE) := $(addprefix -I,$(addprefix $(LOCAL_PATH),$(LOCAL_C_INCLUDES)))
-NDK_CFLAGS_$(LOCAL_MODULE) ::= -iquote $(LOCAL_PATH) $(LOCAL_EXPORT_CFLAGS) $(LOCAL_CFLAGS) $(LOCAL_CFLAGS_$(NDK_BUILD_ARCH))
-NDK_ASFLAGS_$(LOCAL_MODULE) ::= $(LOCAL_ASFLAGS) $(LOCAL_ASFLAGS_$(NDK_BUILD_ARCH))
-NDK_LDFLAGS_$(LOCAL_MODULE) := $(LOCAL_LDLIBS)
-NDK_LDFLAGS_$(LOCAL_MODULE) := $(LOCAL_LDFLAGS)
+NDK_CFLAGS_$(LOCAL_MODULE) := $(addprefix -I,$(LOCAL_C_INCLUDES))
+NDK_CFLAGS_$(LOCAL_MODULE) += -iquote $(LOCAL_PATH) $(LOCAL_EXPORT_CFLAGS) $(LOCAL_CFLAGS) $(LOCAL_CFLAGS_$(NDK_BUILD_ARCH))
+NDK_ASFLAGS_$(LOCAL_MODULE) := $(LOCAL_ASFLAGS) $(LOCAL_ASFLAGS_$(NDK_BUILD_ARCH))
+NDK_LDFLAGS_$(LOCAL_MODULE) := $(LOCAL_LDLIBS) $(LOCAL_LDFLAGS)
ALL_OBJECT_FILES$(LOCAL_MODULE) :=
ifeq ($(NDK_BUILD_ARCH)$(NDK_ARM_MODE),armarm)
@@ -70,6 +69,11 @@ endif
LOCAL_MODULE_FILENAME := $(LOCAL_MODULE_FILENAME).a
+# Record this module's dependencies and exported includes and CFLAGS,
+# and then add that of its dependencies.
+
+include ndk-resolve.mk
+
# Then define rules to build all objects.
ALL_SOURCE_FILES = $(LOCAL_SRC_FILES) $(LOCAL_SRC_FILES_$(NDK_BUILD_ARCH))
diff --git a/cross/ndk-build/ndk-resolve.mk b/cross/ndk-build/ndk-resolve.mk
new file mode 100644
index 00000000000..29dd5c9908d
--- /dev/null
+++ b/cross/ndk-build/ndk-resolve.mk
@@ -0,0 +1,47 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>.
+
+# ndk-build works by including a bunch of Makefiles which set
+# variables, and then having those Makefiles include another makefile
+# which actually builds targets.
+
+# Save information.
+NDK_LOCAL_PATH_$(LOCAL_MODULE) := $(LOCAL_PATH)
+NDK_LOCAL_STATIC_LIBRARIES_$(LOCAL_MODULE) := $(LOCAL_STATIC_LIBRARIES) $(LOCAL_WHOLE_STATIC_LIBRARIES)
+NDK_LOCAL_SHARED_LIBRARIES_$(LOCAL_MODULE) := $(LOCAL_SHARED_LIBRARIES)
+NDK_LOCAL_EXPORT_CFLAGS_$(LOCAL_MODULE) := $(LOCAL_EXPORT_CFLAGS)
+NDK_LOCAL_EXPORT_C_INCLUDES_$(LOCAL_MODULE) := $(LOCAL_EXPORT_C_INCLUDES)
+
+# List of all dependencies resolved for this module thus far.
+# Used to avoid infinite recursion.
+NDK_RESOLVED_$(LOCAL_MODULE) :=
+
+define ndk-resolve
+
+ifeq ($(patsubst $(1),,$(NDK_RESOLVED$(LOCAL_MODULE))),$(NDK_RESOLVED$(LOCAL_MODULE)))
+NDK_RESOLVED$(LOCAL_MODULE) += $(1)
+NDK_CFLAGS_$(LOCAL_MODULE) += $(NDK_LOCAL_EXPORT_CFLAGS_$(1))
+NDK_CFLAGS_$(LOCAL_MODULE) += $(addprefix -I,$(NDK_LOCAL_EXPORT_C_INCLUDES_$(1)))
+
+$$(foreach module,$$(NDK_LOCAL_STATIC_LIBRARIES_$(1)),$$(eval $$(call ndk-resolve,$$(module))))
+$$(foreach module,$$(NDK_LOCAL_SHARED_LIBRARIES_$(1)),$$(eval $$(call ndk-resolve,$$(module))))
+endif
+
+endef
+
+$(foreach module,$(LOCAL_SHARED_LIBRARIES),$(eval $(call ndk-resolve,$(module))))
+$(foreach module,$(LOCAL_STATIC_LIBRARIES) $(LOCAL_WHOLE_STATIC_LIBRARIES),$(eval $(call ndk-resolve,$(module))))
diff --git a/doc/emacs/android.texi b/doc/emacs/android.texi
index e4498da401d..cda0eadf226 100644
--- a/doc/emacs/android.texi
+++ b/doc/emacs/android.texi
@@ -63,18 +63,18 @@ package manager. Instead, Emacs is compiled for Android on a
different operating system, with the resulting binaries packaged into
an archive, that is then transferred to the device and unpacked.
-After being unpacked, Emacs instructs the system to display an
+ After being unpacked, Emacs instructs the system to display an
application icon on the desktop. Emacs then starts up once the
application icon is clicked.
@cindex ``adb logcat''
-During startup, Emacs will display messages in the system log buffer;
-reading that buffer requires the Android Debug Bridge (@code{adb})
-utility to be installed on another computer; it cannot be read on the
-computer running Android itself.
+ During startup, Emacs will display messages in the system log
+buffer; reading that buffer requires the Android Debug Bridge
+(@code{adb}) utility to be installed on another computer; it cannot be
+read on the computer running Android itself.
-After enabling the ``USB Debugging'' feature on the Android system,
+ After enabling the ``USB Debugging'' feature on the Android system,
and connecting it via USB to another system with the @code{adb}
utility installed, the log can be viewed by running the following
command on that other system:
@@ -84,14 +84,31 @@ $ adb logcat | grep -E "(android_run_debug_thread|[Ee]macs)"
@end example
@cindex emacs -Q, android
-Since Android has no command line, there is normally no way to specify
-command-line arguments. However, Emacs can be started with the
-equivalent of the @code{--quick} option (@pxref{Initial Options})
-through a special preferences screen, which can be accessed through
-the Emacs ``app info'' page in the system settings application.
-
-Consult the manufacturer of your device for more details, as how to do
-this varies by device.
+ Since Android has no command line, there is normally no way to
+specify command-line arguments when starting Emacs. However, Emacs
+can be started with the equivalent of the @code{--quick} option
+(@pxref{Initial Options}) through a special preferences screen, which
+can be accessed through the Emacs ``app info'' page in the system
+settings application.
+
+ Consult the manufacturer of your device for more details, as how to
+do this varies by device.
+
+@cindex dumping, android
+ The first time any given copy of Emacs starts on a device, it spends
+a while loading the preloaded Lisp files which normally come with
+Emacs. This produces a ``dump file'' (@pxref{Initial Options}) in the
+files directory, containing an identifier unique to this copy of
+Emacs.
+
+ The next time that same copy of Emacs starts up, it simply loads the
+preloaded Lisp files contained in that dump file, greatly improving
+start up time.
+
+ However, if by some unforseen circumstance the dump file is
+corrupted, Emacs can crash. If that happens, the dump file stored in
+the Emacs files directory can be erased through the same preferences
+screen.
@node Android File System
@section What files Emacs can access under Android
diff --git a/java/Makefile.in b/java/Makefile.in
index d27775ea3db..b5e0cd7bb56 100644
--- a/java/Makefile.in
+++ b/java/Makefile.in
@@ -148,8 +148,7 @@ emacs.apk-in: $(CROSS_BINS) $(CROSS_LIBS) $(libsrc)/asset-directory-tool \
cp -f $$file install_temp/lib/$(ANDROID_ABI); \
fi \
done
- $(foreach module,$(NDK_BUILD_SHARED), \
- cp -f $(module) install_temp/lib/$(ANDROID_ABI))
+ cp -f $(NDK_BUILD_SHARED) install_temp/lib/$(ANDROID_ABI)
# Package everything. Specifying the assets on this command line is
# necessary for AAssetManager_getNextFileName to work on old versions
# of Android.
diff --git a/java/README b/java/README
index 50c2332ce95..05edf7744de 100644
--- a/java/README
+++ b/java/README
@@ -1,5 +1,11 @@
This directory holds the Java sources of the port of GNU Emacs to
-Android-like systems.
+Android-like systems, along with files needed to create an application
+package out of them.
+
+`emacs.keystore' is the signing key used to build Emacs. It is kept
+here, and we encourage all people redistributing Emacs to use this
+key. It holds no security value, and otherwise it will be impossible
+to install different builds of Emacs on top of each other.
Please keep the Java code indented with tabs and formatted according
to the rules for C code in the GNU coding standards. Always use
diff --git a/java/org/gnu/emacs/EmacsApplication.java b/java/org/gnu/emacs/EmacsApplication.java
index 125da05cfd4..87085c32d62 100644
--- a/java/org/gnu/emacs/EmacsApplication.java
+++ b/java/org/gnu/emacs/EmacsApplication.java
@@ -19,9 +19,59 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
package org.gnu.emacs;
+import java.io.File;
+import java.io.FileFilter;
+
import android.app.Application;
+import android.util.Log;
-public class EmacsApplication extends Application
+public class EmacsApplication extends Application implements FileFilter
{
- /* This class currently does nothing. */
+ private static final String TAG = "EmacsApplication";
+
+ /* The name of the dump file to use. */
+ public static String dumpFileName;
+
+ @Override
+ public boolean
+ accept (File file)
+ {
+ return (!file.isDirectory ()
+ && file.getName ().endsWith (".pdmp"));
+ }
+
+ @Override
+ public void
+ onCreate ()
+ {
+ File filesDirectory;
+ File[] allFiles;
+ String wantedDumpFile;
+ int i;
+
+ wantedDumpFile = ("emacs-" + EmacsNative.getFingerprint ()
+ + ".pdmp");
+
+ Log.d (TAG, "onCreate: looking for " + wantedDumpFile);
+
+ /* Obtain a list of all files ending with ``.pdmp''. Then, look
+ for a file named ``emacs-<fingerprint>.pdmp'' and delete the
+ rest. */
+ filesDirectory = getFilesDir ();
+ allFiles = filesDirectory.listFiles (this);
+
+ /* Now try to find the right dump file. */
+ for (i = 0; i < allFiles.length; ++i)
+ {
+ if (allFiles[i].getName ().equals (wantedDumpFile))
+ dumpFileName = allFiles[i].getAbsolutePath ();
+ else
+ /* Delete this outdated dump file. */
+ allFiles[i].delete ();
+ }
+
+ Log.d (TAG, "onCreate: found " + dumpFileName);
+
+ super.onCreate ();
+ }
};
diff --git a/java/org/gnu/emacs/EmacsNative.java b/java/org/gnu/emacs/EmacsNative.java
index 962538bef7b..9636561a524 100644
--- a/java/org/gnu/emacs/EmacsNative.java
+++ b/java/org/gnu/emacs/EmacsNative.java
@@ -25,6 +25,10 @@ import android.content.res.AssetManager;
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. This proves
that libemacs.so is being loaded from Java code.
diff --git a/java/org/gnu/emacs/EmacsPreferencesActivity.java b/java/org/gnu/emacs/EmacsPreferencesActivity.java
index 0db983984fd..ed1db68f732 100644
--- a/java/org/gnu/emacs/EmacsPreferencesActivity.java
+++ b/java/org/gnu/emacs/EmacsPreferencesActivity.java
@@ -19,6 +19,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
package org.gnu.emacs;
+import java.io.File;
+
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
@@ -93,6 +95,31 @@ public class EmacsPreferencesActivity extends Activity
});
layout.addView (textView);
+ textView = new TextView (this);
+ textView.setPadding (8, 20, 20, 8);
+
+ params = new LinearLayout.LayoutParams (LayoutParams.MATCH_PARENT,
+ LayoutParams.WRAP_CONTENT);
+ textView.setLayoutParams (params);
+ textView.setText ("Erase dump file");
+ textView.setOnClickListener (new View.OnClickListener () {
+ @Override
+ public void
+ onClick (View view)
+ {
+ String wantedDumpFile;
+ File file;
+
+ wantedDumpFile = ("emacs-" + EmacsNative.getFingerprint ()
+ + ".pdmp");
+ file = new File (getFilesDir (), wantedDumpFile);
+
+ if (file.exists ())
+ file.delete ();
+ }
+ });
+ layout.addView (textView);
+
super.onCreate (savedInstanceState);
}
};
diff --git a/java/org/gnu/emacs/EmacsService.java b/java/org/gnu/emacs/EmacsService.java
index 95f21b211a3..4db1ea5359f 100644
--- a/java/org/gnu/emacs/EmacsService.java
+++ b/java/org/gnu/emacs/EmacsService.java
@@ -43,6 +43,8 @@ import android.content.Context;
import android.content.Intent;
import android.content.res.AssetManager;
+import android.net.Uri;
+
import android.os.Build;
import android.os.Looper;
import android.os.IBinder;
@@ -504,4 +506,27 @@ public class EmacsService extends Service
EmacsService.class));
}
}
+
+ /* Ask the system to open the specified URL.
+ Value is NULL upon success, or a string describing the error
+ upon failure. */
+
+ public String
+ browseUrl (String url)
+ {
+ Intent intent;
+
+ try
+ {
+ intent = new Intent (Intent.ACTION_VIEW, Uri.parse (url));
+ intent.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity (intent);
+ }
+ catch (Exception e)
+ {
+ return e.toString ();
+ }
+
+ return null;
+ }
};
diff --git a/java/org/gnu/emacs/EmacsThread.java b/java/org/gnu/emacs/EmacsThread.java
index 21d8612703a..5b76d11db4b 100644
--- a/java/org/gnu/emacs/EmacsThread.java
+++ b/java/org/gnu/emacs/EmacsThread.java
@@ -38,10 +38,23 @@ public class EmacsThread extends Thread
{
String args[];
- if (!startDashQ)
- args = new String[] { "libandroid-emacs.so", };
+ if (EmacsApplication.dumpFileName == null)
+ {
+ if (!startDashQ)
+ args = new String[] { "libandroid-emacs.so", };
+ else
+ args = new String[] { "libandroid-emacs.so", "-Q", };
+ }
else
- args = new String[] { "libandroid-emacs.so", "-Q", };
+ {
+ if (!startDashQ)
+ args = new String[] { "libandroid-emacs.so", "--dump-file",
+ EmacsApplication.dumpFileName, };
+ else
+ args = new String[] { "libandroid-emacs.so", "-Q",
+ "--dump-file",
+ EmacsApplication.dumpFileName, };
+ }
/* Run the native code now. */
EmacsNative.initEmacs (args);
diff --git a/lisp/loadup.el b/lisp/loadup.el
index b9ae8212d2d..8d2e4bbb7c2 100644
--- a/lisp/loadup.el
+++ b/lisp/loadup.el
@@ -550,66 +550,96 @@ lost after dumping")))
-(if dump-mode
- (let ((output (cond ((equal dump-mode "pdump") "emacs.pdmp")
- ((equal dump-mode "dump") "emacs")
- ((equal dump-mode "bootstrap") "emacs")
- ((equal dump-mode "pbootstrap") "bootstrap-emacs.pdmp")
- (t (error "Unrecognized dump mode %s" dump-mode)))))
- (when (and (featurep 'native-compile)
- (equal dump-mode "pdump"))
- ;; Don't enable this before bootstrap is completed, as the
- ;; compiler infrastructure may not be usable yet.
- (setq comp-enable-subr-trampolines t))
- (message "Dumping under the name %s" output)
- (condition-case ()
- (delete-file output)
- (file-error nil))
- ;; On MS-Windows, the current directory is not necessarily the
- ;; same as invocation-directory.
- (let (success)
- (unwind-protect
- (let ((tmp-dump-mode dump-mode)
- (dump-mode nil)
- (lexical-binding nil))
- (if (member tmp-dump-mode '("pdump" "pbootstrap"))
- (dump-emacs-portable (expand-file-name output invocation-directory))
- (dump-emacs output (if (eq system-type 'ms-dos)
- "temacs.exe"
- "temacs"))
- (message "%d pure bytes used" pure-bytes-used))
- (setq success t))
- (unless success
- (ignore-errors
- (delete-file output)))))
- ;; Recompute NAME now, so that it isn't set when we dump.
- (if (not (or (eq system-type 'ms-dos)
- (eq system-type 'haiku) ;; BFS doesn't support hard links
- ;; Don't bother adding another name if we're just
- ;; building bootstrap-emacs.
- (member dump-mode '("pbootstrap" "bootstrap"))))
- (let ((name (format "emacs-%s.%d" emacs-version emacs-build-number))
- (exe (if (eq system-type 'windows-nt) ".exe" "")))
- (while (string-match "[^-+_.a-zA-Z0-9]+" name)
- (setq name (concat (downcase (substring name 0 (match-beginning 0)))
- "-"
- (substring name (match-end 0)))))
- (message "Adding name %s" (concat name exe))
- ;; When this runs on Windows, invocation-directory is not
- ;; necessarily the current directory.
- (add-name-to-file (expand-file-name (concat "emacs" exe)
- invocation-directory)
- (expand-file-name (concat name exe)
- invocation-directory)
- t)
- (when (equal dump-mode "pdump")
- (message "Adding name %s" (concat name ".pdmp"))
- (add-name-to-file (expand-file-name "emacs.pdmp"
+(if (eq system-type 'android)
+ (progn
+ ;; Dumping Emacs on Android works slightly differently from
+ ;; everywhere else. The first time Emacs starts, Emacs dumps
+ ;; itself to "emacs-%s.pdump", and then proceeds with loadup,
+ ;; where %s is replaced by the dump fingerprint.
+ ;; EmacsApplication.java removes any pdump files with a
+ ;; different build fingerprint upon being created, which happens
+ ;; the moment the Android system starts Emacs. Then, it passes
+ ;; the appropriate "--dump-file" to libemacs.so as it starts.
+ (let ((temp-dir (getenv "TEMP"))
+ (dump-file-name (format "%semacs-%s.pdmp"
+ (file-name-as-directory "~")
+ pdumper-fingerprint))
+ (dump-temp-file-name (format "%s~emacs-%s.pdmp"
+ (file-name-as-directory "~")
+ pdumper-fingerprint)))
+ (unless (pdumper-stats)
+ (condition-case ()
+ (progn
+ (dump-emacs-portable dump-temp-file-name)
+ ;; Move the dumped file to the actual dump file name.
+ (rename-file dump-temp-file-name dump-file-name)
+ ;; Continue with loadup.
+ nil)
+ (error nil)))))
+ (if dump-mode
+ (let ((output (cond ((equal dump-mode "pdump") "emacs.pdmp")
+ ((equal dump-mode "dump") "emacs")
+ ((equal dump-mode "bootstrap") "emacs")
+ ((equal dump-mode "pbootstrap") "bootstrap-emacs.pdmp")
+ (t (error "Unrecognized dump mode %s" dump-mode)))))
+ (when (and (featurep 'native-compile)
+ (equal dump-mode "pdump"))
+ ;; Don't enable this before bootstrap is completed, as the
+ ;; compiler infrastructure may not be usable yet.
+ (setq comp-enable-subr-trampolines t))
+ (message "Dumping under the name %s" output)
+ (condition-case ()
+ (delete-file output)
+ (file-error nil))
+ ;; On MS-Windows, the current directory is not necessarily the
+ ;; same as invocation-directory.
+ (let (success)
+ (unwind-protect
+ (let ((tmp-dump-mode dump-mode)
+ (dump-mode nil)
+ (lexical-binding nil))
+ (if (member tmp-dump-mode '("pdump" "pbootstrap"))
+ (dump-emacs-portable (expand-file-name output invocation-directory))
+ (dump-emacs output (if (eq system-type 'ms-dos)
+ "temacs.exe"
+ "temacs"))
+ (message "%d pure bytes used" pure-bytes-used))
+ (setq success t))
+ (unless success
+ (ignore-errors
+ (delete-file output)))))
+ ;; Recompute NAME now, so that it isn't set when we dump.
+ (if (not (or (eq system-type 'ms-dos)
+ (eq system-type 'haiku) ;; BFS doesn't support hard links
+ ;; There's no point keeping old dumps around for
+ ;; the binary used to build Lisp on the build
+ ;; machine.
+ (featurep 'android)
+ ;; Don't bother adding another name if we're just
+ ;; building bootstrap-emacs.
+ (member dump-mode '("pbootstrap" "bootstrap"))))
+ (let ((name (format "emacs-%s.%d" emacs-version emacs-build-number))
+ (exe (if (eq system-type 'windows-nt) ".exe" "")))
+ (while (string-match "[^-+_.a-zA-Z0-9]+" name)
+ (setq name (concat (downcase (substring name 0 (match-beginning 0)))
+ "-"
+ (substring name (match-end 0)))))
+ (message "Adding name %s" (concat name exe))
+ ;; When this runs on Windows, invocation-directory is not
+ ;; necessarily the current directory.
+ (add-name-to-file (expand-file-name (concat "emacs" exe)
invocation-directory)
- (expand-file-name (concat name ".pdmp")
+ (expand-file-name (concat name exe)
invocation-directory)
- t))))
- (kill-emacs)))
+ t)
+ (when (equal dump-mode "pdump")
+ (message "Adding name %s" (concat name ".pdmp"))
+ (add-name-to-file (expand-file-name "emacs.pdmp"
+ invocation-directory)
+ (expand-file-name (concat name ".pdmp")
+ invocation-directory)
+ t))))
+ (kill-emacs))))
;; This file must be loaded each time Emacs is run from scratch, e.g., temacs.
;; So run the startup code now. First, remove `-l loadup' from args.
diff --git a/lisp/net/browse-url.el b/lisp/net/browse-url.el
index 0177d12f236..c2629b69d59 100644
--- a/lisp/net/browse-url.el
+++ b/lisp/net/browse-url.el
@@ -52,6 +52,7 @@
;; browse-url-xdg-open freedesktop.org xdg-open
;; browse-url-kde KDE konqueror (kfm)
;; browse-url-elinks Elinks Don't know (tried with 0.12.GIT)
+;; browse-url-default-android-browser Android 2.3.3 (should work on 2.2 too)
;; eww-browse-url Emacs Web Wowser
;; Browsers can cache web pages so it may be necessary to tell them to
@@ -173,6 +174,9 @@
,@(when (eq system-type 'darwin)
(list '(function-item :tag "Default macOS browser"
:value browse-url-default-macosx-browser)))
+ ,@(when (eq system-type 'android)
+ (list '(function-item :tag "Default Android browser"
+ :value browse-url-default-android-browser)))
(function-item :tag "Default browser"
:value browse-url-default-browser)
(function :tag "Your own function")
@@ -1057,6 +1061,8 @@ instead of `browse-url-new-window-flag'."
'browse-url-default-macosx-browser)
((featurep 'haiku)
'browse-url-default-haiku-browser)
+ ((eq system-type 'android)
+ 'browse-url-default-android-browser)
((browse-url-can-use-xdg-open) 'browse-url-xdg-open)
;;; ((executable-find browse-url-gnome-moz-program) 'browse-url-gnome-moz)
((executable-find browse-url-firefox-program) 'browse-url-firefox)
@@ -1294,6 +1300,22 @@ Default to the URL around or before point."
(function-put 'browse-url-default-haiku-browser
'browse-url-browser-kind 'external)
+(declare-function android-browse-url "androidselect.c")
+
+;;;###autoload
+(defun browse-url-default-android-browser (url &optional _new-window)
+ "Browse URL with the system default browser.
+Default to the URL around or before point."
+ (interactive (browse-url-interactive-arg "URL: "))
+ (setq url (browse-url-encode-url url))
+ ;; Make sure the URL starts with an appropriate scheme.
+ (unless (string-match "\\(.+\\):/" url)
+ (setq url (concat "http://" url)))
+ (android-browse-url url))
+
+(function-put 'browse-url-default-android-browser
+ 'browse-url-browser-kind 'external)
+
;;;###autoload
(defun browse-url-emacs (url &optional same-window)
"Ask Emacs to load URL into a buffer and show it in another window.
diff --git a/m4/ndk-build.m4 b/m4/ndk-build.m4
index a35900884d9..d3614a9f490 100644
--- a/m4/ndk-build.m4
+++ b/m4/ndk-build.m4
@@ -67,7 +67,7 @@ esac
# This is a map between pkg-config style package names and Android
# ones.
-ndk_package_map="libwebpdemux:webpdemux libxml-2.0:libxml2"
+ndk_package_map="libwebpdemux:webpdemux libxml-2.0:libxml2 jansson:libjansson"
# Replace ndk_module with the appropriate Android module name if it is
# found in ndk_package_map.
diff --git a/src/android.c b/src/android.c
index d788c6f19b4..c186b462360 100644
--- a/src/android.c
+++ b/src/android.c
@@ -33,6 +33,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <sys/param.h>
#include <assert.h>
+#include <fingerprint.h>
#include "android.h"
#include "androidgui.h"
@@ -95,6 +96,7 @@ struct android_emacs_service
jmethodID detect_mouse;
jmethodID name_keysym;
jmethodID sync;
+ jmethodID browse_url;
};
struct android_emacs_pixmap
@@ -1294,6 +1296,18 @@ android_get_home_directory (void)
#pragma GCC diagnostic ignored "-Wmissing-prototypes"
#endif
+JNIEXPORT jstring JNICALL
+NATIVE_NAME (getFingerprint) (JNIEnv *env, jobject object)
+{
+ char buffer[sizeof fingerprint * 2 + 1];
+
+ memset (buffer, 0, sizeof buffer);
+ hexbuf_digest (buffer, (char *) fingerprint,
+ sizeof fingerprint);
+
+ return (*env)->NewStringUTF (env, buffer);
+}
+
JNIEXPORT void JNICALL
NATIVE_NAME (setEmacsParams) (JNIEnv *env, jobject object,
jobject local_asset_manager,
@@ -1514,6 +1528,8 @@ android_init_emacs_service (void)
FIND_METHOD (detect_mouse, "detectMouse", "()Z");
FIND_METHOD (name_keysym, "nameKeysym", "(I)Ljava/lang/String;");
FIND_METHOD (sync, "sync", "()V");
+ FIND_METHOD (browse_url, "browseUrl", "(Ljava/lang/String;)"
+ "Ljava/lang/String;");
#undef FIND_METHOD
}
@@ -4735,6 +4751,51 @@ android_project_image_nearest (struct android_image *image,
+/* Other miscellaneous functions. */
+
+/* Ask the system to start browsing the specified encoded URL. Upon
+ failure, return a string describing the error. Else, value is
+ nil. */
+
+Lisp_Object
+android_browse_url (Lisp_Object url)
+{
+ jobject value, string;
+ Lisp_Object tem;
+ const char *buffer;
+
+ string = android_build_string (url);
+ value = (*android_java_env)->CallObjectMethod (android_java_env,
+ emacs_service,
+ service_class.browse_url,
+ string);
+ android_exception_check ();
+
+ ANDROID_DELETE_LOCAL_REF (string);
+
+ /* If no string was returned, return Qnil. */
+ if (!value)
+ return Qnil;
+
+ buffer = (*android_java_env)->GetStringUTFChars (android_java_env,
+ (jstring) value,
+ NULL);
+ android_exception_check ();
+
+ /* Otherwise, build the string describing the error. */
+ tem = build_string_from_utf8 (buffer);
+
+ (*android_java_env)->ReleaseStringUTFChars (android_java_env,
+ (jstring) value,
+ buffer);
+
+ /* And return it. */
+ ANDROID_DELETE_LOCAL_REF (value);
+ return tem;
+}
+
+
+
#else /* ANDROID_STUBIFY */
/* X emulation functions for Android. */
diff --git a/src/android.h b/src/android.h
index eee3a7a6498..ce0ccfc4338 100644
--- a/src/android.h
+++ b/src/android.h
@@ -107,6 +107,10 @@ extern void android_closedir (struct android_dir *);
+/* Very miscellaneous functions. */
+
+extern Lisp_Object android_browse_url (Lisp_Object);
+
#endif
/* JNI functions should not be built when Emacs is stubbed out for the
diff --git a/src/androidselect.c b/src/androidselect.c
index 4a71b376e28..2e2f2d7e483 100644
--- a/src/androidselect.c
+++ b/src/androidselect.c
@@ -213,6 +213,25 @@ DEFUN ("android-clipboard-exists-p", Fandroid_clipboard_exists_p,
return rc ? Qt : Qnil;
}
+DEFUN ("android-browse-url", Fandroid_browse_url,
+ Sandroid_browse_url, 1, 1, 0,
+ doc: /* Start the system web browser.
+Then, point the web browser to URL, which should be a URL-encoded
+URL with a scheme specified. Signal an error upon failure. */)
+ (Lisp_Object url)
+{
+ Lisp_Object value;
+
+ CHECK_STRING (url);
+ value = android_browse_url (url);
+
+ /* Signal an error upon failure. */
+ if (!NILP (value))
+ signal_error ("Error browsing URL", value);
+
+ return Qnil;
+}
+
void
@@ -246,4 +265,5 @@ syms_of_androidselect (void)
defsubr (&Sandroid_set_clipboard);
defsubr (&Sandroid_get_clipboard);
defsubr (&Sandroid_clipboard_exists_p);
+ defsubr (&Sandroid_browse_url);
}
diff --git a/src/emacs.c b/src/emacs.c
index 02016e53c45..b0c19fe0070 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -744,6 +744,8 @@ argmatch (char **argv, int argc, const char *sstr, const char *lstr,
}
}
+#if !defined HAVE_ANDROID || defined ANDROID_STUBIFY
+
/* Find a name (absolute or relative) of the Emacs executable whose
name (as passed into this program) is ARGV0. Called early in
initialization by portable dumper loading code, so avoid Lisp and
@@ -843,6 +845,8 @@ find_emacs_executable (char const *argv0, ptrdiff_t *candidate_size)
#endif /* !WINDOWSNT */
}
+#endif
+
#ifdef HAVE_PDUMPER
static const char *
@@ -875,6 +879,30 @@ dump_error_to_string (int result)
static char *
load_pdump (int argc, char **argv)
{
+#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
+ char *dump_file = NULL;
+ int skip_args = 0, result;
+
+ while (skip_args < argc - 1)
+ {
+ if (argmatch (argv, argc, "-dump-file", "--dump-file", 6,
+ &dump_file, &skip_args)
+ || argmatch (argv, argc, "--", NULL, 2, NULL, &skip_args))
+ break;
+ skip_args++;
+ }
+
+ if (!dump_file)
+ return argv[0];
+
+ result = pdumper_load (dump_file, argv[0]);
+
+ if (result != PDUMPER_LOAD_SUCCESS)
+ fatal ("could not load dump file \"%s\": %s",
+ dump_file, dump_error_to_string (result));
+ return argv[0];
+#else
+
const char *const suffix = ".pdmp";
int result;
char *emacs_executable = argv[0];
@@ -1067,6 +1095,7 @@ load_pdump (int argc, char **argv)
xfree (dump_file);
return emacs_executable;
+#endif
}
#endif /* HAVE_PDUMPER */
diff --git a/src/pdumper.c b/src/pdumper.c
index eca64725211..dbdeae9a799 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -4072,10 +4072,12 @@ types. */)
{
eassert (initialized);
+#ifndef HAVE_ANDROID
if (! noninteractive)
error ("Dumping Emacs currently works only in batch mode. "
"If you'd like it to work interactively, please consider "
"contributing a patch to Emacs.");
+#endif
if (will_dump_with_unexec_p ())
error ("This Emacs instance was started under the assumption "
@@ -5842,6 +5844,10 @@ void
syms_of_pdumper (void)
{
#ifdef HAVE_PDUMPER
+ unsigned char desired[sizeof fingerprint];
+ int i;
+ char hexbuf[2 * sizeof fingerprint];
+
defsubr (&Sdump_emacs_portable);
defsubr (&Sdump_emacs_portable__sort_predicate);
defsubr (&Sdump_emacs_portable__sort_predicate_copied);
@@ -5854,5 +5860,17 @@ syms_of_pdumper (void)
DEFSYM (Qdump_file_name, "dump-file-name");
DEFSYM (Qafter_pdump_load_hook, "after-pdump-load-hook");
defsubr (&Spdumper_stats);
+
+ for (i = 0; i < sizeof fingerprint; i++)
+ desired[i] = fingerprint[i];
+
+ hexbuf_digest (hexbuf, desired, sizeof desired);
+
+ DEFVAR_LISP ("pdumper-fingerprint", Vpdumper_fingerprint,
+ doc: /* The fingerprint of this Emacs binary.
+It is a string that is supposed to be unique to each build of
+Emacs. */);
+ Vpdumper_fingerprint = make_unibyte_string ((char *) hexbuf,
+ sizeof hexbuf);
#endif /* HAVE_PDUMPER */
}
diff --git a/src/sfntfont-android.c b/src/sfntfont-android.c
index 5c9835fb13e..bc8f1b35b84 100644
--- a/src/sfntfont-android.c
+++ b/src/sfntfont-android.c
@@ -320,7 +320,10 @@ sfntfont_android_composite_bitmap (unsigned char *restrict buffer,
{
unsigned int *src_row;
unsigned int *dst_row;
- unsigned int i, src_y, x, src_x, max_x, dst_x, lim_x;
+ unsigned int i, src_y, x, src_x, max_x, dst_x;
+#ifdef __aarch64__
+ unsigned int lim_x;
+#endif
if ((intptr_t) dest & 3 || bitmap_info->stride & 3)
/* This shouldn't be possible as Android is supposed to align the
@@ -353,10 +356,10 @@ sfntfont_android_composite_bitmap (unsigned char *restrict buffer,
src_x = x + (rect->x - text_rectangle->x);
dst_x = x + rect->x;
+#ifdef __aarch64__
/* This is the largest value of src_x. */
lim_x = max_x + (rect->x - text_rectangle->x);
-#ifdef __aarch64__
if (!sfntfont_android_over_8888 (src_row + src_x,
dst_row + dst_x,
src_row + lim_x,