1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-05 22:20:24 -08:00

Merge from savannah/emacs-30

b00fc31dd1 Do not set LD_LIBRARY_PATH during Android initialization
04bf3172f0 ; Set Transient's version
e6f78485aa ; Fix typos in 'which-key-mode' (bug#72093)
This commit is contained in:
Po Lu 2024-07-14 12:47:51 +08:00
commit f9dae55ccc
7 changed files with 153 additions and 153 deletions

View file

@ -30,37 +30,69 @@ import java.lang.reflect.Method;
/* Noninteractive Emacs.
This is the class that libandroid-emacs.so starts.
libandroid-emacs.so figures out the system classpath, then starts
dalvikvm with the framework jars.
At that point, dalvikvm calls main, which sets up the main looper,
creates an ActivityThread and attaches it to the main thread.
Then, it obtains an application context for the LoadedApk in the
application thread.
Finally, it obtains the necessary context specific objects and
initializes Emacs. */
When started, libandroid-emacs.so invokes `app_process(64)' with a
command line placing Emacs's classes.dex file in the JVM class path,
which in turn transfers control to `main'. `main' creates a context,
which may be likened to a connection to the system server, and a
class loader derived from Emacs's application package, which it loads
beforehand. From this class loader, it loads another instance of
itself, and invokes `main1', to ensure the execution of
`EmacsNative''s static initializer within the application class
loader, where a proper library search path is in effect. */
@SuppressWarnings ("unchecked")
public final class EmacsNoninteractive
{
/* Prepare Emacs for startup and call `initEmacs'. This function is
called in an instance of `EmacsNoninteractive' loaded by the APK
ClassLoader acquired in `main', which guarantees that shared
libraries in the APK will be considered in resolving shared
libraries for `EmacsNative'. */
public static void
main1 (String[] args, Context context)
throws Exception
{
AssetManager assets;
String filesDir, libDir, cacheDir;
/* Don't actually start the looper or anything. Instead, obtain
an AssetManager. */
assets = context.getAssets ();
/* Now configure Emacs. The class path should already be set. */
filesDir = context.getFilesDir ().getCanonicalPath ();
libDir = EmacsService.getLibraryDirectory (context);
cacheDir = context.getCacheDir ().getCanonicalPath ();
EmacsNative.setEmacsParams (assets, filesDir,
libDir, cacheDir, 0.0f,
0.0f, 0.0f, null, null,
Build.VERSION.SDK_INT);
/* Now find the dump file that Emacs should use, if it has already
been dumped. */
EmacsApplication.findDumpFile (context);
/* Start Emacs. */
EmacsNative.initEmacs (args, EmacsApplication.dumpFileName);
}
public static void
main (String[] args)
{
Object activityThread, loadedApk;
Class activityThreadClass, loadedApkClass, contextImplClass;
Class compatibilityInfoClass;
Class compatibilityInfoClass, emacsNoninteractiveClass;
Method method;
Context context;
AssetManager assets;
String filesDir, libDir, cacheDir;
ClassLoader classLoader;
Looper.prepare ();
context = null;
assets = null;
filesDir = libDir = cacheDir = null;
loadedApkClass = null;
classLoader = null;
try
{
@ -72,7 +104,6 @@ public final class EmacsNoninteractive
/* Create and attach the activity thread. */
activityThread = method.invoke (null);
context = null;
/* Now get an LoadedApk. */
@ -82,99 +113,88 @@ public final class EmacsNoninteractive
}
catch (ClassNotFoundException exception)
{
/* Android 2.2 has no LoadedApk class, but fortunately it
does not need to be used, since contexts can be
directly created. */
/* Android 2.2 has no LoadedApk class; the several following
statements will load a context and an
ActivityThread.PackageInfo, as is appropriate on this
system. */
}
loadedApkClass = null;
contextImplClass = Class.forName ("android.app.ContextImpl");
/* Get a LoadedApk or ActivityThread.PackageInfo. How to do
this varies by Android version. On Android 2.3.3 and
earlier, there is no ``compatibilityInfo'' argument to
getPackageInfo. */
method = activityThreadClass.getDeclaredMethod ("getSystemContext");
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1)
{
method
= activityThreadClass.getMethod ("getPackageInfo",
String.class,
int.class);
loadedApk = method.invoke (activityThread, "org.gnu.emacs",
(Context.CONTEXT_INCLUDE_CODE
| Context.CONTEXT_IGNORE_SECURITY));
}
else
{
compatibilityInfoClass
= Class.forName ("android.content.res.CompatibilityInfo");
method
= activityThreadClass.getMethod ("getPackageInfo",
String.class,
compatibilityInfoClass,
int.class);
loadedApk = method.invoke (activityThread, "org.gnu.emacs",
null, (Context.CONTEXT_INCLUDE_CODE
| Context.CONTEXT_IGNORE_SECURITY));
}
if (loadedApk == null)
throw new RuntimeException ("getPackageInfo returned NULL");
/* If loadedApkClass remains NULL, substitute the class of
the object returned by getPackageInfo. */
if (loadedApkClass == null)
loadedApkClass = loadedApk.getClass ();
/* Now, get a context. */
contextImplClass = Class.forName ("android.app.ContextImpl");
try
{
method
= contextImplClass.getDeclaredMethod ("createAppContext",
activityThreadClass,
loadedApkClass);
method.setAccessible (true);
context = (Context) method.invoke (null, activityThread,
loadedApk);
}
catch (NoSuchMethodException exception)
{
/* Older Android versions don't have createAppContext, but
instead require creating a ContextImpl, and then
calling createPackageContext. */
method
= activityThreadClass.getDeclaredMethod ("getSystemContext");
context = (Context) method.invoke (activityThread);
method = contextImplClass.getDeclaredMethod ("createPackageContext",
String.class,
int.class);
method
= contextImplClass.getDeclaredMethod ("createPackageContext",
String.class,
int.class);
method.setAccessible (true);
context = (Context) method.invoke (context, "org.gnu.emacs",
0);
}
/* If the context has not already been created, then do what
is appropriate for newer versions of Android. */
/* Retrieve the LoadedApk's class loader and execute the
remaining portion of the start-up process within its version
of EmacsNoninteractive, which will indicate to the system
that it must load shared libraries from the APK's library
search path. */
if (context == null)
{
/* Get a LoadedApk. How to do this varies by Android version.
On Android 2.3.3 and earlier, there is no
``compatibilityInfo'' argument to getPackageInfo. */
if (Build.VERSION.SDK_INT
<= Build.VERSION_CODES.GINGERBREAD_MR1)
{
method
= activityThreadClass.getMethod ("getPackageInfo",
String.class,
int.class);
loadedApk = method.invoke (activityThread, "org.gnu.emacs",
0);
}
else
{
compatibilityInfoClass
= Class.forName ("android.content.res.CompatibilityInfo");
method
= activityThreadClass.getMethod ("getPackageInfo",
String.class,
compatibilityInfoClass,
int.class);
loadedApk = method.invoke (activityThread, "org.gnu.emacs",
null, 0);
}
if (loadedApk == null)
throw new RuntimeException ("getPackageInfo returned NULL");
/* Now, get a context. */
contextImplClass = Class.forName ("android.app.ContextImpl");
try
{
method
= contextImplClass.getDeclaredMethod ("createAppContext",
activityThreadClass,
loadedApkClass);
method.setAccessible (true);
context = (Context) method.invoke (null, activityThread,
loadedApk);
}
catch (NoSuchMethodException exception)
{
/* Older Android versions don't have createAppContext, but
instead require creating a ContextImpl, and then
calling createPackageContext. */
method
= activityThreadClass.getDeclaredMethod ("getSystemContext");
context = (Context) method.invoke (activityThread);
method
= contextImplClass.getDeclaredMethod ("createPackageContext",
String.class,
int.class);
method.setAccessible (true);
context = (Context) method.invoke (context, "org.gnu.emacs",
0);
}
}
/* Don't actually start the looper or anything. Instead, obtain
an AssetManager. */
assets = context.getAssets ();
/* Now configure Emacs. The class path should already be set. */
filesDir = context.getFilesDir ().getCanonicalPath ();
libDir = EmacsService.getLibraryDirectory (context);
cacheDir = context.getCacheDir ().getCanonicalPath ();
method = loadedApkClass.getDeclaredMethod ("getClassLoader");
classLoader = (ClassLoader) method.invoke (loadedApk);
}
catch (Exception e)
{
@ -188,16 +208,20 @@ public final class EmacsNoninteractive
System.exit (1);
}
EmacsNative.setEmacsParams (assets, filesDir,
libDir, cacheDir, 0.0f,
0.0f, 0.0f, null, null,
Build.VERSION.SDK_INT);
/* Now find the dump file that Emacs should use, if it has already
been dumped. */
EmacsApplication.findDumpFile (context);
/* Start Emacs. */
EmacsNative.initEmacs (args, EmacsApplication.dumpFileName);
try
{
emacsNoninteractiveClass
= classLoader.loadClass ("org.gnu.emacs.EmacsNoninteractive");
method = emacsNoninteractiveClass.getMethod ("main1", String[].class,
Context.class);
method.setAccessible (true);
method.invoke (null, args, context);
}
catch (Exception e)
{
System.err.println ("Internal error during startup: " + e);
e.printStackTrace ();
System.exit (1);
}
}
};