打通驱动层到应用层--(三)Framework层

前言

framework主要向上提供JAVA接口用于访问硬件设备,

一、新建

进入到frameworks\base\services\core\jni文件夹中,新建com_android_server_HelloxjqService.cpp文件。com_android_server表示硬件服务Helloxjqservice放在frameworks/base/services/java目录下的com/android/server目录的,这儿HelloxjqService是一个提供JAVA接口的硬件访问服务类。

#define LOG_TAG "HelloxjqService"

#include "JNIHelp.h"
#include "jni.h"
#include <utils/Log.h>
#include <utils/misc.h>
#include <utils/String8.h>

#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/timerfd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <linux/ioctl.h>
#include <linux/rtc.h>
#include <hardware/helloxjq.h>
#include <fcntl.h>
#include <stdio.h>
#include<malloc.h>
#include <hardware/hardware.h>  
namespace android  
{  
    //jstring to char*
    char* jstringTostring(JNIEnv* env, jstring jstr);
    //char* to jstring
    jstring stoJstring(JNIEnv* env, const char* pat);


    /*在硬件抽象层中定义的硬件访问结构体,参考<hardware/helloxjq.h>*/  
        struct helloxjq_device_t* device = NULL;  
    /*通过硬件抽象层定义的硬件访问接口读字符串*/  
        static jstring helloxjq_readString(JNIEnv* env, jobject clazz) {  
        jstring ret;
        if(!device) {  
            ALOGI("Helloxjq JNI: device is not open.");  
            return NULL;  
        }  
        char *read_str = (char*)malloc(10);
        device->read_string(device, &read_str);  
        ALOGI("Helloxjq JNI: read string %s from helloxjq device.", read_str); 
        ret = stoJstring(env,read_str);
        free(read_str);
        read_str = NULL;
        return ret;
    }  
        /*通过硬件抽象层定义的硬件访问接口写字符串*/  
    static jint helloxjq_writeString(JNIEnv* env, jobject clazz,jstring str) {  
        if(!device) {  
            ALOGI("Helloxjq JNI: device is not open.");  
            return -1;  
        }  
     char * local_str = jstringTostring(env,str);
        device->write_string(device, local_str);  

        ALOGI("Helloxjq JNI: write string %s to helloxjq device.", local_str); 
     return sizeof(local_str);
    }  
        /*通过硬件抽象层定义的硬件模块打开接口打开硬件设备*/  
    static inline int helloxjq_device_open(const hw_module_t* module, struct helloxjq_device_t** device) {  
        return module->methods->open(module, HELLOXJQ_HARDWARE_MODULE_ID, (struct hw_device_t**)device);  
    }  
        /*通过硬件模块ID来加载指定的硬件抽象层模块并打开硬件*/  
    static jboolean helloxjq_init(JNIEnv* env, jclass clazz) {  
        helloxjq_module_t* module;  

        ALOGI("Helloxjq JNI: initializing......");  
        if(hw_get_module(HELLOXJQ_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module) == 0) {  
            ALOGI("Helloxjq JNI: helloxjq Stub found.");  
            if(helloxjq_device_open(&(module->common), &device) == 0) {  
                ALOGI("Helloxjq JNI: helloxjq device is open.");  
                return 0;  
            }
            ALOGI("Helloxjq JNI: failed to open helloxjq device.");  
            return -1;  
        }  
        ALOGI("Helloxjq JNI: failed to get helloxjq stub module.");  
        return -1;
    }  
        /*JNI方法表*/  
    static const JNINativeMethod method_table[] = {  
        {"init_native", "()Z", (void*)helloxjq_init},  
        {"readString_native", "()Ljava/lang/String;", (void*)helloxjq_readString},  
        {"wirteString_native", "(Ljava/lang/String;)I", (void*)helloxjq_writeString},  
    };  
        /*注册JNI方法*/  
    int register_android_server_HelloxjqService(JNIEnv *env) {
             ALOGI("SystemServer :register_android_server_HelloxjqService.");  
            return jniRegisterNativeMethods(env, "com/android/server/HelloxjqService", method_table, NELEM(method_table));  
    }  

    //jstring to char*
char* jstringTostring(JNIEnv* env, jstring jstr)
{
       char* rtn = NULL;
       jclass clsstring = env->FindClass("java/lang/String");
       jstring strencode = env->NewStringUTF("utf-8");
       jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
       jbyteArray barr= (jbyteArray)env->CallObjectMethod(jstr, mid, strencode);
       jsize alen = env->GetArrayLength(barr);
       jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
       if (alen > 0)
       {
                 rtn = (char*)malloc(alen + 1);
                 memcpy(rtn, ba, alen);
                 rtn[alen] = 0;
       }
       env->ReleaseByteArrayElements(barr, ba, 0);
       return rtn;
}

//char* to jstring
jstring stoJstring(JNIEnv* env, const char* pat)
{
       jclass strClass = env->FindClass("java/lang/String");
       jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
       jbyteArray bytes = env->NewByteArray(strlen(pat));
       env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*)pat);
       jstring encoding = env->NewStringUTF("utf-8");
       return (jstring)env->NewObject(strClass, ctorID, bytes, encoding);
}

};  

进入到frameworks/base/core/java/android/os目录,添加 IHelloxjqService.aidl 文件:

package android.os;  

interface IHelloxjqService {  
    int wirteString(String str);  
    String readString();  
}  

进入到 frameworks/base/services/java/com/android/server 目录,添加 HelloxjqService.java 文件:

package com.android.server;  
import android.content.Context;  
import android.os.IHelloxjqService;  
import android.util.Slog;  
public class HelloxjqService extends IHelloxjqService.Stub {  
    private static final String TAG = "HelloxjqService";  
    HelloxjqService() {  
        init_native();  
    }    
    public int wirteString(java.lang.String str){
    return wirteString_native(str);
    }
    public java.lang.String readString() {  
       return readString_native();  
    }  

    private static native boolean init_native();  
    private static native int wirteString_native(String str);  
    private static native String readString_native();  
}; 

二、修改

  1. 修改frameworks/base/services/jni目录下的 onload.cpp 文件,在 JNI_OnLoad函数中的return之前添加下面一句:
    register_android_server_HelloxjqService(env);
    在namespace中添加
    int register_android_server_HelloxjqService(JNIEnv* env);
    这样,在系统初始化时,就会调用register_android_server_HelloxjqService方法来加载JNI方法了。

  2. 在同目录下的Android.mk中在LOCAL_SRC_FILES变量中增加$(LOCAL_REL_DIR)/com_android_server_HelloxjqService.cpp \

  3. 进入到 frameworks/base 目录,打开 Android.mk 文件,在 LOCAL_SRC_FILES 变量中加入这么一行:注:一定要在LOCAL_SRC_FILES变量中
    core/java/android/os/IHelloxjqService.aidl \

  4. 打开frameworks/base/services/java/com/android/server 目录下的 SystemServer.java 文件,
    添加头文件import com.android.server.HelloxjqService;
    在其中的 run() 函数中找到

try {
 Slog.i(TAG, "DiskStats Service");
 ServiceManager.addService("diskstats", new DiskStatsService(context));
 } catch (Throwable e) {
 reportWtf("starting DiskStats Service", e);
 }

这一段,在后面加上下面的代码:

         try {

                Slog.i(TAG, "Helloxjq Service");
                ServiceManager.addService("helloxjq", new HelloxjqService());

            } catch (Throwable e) {
                Slog.e(TAG, "Failure starting Helloxjq Service", e);
            }

三、编译

  • 编译JNI
    编译mmm frameworks/base/services/core/jni/
    打包make snod
  • 编译service
    编译IHelloxjqService的stub接口:先执行mmm frameworks/base
    编译 HelloxjqService 服务:mmm frameworks/base/services/java
    重新打包:make snod

我看到很多帖子说make snod有问题,如果出现奇奇怪怪的问题,就使用make clean清理一遍工程,直接整编。
本章节出现问题很可能会导致系统一直重启,这时,可以通过查看Log,查看相关服务是否启动。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值