/* Android initialization for GNU Emacs.
Copyright (C) 2023-2025 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 . */
#include
#include
#include
#include
#include
/* android-emacs is a wrapper around /system/bin/app_process(64).
It invokes app_process(64) with the right class path and then
starts org.gnu.emacs.EmacsNoninteractive.
The main function in that class tries to load an activity thread
and obtain a context and asset manager before calling
android_emacs_init, which is required for Emacs to find required
preloaded Lisp. */
int
main (int argc, char **argv)
{
char **args;
int i;
char *bootclasspath, *emacs_class_path;
/* Allocate enough to hold the arguments to app_process. */
args = alloca ((10 + argc) * sizeof *args);
/* Clear args. */
memset (args, 0, (10 + argc) * sizeof *args);
/* First, figure out what program to start. */
#if defined __x86_64__ || defined __aarch64__ || defined __mips64
args[0] = (char *) "/system/bin/app_process64";
#else /* i386 || regular mips || arm */
args[0] = (char *) "/system/bin/app_process";
#endif /* __x86_64__ || __aarch64__ || __mips64 */
/* And the Emacs class path. */
emacs_class_path = getenv ("EMACS_CLASS_PATH");
if (!emacs_class_path)
{
fprintf (stderr, "EMACS_CLASS_PATH not set."
" Please make sure Emacs is being started"
" from within a running copy of Emacs.\n");
return 1;
}
if (asprintf (&bootclasspath, "-Djava.class.path=%s",
emacs_class_path) < 0)
{
perror ("asprintf");
return 1;
}
args[1] = bootclasspath;
args[2] = (char *) "/system/bin";
#if HAVE_DECL_ANDROID_GET_DEVICE_API_LEVEL
/* I don't know exactly when --nice-name was introduced; this is
just a guess. */
if (android_get_device_api_level () >= 26)
{
args[3] = (char *) "--nice-name=emacs";
args[4] = (char *) "org.gnu.emacs.EmacsNoninteractive";
/* Arguments from here on are passed to main in
EmacsNoninteractive.java. */
args[5] = argv[0];
/* Now copy the rest of the arguments over. */
for (i = 1; i < argc; ++i)
args[5 + i] = argv[i];
}
else
{
#endif /* HAVE_DECL_ANDROID_GET_DEVICE_API_LEVEL */
args[3] = (char *) "org.gnu.emacs.EmacsNoninteractive";
/* Arguments from here on are passed to main in
EmacsNoninteractive.java. */
args[4] = argv[0];
/* Now copy the rest of the arguments over. */
for (i = 1; i < argc; ++i)
args[4 + i] = argv[i];
#if HAVE_DECL_ANDROID_GET_DEVICE_API_LEVEL
}
#endif /* HAVE_DECL_ANDROID_GET_DEVICE_API_LEVEL */
/* Finally, try to start the app_process. */
execvp (args[0], args);
/* If exit fails, return an error indication. */
perror ("exec");
return 1;
}