6. Android10向系统注册service访问内核驱动程序

wuchangjian2021-11-05 00:37:44编程学习

本文是在上文5. Android10增加硬件抽象层(HAL)模块访问内核驱动程序的基础上进行的,虚拟机环境就是上文结束时的环境。

实现HelloService

在aosp10/frameworks/base/core/java/android/os/目录下新建IHelloService.aidl文件

package android.os;  

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

在aosp10/frameworks/base/services/core/java/com/android/server目录下新HelloService.java文件

package com.android.server;  
import android.content.Context;  
import android.os.IHelloService;  
import android.util.Slog;  
public class HelloService extends IHelloService.Stub {  
    private static final String TAG = "HelloService";  
    HelloService() {  
        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();  
}; 

修改aosp10/frameworks/base目录下的Android.bp,增加一行

"core/java/android/os/IHelloService.aidl",

 添加jni接口访问HAL层

HelloService通过init_native()、wirteString_native(String str)、readString_native()这三个jni函数来访问HAL层,这里来实现这三个jni函数。

在aosp10/frameworks/base/services/core/jni目录下新建com_android_server_HelloService.cpp文件

#define LOG_TAG "HelloService"
#include <nativehelper/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/hello.h>
namespace android {
	//jstring to char*
	char* jstringTostring(JNIEnv* env, jstring jstr);
	//char* to jstring
	jstring stoJstring(JNIEnv* env, const char* pat);
	/*在硬件抽象层中定义的硬件访问结构体,参考<hardware/hello.h>*/
	struct hello_device_t* device = NULL;
	/*通过硬件抽象层定义的硬件访问接口读字符串*/
	static jstring hello_readString(JNIEnv* env, jobject clazz) {
		if(!device) {
			ALOGI("Hello JNI: device is not open.");
			return NULL;
		}
		char read_str[100];
		device->read_string(device, (char *)&read_str);
		ALOGI("Hello JNI: read string %s from hello device.", read_str);
		return stoJstring(env,read_str);
	}
	/*通过硬件抽象层定义的硬件访问接口写字符串*/
	static jint hello_writeString(JNIEnv* env, jobject clazz,jstring str) {
		if(!device) {
			ALOGI("Hello JNI: device is not open.");
			return -1;
		}
		char * local_str = jstringTostring(env,str);
		device->write_string(device, local_str);
		ALOGI("Hello JNI: write string %s to hello device.", local_str);
		return sizeof(local_str);
	}
	/*通过硬件抽象层定义的硬件模块打开接口打开硬件设备*/
	static inline int hello_device_open(const hw_module_t* module, struct hello_device_t** device) {
		return module->methods->open(module, HELLO_HARDWARE_MODULE_ID, (struct hw_device_t**)device);
	}
	/*通过硬件模块ID来加载指定的硬件抽象层模块并打开硬件*/
	static jboolean hello_init(JNIEnv* env, jclass clazz) {
		hello_module_t* module;
		ALOGI("Hello JNI: initializing......");
		if(hw_get_module(HELLO_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module) == 0) {
			ALOGI("Hello JNI: hello Stub found.");
			if(hello_device_open(&(module->common), &device) == 0) {
				ALOGI("Hello JNI: hello device is open.");
				return 0;
			}
			ALOGI("Hello JNI: failed to open hello device.");
			return -1;
		}
		ALOGI("Hello JNI: failed to get hello stub module.");
		return -1;
	}
	/*JNI方法表*/
	static const JNINativeMethod method_table[] = { {
			"init_native", "()Z", (void*)hello_init
		}
		, {
			"readString_native", "()Ljava/lang/String;", (void*)hello_readString
		}
		, {
			"wirteString_native", "(Ljava/lang/String;)I", (void*)hello_writeString
		}
		,
	}
	;
	/*注册JNI方法*/
	int register_android_server_HelloService(JNIEnv *env) {
		ALOGI("SystemServer :register_android_server_HelloService.");
		return jniRegisterNativeMethods(env, "com/android/server/HelloService", 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);
	}
};

修改aosp10/frameworks/base/services/core/jni目录下的Android.bp文件

        "com_android_server_HelloService.cpp",

修改aosp10/frameworks/base/services/core/jni目录下的onload.cpp

int register_android_server_HelloService(JNIEnv* env);

// ......

    register_android_server_HelloService(env);

 

向系统注册HelloService

修改aosp10/frameworks/base/services/java/com/android/server目录下的SystemServer.java文件

import com.android.server.HelloService;

// ......

            traceBeginAndSlog("StartHelloService");
            try {
                ServiceManager.addService("hello_service", new HelloService());
            } catch (Throwable e) {
                reportWtf("starting HelloService", e);
            }
            traceEnd();

编译 


cd ~/Documents/aosp10
export TARGET_PREBUILT_KERNEL=/home/test/Documents/msm/arch/arm64/boot/Image.lz4-dtb
source build/envsetup.sh
lunch
aosp_walleye-userdebug
time make -j16

 报错

make api-stubs-docs-update-current-api

 继续编译

time make -j16

 参考

Android应用程序访问linux驱动第三步:实现并向系统注册Service_阳光玻璃杯-CSDN博客

在Ubuntu为Android硬件抽象层(HAL)模块编写JNI方法提供Java访问硬件服务接口_老罗的Android之旅-CSDN博客

在Ubuntu上为Android系统的Application Frameworks层增加硬件访问服务_老罗的Android之旅-CSDN博客

相关文章

一汽-大众全新探岳家族上市,20.49万元起售

一汽-大众全新探岳家族上市,20.49万元起售

2022-08-24 08:50:09 8月23日,记者从一汽-大众官...

level 0 字符串转换

#level 0 word1 = " vimlne11o redrock...

王嘉尔潮牌公司申请个人姓名商标

王嘉尔潮牌公司申请个人姓名商标

2022-08-24 20:55:10 企查查APP显示,近日,队王贸...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。