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:
parent
8e4c5db193
commit
df29bb71fc
@ -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 ();
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user