coordinates appropriately. */
if (gc.clip_mask == null)
- canvas.drawLine ((float) x + 0.5f, (float) y + 0.5f,
+ canvas.drawLine ((float) x, (float) y + 0.5f,
(float) x2 + 0.5f, (float) y2 + 0.5f,
paint);
On Android 2.3.3 and earlier, there is no
``compatibilityInfo'' argument to getPackageInfo. */
- if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD)
+ if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1)
{
method
= activityThreadClass.getMethod ("getPackageInfo",
/* Now, get a context. */
contextImplClass = Class.forName ("android.app.ContextImpl");
- method = contextImplClass.getDeclaredMethod ("createAppContext",
- activityThreadClass,
- loadedApkClass);
- method.setAccessible (true);
- context = (Context) method.invoke (null, activityThread, loadedApk);
+
+ 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. */
public
EmacsSdk11Clipboard ()
{
- String what;
- Context context;
-
- what = Context.CLIPBOARD_SERVICE;
- context = EmacsService.SERVICE;
- manager
- = (ClipboardManager) context.getSystemService (what);
+ manager = EmacsService.SERVICE.getClipboardManager ();
manager.addPrimaryClipChangedListener (this);
}
import android.app.PendingIntent;
import android.app.Service;
+import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
return null;
}
+
+ /* Get a SDK 11 ClipboardManager.
+
+ Android 4.0.x requires that this be called from the main
+ thread. */
+
+ public ClipboardManager
+ getClipboardManager ()
+ {
+ final Holder<ClipboardManager> manager;
+ Runnable runnable;
+
+ manager = new Holder<ClipboardManager> ();
+
+ runnable = new Runnable () {
+ public void
+ run ()
+ {
+ Object tem;
+
+ synchronized (this)
+ {
+ tem = getSystemService (Context.CLIPBOARD_SERVICE);
+ manager.thing = (ClipboardManager) tem;
+ notify ();
+ }
+ }
+ };
+
+ synchronized (runnable)
+ {
+ runOnUiThread (runnable);
+
+ try
+ {
+ runnable.wait ();
+ }
+ catch (InterruptedException e)
+ {
+ EmacsNative.emacsAbort ();
+ }
+ }
+
+ return manager.thing;
+ }
};
if (pure_bytes_used_non_lisp <= nbytes)
return NULL;
+ /* The Android GCC generates code like:
+
+ 0xa539e755 <+52>: lea 0x430(%esp),%esi
+=> 0xa539e75c <+59>: movdqa %xmm0,0x0(%ebp)
+ 0xa539e761 <+64>: add $0x10,%ebp
+
+ but data is not aligned appropriately, so a GP fault results. */
+
+#if defined __i386__ \
+ && defined HAVE_ANDROID \
+ && !defined ANDROID_STUBIFY \
+ && !defined (__clang__)
+ if ((intptr_t) data & 15)
+ return NULL;
+#endif
+
/* Set up the Boyer-Moore table. */
skip = nbytes + 1;
for (i = 0; i < 256; i++)
args[0] = (char *) "/system/bin/app_process";
#endif
+ /* Machines with ART require the boot classpath to be manually
+ specified. Machines with Dalvik however refuse to do so, as they
+ open the jars inside the BOOTCLASSPATH environment variable at
+ startup, resulting in the following crash:
+
+ W/dalvikvm( 1608): Refusing to reopen boot DEX
+ '/system/framework/core.jar'
+ W/dalvikvm( 1608): Refusing to reopen boot DEX
+ '/system/framework/bouncycastle.jar'
+ E/dalvikvm( 1608): Too many exceptions during init (failed on
+ 'Ljava/io/IOException;' 'Re-opening BOOTCLASSPATH DEX files is
+ not allowed')
+ E/dalvikvm( 1608): VM aborting */
+
+#if HAVE_DECL_ANDROID_GET_DEVICE_API_LEVEL
+ if (android_get_device_api_level () < 21)
+ {
+ bootclasspath = NULL;
+ goto skip_setup;
+ }
+#else
+ if (__ANDROID_API__ < 21)
+ {
+ bootclasspath = NULL;
+ goto skip_setup;
+ }
+#endif
+
/* Next, obtain the boot class path. */
bootclasspath = getenv ("BOOTCLASSPATH");
- /* And the Emacs class path. */
- emacs_class_path = getenv ("EMACS_CLASS_PATH");
-
if (!bootclasspath)
{
fprintf (stderr, "The BOOTCLASSPATH environment variable"
return 1;
}
+ skip_setup:
+
+ /* And the Emacs class path. */
+ emacs_class_path = getenv ("EMACS_CLASS_PATH");
+
if (!emacs_class_path)
{
fprintf (stderr, "EMACS_CLASS_PATH not set."
return 1;
}
- if (asprintf (&bootclasspath, "-Djava.class.path=%s:%s",
- bootclasspath, emacs_class_path) < 0)
+ if (bootclasspath)
{
- perror ("asprintf");
- return 1;
+ if (asprintf (&bootclasspath, "-Djava.class.path=%s:%s",
+ bootclasspath, emacs_class_path) < 0)
+ {
+ perror ("asprintf");
+ return 1;
+ }
+ }
+ else
+ {
+ if (asprintf (&bootclasspath, "-Djava.class.path=%s",
+ emacs_class_path) < 0)
+ {
+ perror ("asprintf");
+ return 1;
+ }
}
args[1] = bootclasspath;
args[2] = (char *) "/system/bin";
- 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];
+#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];
+ /* Now copy the rest of the arguments over. */
+ for (i = 1; i < argc; ++i)
+ args[5 + i] = argv[i];
+ }
+ else
+ {
+#endif
+ 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
/* Finally, try to start the app_process. */
execvp (args[0], args);
stored in unsigned long to be consistent with X. */
static unsigned int event_serial;
+/* Unused pointer used to control compiler optimizations. */
+void *unused_pointer;
+
\f
/* Event handling functions. Events are stored on a (circular) queue
const char *c_argument;
char *dump_file;
+ /* android_emacs_init is not main, so GCC is not nice enough to add
+ the stack alignment prologue.
+
+ Unfortunately for us, dalvik on Android 4.0.x calls native code
+ with a 4 byte aligned stack. */
+
+ __attribute__ ((aligned (32))) char buffer[32];
+
+ /* Trick GCC into not optimizing this variable away. */
+ unused_pointer = buffer;
+
android_java_env = env;
nelements = (*env)->GetArrayLength (env, argv);
dir_warning ("arch-independent data dir", Vdata_directory);
sh = getenv ("SHELL");
+#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
+ /* The Android shell is found under /system/bin, not /bin. */
+ Vshell_file_name = build_string (sh ? sh : "/system/bin/sh");
+#else
Vshell_file_name = build_string (sh ? sh : "/bin/sh");
+#endif
Lisp_Object gamedir = Qnil;
if (PATH_GAME)