1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-12-01 08:17:38 +00:00

Update Android port

* java/org/gnu/emacs/EmacsNoninteractive.java (main): Port to
Android 2.2.
* src/android-asset.h (AAsset_openFileDescriptor): Delete stub
function.
* src/android.c (android_check_compressed_file): Delete
function.
(android_open): Stop trying to find compressed files or to use
the system provided file descriptor.  Explain why.
This commit is contained in:
Po Lu 2023-02-25 20:11:48 +08:00
parent 8e4c5db193
commit df29bb71fc
3 changed files with 88 additions and 106 deletions

View File

@ -87,56 +87,23 @@ else if (apiLevel >= Build.VERSION_CODES.DONUT)
/* Create and attach the activity thread. */
activityThread = method.invoke (null);
context = null;
/* Now get an LoadedApk. */
loadedApkClass = Class.forName ("android.app.LoadedApk");
/* 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);
loadedApkClass = Class.forName ("android.app.LoadedApk");
}
catch (NoSuchMethodException exception)
catch (ClassNotFoundException exception)
{
/* Older Android versions don't have createAppContext, but
instead require creating a ContextImpl, and then
calling createPackageContext. */
/* Android 2.2 has no LoadedApk class, but fortunately it
does not need to be used, since contexts can be
directly created. */
loadedApkClass = null;
contextImplClass = Class.forName ("android.app.ContextImpl");
method = activityThreadClass.getDeclaredMethod ("getSystemContext");
context = (Context) method.invoke (activityThread);
method = contextImplClass.getDeclaredMethod ("createPackageContext",
@ -147,6 +114,73 @@ else if (apiLevel >= Build.VERSION_CODES.DONUT)
0);
}
/* If the context has not already been created, then do what
is appropriate for newer versions of Android. */
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 ();

View File

@ -365,15 +365,6 @@ android_asset_read_internal (AAsset *asset, int nbytes, char *buffer)
return total;
}
static int
AAsset_openFileDescriptor (AAsset *asset, off_t *out_start,
off_t *out_end)
{
*out_start = 0;
*out_end = 0;
return -1;
}
static long
AAsset_getLength (AAsset *asset)
{

View File

@ -1376,42 +1376,6 @@ android_hack_asset_fd (AAsset *asset)
#endif
}
/* Read two bytes from FD and see if they are ``PK'', denoting ZIP
archive compressed data. If FD is -1, return -1.
If they are not, rewind the file descriptor to offset 0.
If either operation fails, return -1 and close FD. Else, value is
FD. */
static int
android_check_compressed_file (int fd)
{
char bytes[2];
if (fd == -1)
return -1;
if (read (fd, bytes, 2) != 2)
goto lseek_back;
if (bytes[0] != 'P' || bytes[1] != 'K')
goto lseek_back;
/* This could be compressed data! */
return -1;
lseek_back:
/* Seek back to offset 0. If this fails, return -1. */
if (lseek (fd, 0, SEEK_SET) != 0)
{
close (fd);
return -1;
}
return fd;
}
/* Make FD close-on-exec. If any system call fails, do not abort, but
log a warning to the system log. */
@ -1482,28 +1446,21 @@ android_open (const char *filename, int oflag, int mode)
return -1;
}
/* Try to obtain the file descriptor corresponding to this
asset. */
fd = AAsset_openFileDescriptor (asset, &out_start,
&out_length);
/* Create a shared memory file descriptor containing the asset
contents.
/* The platform sometimes returns a file descriptor to ZIP
compressed data. Detect that and fall back to creating a
shared memory file descriptor. */
fd = android_check_compressed_file (fd);
The documentation misleads people into thinking that
AAsset_openFileDescriptor does precisely this. However, it
instead returns an offset into any uncompressed assets in the
ZIP archive. This cannot be found in its documentation. */
fd = android_hack_asset_fd (asset);
if (fd == -1)
{
/* The asset can't be accessed for some reason. Try to
create a shared memory file descriptor. */
fd = android_hack_asset_fd (asset);
if (fd == -1)
{
AAsset_close (asset);
errno = ENXIO;
return -1;
}
AAsset_close (asset);
errno = ENXIO;
return -1;
}
/* If O_CLOEXEC is specified, make the file descriptor close on