diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi index 3c704970cda..5400d492f0a 100644 --- a/doc/lispref/os.texi +++ b/doc/lispref/os.texi @@ -3220,15 +3220,25 @@ These have the same meaning as they do when used in calls to @code{notifications-notify}. @item :urgency @var{urgency} +The set of values for @var{urgency} is the same as with +@code{notifications-notify}, but the urgency applies to all +notifications displayed with the defined @var{group}, except under +Android 7.1 and earlier. + @item :group @var{group} -These two parameters are ignored under Android 7.1 and earlier -versions of the system. The set of values for @var{urgency} is the -same as with @code{notifications-notify}, but the urgency applies to -all notifications displayed with the defined @var{group}. +@var{group} is a string that designates a category to which the +notification sent will belong. This category is reproduced within the +system's notification settings menus, but is ignored under Android 7.1 +and earlier. If @var{group} is nil or not present within @var{params}, it is replaced by the string @samp{"Desktop Notifications"}. +Callers should provide one stable combination of @var{urgency} and +@var{group} for each kind of notification they send, given that the +system may elect to disregard @var{urgency} if it does not match that +of any notification previously delivered to @var{group}. + @item :icon @var{icon} This parameter controls the symbolic icon the notification will be displayed with. Its value is a string designating an icon within the diff --git a/java/org/gnu/emacs/EmacsDesktopNotification.java b/java/org/gnu/emacs/EmacsDesktopNotification.java index 121d8f481a2..56ed984d497 100644 --- a/java/org/gnu/emacs/EmacsDesktopNotification.java +++ b/java/org/gnu/emacs/EmacsDesktopNotification.java @@ -96,6 +96,7 @@ public final class EmacsDesktopNotification RemoteViews contentView; Intent intent; PendingIntent pending; + int priority; tem = context.getSystemService (Context.NOTIFICATION_SERVICE); manager = (NotificationManager) tem; @@ -116,11 +117,37 @@ public final class EmacsDesktopNotification .build ()); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) - notification = (new Notification.Builder (context) - .setContentTitle (title) - .setContentText (content) - .setSmallIcon (icon) - .build ()); + { + /* Android 7.1 and earlier don't segregate notifications into + distinct categories, but permit an importance to be + assigned to each individual notification. */ + + switch (importance) + { + case 2: /* IMPORTANCE_LOW */ + default: + priority = Notification.PRIORITY_LOW; + break; + + case 3: /* IMPORTANCE_DEFAULT */ + priority = Notification.PRIORITY_DEFAULT; + break; + + case 4: /* IMPORTANCE_HIGH */ + priority = Notification.PRIORITY_HIGH; + break; + } + + notification = (new Notification.Builder (context) + .setContentTitle (title) + .setContentText (content) + .setSmallIcon (icon) + .setPriority (priority) + .build ()); + + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) + notification.priority = priority; + } else { notification = new Notification (); diff --git a/java/org/gnu/emacs/EmacsPixmap.java b/java/org/gnu/emacs/EmacsPixmap.java index e02699ecba7..fa6e61c15a5 100644 --- a/java/org/gnu/emacs/EmacsPixmap.java +++ b/java/org/gnu/emacs/EmacsPixmap.java @@ -50,39 +50,6 @@ public final class EmacsPixmap extends EmacsHandleObject changed. */ private long gcClipRectID; - public - EmacsPixmap (short handle, int colors[], int width, - int height, int depth) - { - super (handle); - - if (depth != 1 && depth != 24) - throw new IllegalArgumentException ("Invalid depth specified" - + " for pixmap: " + depth); - - switch (depth) - { - case 1: - bitmap = Bitmap.createBitmap (colors, width, height, - Bitmap.Config.ALPHA_8); - break; - - case 24: - bitmap = Bitmap.createBitmap (colors, width, height, - Bitmap.Config.ARGB_8888); - bitmap.setHasAlpha (false); - break; - } - - this.width = width; - this.height = height; - this.depth = depth; - - /* The immutable bitmap constructor is only leveraged to create - small fringe bitmaps. */ - this.needCollect = false; - } - public EmacsPixmap (short handle, int width, int height, int depth) { diff --git a/src/android.c b/src/android.c index 0996a84823d..4df9d71b1b1 100644 --- a/src/android.c +++ b/src/android.c @@ -73,7 +73,6 @@ bool android_init_gui; struct android_emacs_pixmap { jclass class; - jmethodID constructor; jmethodID constructor_mutable; }; @@ -1649,7 +1648,6 @@ android_init_emacs_pixmap (void) name, signature); \ assert (pixmap_class.c_name); - FIND_METHOD (constructor, "", "(S[IIII)V"); FIND_METHOD (constructor_mutable, "", "(SIII)V"); #undef FIND_METHOD @@ -3404,86 +3402,91 @@ android_create_pixmap_from_bitmap_data (char *data, unsigned int width, unsigned long background, unsigned int depth) { - android_handle prev_max_handle; - jobject object; - jintArray colors; android_pixmap pixmap; + jobject object; + AndroidBitmapInfo info; + unsigned int *depth_24; + unsigned char *depth_8; + void *bitmap_data; unsigned int x, y; - jint *region; + unsigned int r, g, b; - USE_SAFE_ALLOCA; + /* Create a pixmap with the right dimensions and depth. */ + pixmap = android_create_pixmap (width, height, depth); - /* Create the color array holding the data. */ - colors = (*android_java_env)->NewIntArray (android_java_env, - width * height); - android_exception_check (); + /* Lock the bitmap data. */ + bitmap_data = android_lock_bitmap (pixmap, &info, &object); - SAFE_NALLOCA (region, sizeof *region, width); + /* Merely return if locking the bitmap fails. */ + if (!bitmap_data) + return pixmap; - for (y = 0; y < height; ++y) + eassert (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 + || info.format == ANDROID_BITMAP_FORMAT_A_8); + + /* Begin copying each line. */ + + switch (info.format) { - for (x = 0; x < width; ++x) - { - if (depth == 24) - { - /* The alpha channels must be set, or otherwise, the - pixmap will be created entirely transparent. */ + case ANDROID_BITMAP_FORMAT_RGBA_8888: - if (data[x / 8] & (1 << (x % 8))) - region[x] = foreground | 0xff000000; - else - region[x] = background | 0xff000000; - } - else - { - if (data[x / 8] & (1 << (x % 8))) - region[x] = foreground; - else - region[x] = background; - } + /* Swizzle the pixels into ABGR format. Android uses Skia's + ``native color type'', which is ABGR. This is despite the + format being named ``ARGB'', and more confusingly + `ANDROID_BITMAP_FORMAT_RGBA_8888' in bitmap.h. */ + + r = background & 0x00ff0000; + g = background & 0x0000ff00; + b = background & 0x000000ff; + background = (r >> 16) | g | (b << 16) | 0xff000000; + r = foreground & 0x00ff0000; + g = foreground & 0x0000ff00; + b = foreground & 0x000000ff; + foreground = (r >> 16) | g | (b << 16) | 0xff000000; + + for (y = 0; y < height; ++y) + { + depth_24 = (void *) ((char *) bitmap_data + y * info.stride); + + for (x = 0; x < width; ++x) + depth_24[x] = ((data[x / 8] & (1 << (x % 8))) + ? foreground : background); + + data += (width + 7) / 8; } - (*android_java_env)->SetIntArrayRegion (android_java_env, - colors, - width * y, width, - region); - data += width / 8; + break; + + case ANDROID_BITMAP_FORMAT_A_8: + + /* 8-bit pixmaps are created, but in spite of that they are + employed only to represent bitmaps. */ + + foreground = (foreground ? 255 : 0); + background = (background ? 255 : 0); + + for (y = 0; y < height; ++y) + { + depth_8 = (void *) ((char *) bitmap_data + y * info.stride); + + for (x = 0; x < width; ++x) + depth_8[x] = ((data[x / 8] & (1 << (x % 8))) + ? foreground : background); + + data += (width + 7) / 8; + } + + break; + + default: + emacs_abort (); } - /* First, allocate the pixmap handle. */ - prev_max_handle = max_handle; - pixmap = android_alloc_id (); - - if (!pixmap) - { - ANDROID_DELETE_LOCAL_REF ((jobject) colors); - error ("Out of pixmap handles!"); - } - - object = (*android_java_env)->NewObject (android_java_env, - pixmap_class.class, - pixmap_class.constructor, - (jshort) pixmap, colors, - (jint) width, (jint) height, - (jint) depth); - (*android_java_env)->ExceptionClear (android_java_env); - ANDROID_DELETE_LOCAL_REF ((jobject) colors); - - if (!object) - { - max_handle = prev_max_handle; - memory_full (0); - } - - android_handles[pixmap].type = ANDROID_HANDLE_PIXMAP; - android_handles[pixmap].handle - = (*android_java_env)->NewGlobalRef (android_java_env, object); + /* Unlock the bitmap itself. */ + AndroidBitmap_unlockPixels (android_java_env, object); ANDROID_DELETE_LOCAL_REF (object); - if (!android_handles[pixmap].handle) - memory_full (0); - - SAFE_FREE (); + /* Return the pixmap. */ return pixmap; } diff --git a/src/androidselect.c b/src/androidselect.c index 5735eda2dd5..cf2265d4cf4 100644 --- a/src/androidselect.c +++ b/src/androidselect.c @@ -660,12 +660,18 @@ keywords is understood: :icon The name of a drawable resource to display as the notification's icon. -The notification group and urgency are ignored on Android 7.1 and -earlier versions of Android. Outside such older systems, it -identifies a category that will be displayed in the system Settings -menu. The urgency provided always extends to affect all notifications -displayed within that category. If the group is not provided, it -defaults to the string "Desktop Notifications". +The notification group is ignored on Android 7.1 and earlier versions +of Android. Outside such older systems, it identifies a category that +will be displayed in the system Settings menu, and the urgency +provided always extends to affect all notifications displayed within +that category. If the group is not provided, it defaults to the +string "Desktop Notifications". + +Each caller should strive to provide one unchanging combination of +notification group and urgency for each kind of notification it sends, +inasmuch as the system may, subject to user configuration, disregard +the urgency specified within a notification, should it not be the +first notification sent to its notification group. The provided icon should be the name of a "drawable resource" present within the "android.R.drawable" class designating an icon with a