本文是在上文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[VAL_LENGTH];
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 strlen(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/core/java/android/app/目录下新建HelloManager.java文件
package android.app;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.IHelloService;
import android.util.Log;
public class HelloManager {
IHelloService mService;
public HelloManager(Context ctx,IHelloService service){
mService = service;
}
public void wirteString(String value){
try{
Log.e("HelloManager","HelloManager wirteString");
mService.wirteString(value);
}catch(Exception e){
Log.e("HelloManager",e.toString());
e.printStackTrace();
}
}
public String readString(){
try{
Log.e("HelloManager","HelloManager readString");
return mService.readString();
}catch(Exception e){
Log.e("HelloManager",e.toString());
e.printStackTrace();
}
return null;
}
}
修改aosp10/frameworks/base/core/java/android/app/SystemServiceRegistry.java文件
import android.os.IHelloService;
......
registerService("hello", HelloManager.class,
new CachedServiceFetcher<HelloManager>() {
@Override
public HelloManager createService(ContextImpl ctx)
throws ServiceNotFoundException {
IBinder b = ServiceManager.getServiceOrThrow(
"hello");
return new HelloManager(ctx, IHelloService.Stub.asInterface(b));
}});
修改aosp10/frameworks/base/services/java/com/android/server目录下的SystemServer.java文件
import com.android.server.HelloService;
// ......
traceBeginAndSlog("StartHelloService");
try {
ServiceManager.addService("hello", new HelloService());
} catch (Throwable e) {
reportWtf("starting HelloService", e);
}
traceEnd();
为HelloService添加selinux权限
首先需要修改这3个文件
aosp10/system/sepolicy/public/property_contexts
aosp10/system/sepolicy/prebuilts/api/28.0/public/property_contexts
aosp10/system/sepolicy/prebuilts/api/29.0/public/property_contexts
在每个文件中添加一行
ro.hardware.hello u:object_r:exported_default_prop:s0 exact string
第二步,修改aosp10/system/sepolicy/vendor/file_contexts文件,添加一行
/(vendor|system/vendor)/lib(64)?/hw/hello\.default\.so u:object_r:same_process_hal_file:s0
第三步 ,修改service_contexts和service.te文件,一共有10个文件,分为5组,每组都有service_contexts和service.te两个文件
aosp10/system/sepolicy/private/service_contexts
aosp10/system/sepolicy/public/service.te
aosp10/system/sepolicy/prebuilts/api/26.0/private/service_contexts
aosp10/system/sepolicy/prebuilts/api/26.0/public/service.te
aosp10/system/sepolicy/prebuilts/api/27.0/private/service_contexts
aosp10/system/sepolicy/prebuilts/api/27.0/public/service.te
aosp10/system/sepolicy/prebuilts/api/28.0/private/service_contexts
aosp10/system/sepolicy/prebuilts/api/28.0/public/service.te
aosp10/system/sepolicy/prebuilts/api/29.0/private/service_contexts
aosp10/system/sepolicy/prebuilts/api/29.0/public/service.te
所有的 service_contexts文件添加一行
hello u:object_r:hello_service:s0
所有的 service.te文件添加一行
type hello_service, app_api_service, ephemeral_app_api_service, system_server_service, service_manager_type;
编译
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
mm ./frameworks/base/
本文涉及到的知识主要和Android架构中的应用程序框架层、系统运行库层、硬件抽象层相关