添加 aidl 文件
添加 aidl 文件 frameworks/base/core/java/android/os/IHelloService.aidl
:
java
package android.os;
interface IHelloService
{
void open();
void write(String str);
String read();
}
在 frameworks/base/Android.mk
中添加上 aidl 文件:
Makefile
LOCAL_SRC_FILES += \
core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl \
core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl \
core/java/android/accounts/IAccountManager.aidl \
core/java/android/accounts/IAccountManagerResponse.aidl \
core/java/android/accounts/IAccountAuthenticator.aidl \
# .......
core/java/android/os/IHelloService.aidl \ # 添加的内容
core/java/android/security/IKeystoreService.aidl \
core/java/android/service/carrier/ICarrierService.aidl
# ......
实现服务端
添加 frameworks/base/services/core/java/com/android/server/HelloService.java
文件:
Java
package com.android.server;
import android.os.IHelloService;
// 硬件服务的服务端实现
public class HelloService extends IHelloService.Stub {
public native void natvieOpen();
public native void natvieWrite(String str);
public native String nativeRead();
public void open() throws android.os.RemoteException {
natvieOpen();
}
public void write(String str) throws android.os.RemoteException {
natvieWrite(str);
}
public String read() throws android.os.RemoteException {
return nativeRead();
}
}
JNI 层实现
添加 frameworks/base/services/core/jni/com_android_server_HelloService.cpp
JNI 实现:
cpp
#define LOG_TAG "HelloService"
#include <jni.h>
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include <utils/misc.h>
#include <utils/Log.h>
#include <hardware/hello_hal.h>
#include <stdio.h>
#include <string>
namespace android
{
static hw_module_t *gHelloModule = NULL;
static hello_hal_device_t *gHelloHalDevice = NULL;
static void helloOpen(JNIEnv env, jobject clazz)
{
ALOGD("yuandaima_jni_open");
if (gHelloModule != NULL) {
return;
}
int err = hw_get_module(HELLO_HAL_HARDWARE_MODULE_ID, (hw_module_t const**)&gHelloModule);
if (err) {
ALOGE("Couldn't load %s module (%s)", HELLO_HAL_HARDWARE_MODULE_ID, strerror(-err));
} else {
if (gHelloModule) {
ALOGD("yuandaima_jni_open get module sucess");
hello_hal_methods_open(gHelloModule, &gHelloHalDevice);
}
}
if(gHelloHalDevice) {
gHelloHalDevice->hello_hal_open(gHelloHalDevice);
}
}
static void helloWrite(JNIEnv* env, jobject clazz, jstring str)
{
if (gHelloHalDevice) {
ALOGD("yuandaima_jni_write");
const char * c_str = NULL;
jboolean isCopy;
c_str = env->GetStringUTFChars(str, &isCopy); //从jstring指针中获取数据
ALOGD("yuandaima_jni_write %s",c_str);
gHelloHalDevice->hello_hal_write(gHelloHalDevice, c_str);
}
else {
ALOGW("Tried to hello but there is no hello device.");
}
}
static jstring helloRead(JNIEnv* env, jobject clazz)
{
if (gHelloHalDevice) {
ALOGD("yuandaima_jni_read");
char* data = NULL;
gHelloHalDevice->hello_hal_read(gHelloHalDevice, &data);
ALOGD("yuandaima_jni_read result is %s", data);
if(data != NULL ) {
// Android7 上直接用 NewStringUTF 把 char* 转 jstring 有乱码缺码 bug
jbyteArray array = env->NewByteArray(1024);
env->SetByteArrayRegion(array, 0, 1024,(const jbyte *)data);
jstring strEncode = env->NewStringUTF("UTF-8");
jclass cls = env->FindClass("java/lang/String");
jmethodID ctor = env->GetMethodID(cls, "<init>", "([BLjava/lang/String;)V");
jstring ret = (jstring) env->NewObject(cls, ctor, array, strEncode);
return ret;
}
}
return env->NewStringUTF("no msg");
}
// public native void natvieOpen();
// public native void natvieWrite(String str);
// public native String nativeRead();
static const JNINativeMethod method_table[] = {
{ "natvieOpen", "()V", (void*)helloOpen },
{ "natvieWrite", "(Ljava/lang/String;)V", (void*)helloWrite },
{ "nativeRead", "()Ljava/lang/String;", (void*)helloRead }
};
int register_android_server_HelloService(JNIEnv *env)
{
ALOGD("yuandaima_jni_register");
return jniRegisterNativeMethods(env, "com/android/server/HelloService",
method_table, NELEM(method_table));
}
};
在 frameworks/base/services/core/jni/Android.mk
中添加:
Makefile
LOCAL_SRC_FILES += \
# ......
$(LOCAL_REL_DIR)/com_android_server_UsbMidiDevice.cpp \
$(LOCAL_REL_DIR)/com_android_server_UsbHostManager.cpp \
$(LOCAL_REL_DIR)/com_android_server_VibratorService.cpp \
$(LOCAL_REL_DIR)/com_android_server_HelloService.cpp \ # 添加的内容
$(LOCAL_REL_DIR)/com_android_server_PersistentDataBlockService.cpp \
$(LOCAL_REL_DIR)/onload.cpp
在 frameworks/base/services/core/jni/onload.cpp
中添加:
cpp
// 在这里注册 JNI 函数
// java 层的 native 方法就能调用到对应的 native 层函数了
extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
{
JNIEnv* env = NULL;
jint result = -1;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
ALOGE("GetEnv failed!");
return result;
}
ALOG_ASSERT(env, "Could not retrieve the env!");
register_android_server_ActivityManagerService(env);
register_android_server_PowerManagerService(env);
// ......
register_android_server_VibratorService(env);
register_android_server_HelloService(env); // 添加的内容
register_android_server_SystemServer(env);
register_android_server_location_GnssLocationProvider(env);
register_android_server_location_FlpHardwareProvider(env);
// ......
return JNI_VERSION_1_4;
}
客户端实现
添加一个接口 frameworks/base/core/java/android/os/HelloHal.java
:
java
package android.os;
import android.app.ActivityThread;
import android.content.Context;
public abstract class HelloHal {
public HelloHal() {
}
public abstract int open() throws RemoteException;
public abstract int write(String st) throws RemoteException;
public abstract String read() throws RemoteException;
}
实现接口 frameworks/base/core/java/android/os/SystemHelloHal.java
:
java
package android.os;
import android.content.Context;
import android.util.Log;
/**
* Vibrator implementation that controls the main system vibrator.
*
* @hide
*/
public class SystemHelloHal extends HelloHal {
private static final String TAG = "HelloHal";
private final IHelloService mService;
// 获取Hello服务的代理端
public SystemHelloHal() {
mService = IHelloService.Stub.asInterface(
ServiceManager.getService("hello"));
}
// 通过代理端对象发起远程调用
@Override
public int open() throws RemoteException{
if (mService != null) {
mService.open();
}
return -1;
}
@Override
public int write(String str) throws RemoteException {
if (mService != null) {
mService.write(str);
}
return -1;
}
@Override
public String read() throws RemoteException {
if (mService != null) {
return mService.read();
}
return null;
}
}
最后在 SystemServiceRegistry 的静态块中添加:
java
// frameworks/base/core/java/android/app/SystemServiceRegistry.java
static {
registerService(Context.HELLO_SERVICE, HelloHal.class,
new CachedServiceFetcher<HelloHal>() {
@Override
public HelloHal createService(ContextImpl ctx) {
return new SystemHelloHal();
}});
}
Selinux 配置
修改 system/sepolicy/service.te:
bash
type HelloServiceType, app_api_service, system_server_service, service_manager_type;
修改 system/sepolicy/service_contexts:
bash
HelloService u:object_r:HelloServiceType:s0
修改 system/sepolicy/platform_app.te,让系统 App 可以访问我们自定义的 Binder 服务:
bash
allow platform_app HelloServiceType:service_manager find;
修改 system/sepolicy/untrusted_app.te,让普通 App 可以访问我们自定义的 Binder 服务:
bash
allow untrusted_app HelloServiceType:service_manager find;
最后,让 SystemServer 可以访问到 hello 驱动,修改 system/sepolicy/system_server.te
:
bash
allow system_server hello_dev_t:chr_file { open read write };
编译
bash
source build/envsetup.sh
lunch aosp_x86_64-eng
# 在 com.android.server 包中添加了 HelloService 后,给系统添加了 API
make update-api
make -j32
# 启动模拟器
emulator -kernel /tmp/kernel-qemu/x86_64-3.10.0/kernel-qemue