首页 > 代码库 > init.rc文件里面启动c++程序,通过jni调用java实现

init.rc文件里面启动c++程序,通过jni调用java实现


功能:手机开机后要写个标志位。

已有实现,就是收到开机广播后,启动服务读取bp中的标志位(java代码需要等待ril准备好),
并把这个标志位写入到ap中(java代码调用c++)。

后来遇到的问题:实际应用中发现,接收开机广播等待的时间更长,需要提前写入ap时间。

解决方案:
在init.rc文件里面启动c++程序,通过jni调用java实现。

精简代码如下:
C++程序代码:

#define LOG_TAG "testmain"

#define LOG_NDEBUG 0

#include <dlfcn.h>
#include <cutils/log.h>
#include <utils/Log.h>
#include <jni.h>

using namespace android;

void wirtePsCaliValToKernel();

int main (int argc, char * argv[]){
    ALOGI("start c");
    wirtePsCaliValToKernel();
    ALOGI("start c end");
    return 0;
}

void wirtePsCaliValToKernel() {
    JavaVM* vm;
    JNIEnv* env;

    // start a VM
    JavaVMInitArgs args;
    JavaVMOption opt;

    opt.optionString =
        "-agentlib:jdwp=transport=dt_android_adb,suspend=n,server=y";

    args.version = JNI_VERSION_1_4;
    args.options = &opt;
    args.nOptions = 1;
    args.ignoreUnrecognized = JNI_FALSE;


    void* libdvm_dso = dlopen("libdvm.so", RTLD_NOW);
    ALOGE_IF(!libdvm_dso, "DdmConnection: %s", dlerror());

    void* libandroid_runtime_dso = dlopen("libandroid_runtime.so", RTLD_NOW);
    ALOGE_IF(!libandroid_runtime_dso, "DdmConnection: %s", dlerror());

    if (!libdvm_dso || !libandroid_runtime_dso) {
        goto error;
    }

    jint (*JNI_CreateJavaVM)(JavaVM** p_vm, JNIEnv** p_env, void* vm_args);
    JNI_CreateJavaVM = (typeof JNI_CreateJavaVM)dlsym(libdvm_dso, "JNI_CreateJavaVM");
    ALOGE_IF(!JNI_CreateJavaVM, "DdmConnection: %s", dlerror());

    jint (*registerNatives)(JNIEnv* env, jclass clazz);
    registerNatives = (typeof registerNatives)dlsym(libandroid_runtime_dso,
        "Java_com_android_internal_util_WithFramework_registerNatives");
    ALOGE_IF(!registerNatives, "DdmConnection: %s", dlerror());

    if (!JNI_CreateJavaVM || !registerNatives) {
        goto error;
    }

    if (JNI_CreateJavaVM(&vm, &env, &args) == 0) {
        jclass startClass;
        jmethodID readPsMeth;

        // register native code
        if (registerNatives(env, 0) == 0) {
            startClass = env->FindClass("android/hardware/Camera");
            if (startClass) {
                ALOGI(" startclass is ok");
                //readPsMeth = env->GetStaticMethodID(startClass, "getCurrentFocusPosition", "(I)V");
                readPsMeth = env->GetMethodID(startClass, "getCurrentFocusPosition", "()I");
                int result = -1;
                if (readPsMeth) {
                    ALOGI("readPsMeth is ok, result = %d ",  result);
                    result = env->CallStaticIntMethod(startClass, readPsMeth);
                    ALOGI("readPsMeth is ok end, result = %d ",  result);
                }else{
                    ALOGE("-->> readPsMeth is fail");
                }

            }else{
                ALOGE("startclass is fail");
            }
        }
    }
    return;

error:
    if (libandroid_runtime_dso) {
        dlclose(libandroid_runtime_dso);
    }
    if (libdvm_dso) {
        dlclose(libdvm_dso);
    }
}



Android.mk:


LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE:= testmain

LOCAL_SRC_FILES:=         testmain.cpp

LOCAL_C_INCLUDES :=

LOCAL_MODULE_TAGS := optional eng

LOCAL_SHARED_LIBRARIES += libcutils                             libutils                              liblog                              libandroid_runtime                           libnativehelper                           libdl 
include $(BUILD_EXECUTABLE)


init.rc修改:

class 值为main时才能开机自动启动

service testmain /system/bin/testmain
	class main
	user root
	oneshot




end

init.rc文件里面启动c++程序,通过jni调用java实现