javaandroidjava-native-interfacegluongraalvm

gluonfx attach service between graalvm and android


this is my gluon attach service (under folder native/android/dalvik/)

package com.gluonhq.helloandroid;

import android.app.Activity;
import android.util.Log;

public class DalvikSmsService {
    private final Activity activity;

    public DalvikSmsService(Activity activity) {
        this.activity = activity;
    }

    public static void receiveSms(String phone, String sms) {
        processReceivedSms(phone, sms);
    }
    
    private native static void processReceivedSms(String key, String value);
}

with a corresponding JNI sms.c (under native/android/c/)file as below

#include "util.h"

// ... other handle declarations ...

JNIEXPORT jint JNICALL 
JNI_OnLoad_sms(JavaVM *vm, void *reserved)
{
    ATTACH_LOG_INFO("JNI_OnLoad_sms called");
#ifdef JNI_VERSION_1_8
    JNIEnv* graalEnv;
    if ((*vm)->GetEnv(vm, (void **)&graalEnv, JNI_VERSION_1_8) != JNI_OK) {
        ATTACH_LOG_WARNING("sms error initializing native Sms from OnLoad");
        return JNI_FALSE;
    }
    ATTACH_LOG_FINE("[sms service] Initializing native Sms from OnLoad started");
    initializeGraalHandles(graalEnv);
    initializeDalvikHandles();
    ATTACH_LOG_FINE("[sms service] Initializing native Sms from OnLoad done");
    return JNI_VERSION_1_8;
#else
    #error Error: Java 8+ SDK is required to compile Attach
#endif
}

JNIEXPORT void JNICALL Java_com_gluonhq_helloandroid_DalvikSmsService_processReceivedSms 
(JNIEnv *env, jclass service, jstring jkey, jstring jvalue) 
{
 // ... additonal code not show ...
}

When I load the apk and run the app, the sms service is loaded, BUT when I try to call DalvikSmsService.receiveSms('', 'sample sms'); the method is called but with the following error ...

AndroidRuntime: java.lang.UnsatisfiedLinkError: No implementation found for void com.gluonhq.helloandroid.DalvikSmsService.processReceivedSms(java.lang.String, java.lang.String) (tried Java_com_gluonhq_helloandroid_DalvikSmsService_processReceivedSms and Java_com_gluonhq_helloandroid_DalvikSmsService_processReceivedSms__Ljava_lang_String_2Ljava_lang_String_2)

build output structure ... enter image description here


Solution

  • The call from JNI (sms.c):

    static void initializeGraalHandles(JNIEnv* env) {
        ...
        jGraalReceiceSmsMethod = (*env)->GetStaticMethodID(env, jGraalSmsClass, "receiveSms", "(Ljava/lang/String;Ljava/lang/String;)V");
    }
    
    JNIEXPORT void JNICALL Java_com_gluonhq_helloandroid_DalvikSmsService_processReceivedSms
    (JNIEnv *env, jclass service, jstring jkey, jstring jvalue)
    {
        ...
        ATTACH_LOG_FINE("[sms service] call dalvik->native layer all got sms, key: %s, value: %s", keyChars, valueChars);
        ...
        (*graalEnv)->CallStaticVoidMethod(graalEnv, jGraalSmsClass, jGraalReceiceSmsMethod, jKeyChars, jValueChars);
        ...
    }
    

    to to Java (AndroidSmsService.java):

    public static void receiveSms(String phone, String sms) {
        Platform.runLater(() -> messages.add(new Message(phone, sms)));
    }
    

    actually uses reflection.

    Currently, when the method is invoked, there is a SIGSEGV:

    08-12 16:51:22.346 29215 29246 D GluonAttach: [sms service] Initializing native Sms from OnLoad started
    08-12 16:51:22.346 29215 29246 D GraalGluon: ATTACH_DALVIK, tid = 29246, existed? 1, dalvikEnv at 0x7845064540
    08-12 16:51:22.346 29215 29246 D GluonAttach: Util :: Load className com/gluonhq/helloandroid/DalvikSmsService
    08-12 16:51:22.347 29215 29246 D GraalGluon: ATTACH_DALVIK, tid = 29246, existed? 1, dalvikEnv at 0x7845064540
    08-12 16:51:22.351 29215 29246 I DalvikSmsService: sms receiced, phone: 123, sms: 456
    08-12 16:51:22.351 29215 29246 D GluonAttach: [sms service] native layer got sms, key: 123, value: 456
    08-12 16:51:22.351 29215 29246 D GraalGluon: ATTACH_GRAAL, tid = 29246, existed? 1, graalEnv at 0x7845064400
    08-12 16:51:22.351 29215 29246 D GluonAttach: [sms service] call dalvik->native layer all got sms, key: 123, value: 456
    --------- beginning of crash
    08-12 16:51:22.352 29215 29246 F libc    : Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x20 in tid 29246 (Thread-3), pid 29215 (ples.hellogluon)
    08-12 16:51:22.463 29410 29410 I crash_dump64: obtaining output fd from tombstoned, type: kDebuggerdTombstone
    08-12 16:51:22.468   835   835 I /system/bin/tombstoned: received crash request for pid 29246
    08-12 16:51:22.469 29410 29410 I crash_dump64: performing dump of process 29215 (target tid = 29246)
    08-12 16:51:22.480 29410 29410 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
    08-12 16:51:22.480 29410 29410 F DEBUG   : Build fingerprint: 'google/marlin/marlin:10/QP1A.191005.007.A3/5972272:user/release-keys'
    08-12 16:51:22.480 29410 29410 F DEBUG   : Revision: '0'
    08-12 16:51:22.480 29410 29410 F DEBUG   : ABI: 'arm64'
    

    To prevent the crash, you just need to include the method receiveSms in the jniconfig-aarch64-android.json file under src/main/resources/META-INF/substrate/config/jniconfig-aarch64-android.json:

    [
        {
            "name" : "org.jpereda.attach.sms.impl.AndroidSmsService",
            "methods":[
                {"name":"receiveSms","parameterTypes":["java.lang.String","java.lang.String"] }
            ]
        }
    ]
    

    That works for me with GluonFX 1.0.4 and Gluon's GraalVM 21.2.0.