目标:在安卓5.0里添加一个ledservice的硬件访问服务,让其他app可以通过我们的ledservice来控制led灯。
一、定义service提供给其他app的接口:.aidl文件
我们的LedService是要替其他app去控制led硬件的,所以肯定要有一个ILedService.java的文件里提供了一些接口,对于这个.java文件,我们可以提供一个aidl文件,然后用安卓的编译系统来生成。
代码如下,并将这个文件放在frameworks/base/core/java/android/hardware/目录下
package android.hardware;
/** @hide */
interface ILedService //这里接口的名字必须于文件名一致
{
/**
*
*/
int leds_ctrl(int id, bool on);
}
修改frameworks/base/android.mk文件,将aidl文件添加到安卓的编译系统
在framework/base目录下使用mmm .命令编译,编译成功后,在out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/hardware/目录下就会有安卓编译系统帮我们生成的java接口文件ILedService.java
打开这个ILedService.java文件
可以看到,这个ILedService是一个interface接口,里面声明了led_ctrl方法
二、实现接口的实际方法
我们要写一个LedService.java文件,这个class LedService要extends ILedService.stub。覆写其中的led_ctrl方法
package com.android.hardware;
import android.hardware.ILedService;
/** @hide */
public class LedService extends ILedService.Stub
{
public static native int native_leds_ctrl(int id, boolean on);
public int leds_ctrl(int id, boolean on) throws android.os.RemoteException{
return native_leds_ctrl(id, on);
}
}
将这个文件放到frameworks/base/services/core/java/com/android/server/目录下
不需要修改Android.mk,因为android-5.0.2/frameworks/base/services/Android.mk文件里已经定义要把services目录下的所有java文件都编译进去了
在frameworks/base/services/java/com/android/server/目录下的SystemServer.java文件里的StartOtherServices()方法中添加我们的LedService!
编译:
book@book-virtual-machine:/work/android-5.0.2$ mmm frameworks/base/services/
在out/target/common/obj/JAVA_LIBRARIES/services.core_intermediates/classes/com/android/hardware目录下就会有LedService.class
三、jni文件编写
为了让LedService.java中的native 方法和jni文件里的函数直接建立映射,我们需要定义一个JNINativeMethod 结构体数组来描述java中方法名和c中函数名的对应关系,调用jniRegisterNativeMethods()函数注册,同时加载hal库,然后在jni函数里调用对应的hal层接口,控制led。
/frameworks/base/services/core/jni/com_android_server_LedService.cpp的代码如下:
#define LOG_TAG "LedService_jni"
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include <utils/misc.h>
#include <utils/Log.h>
#include <dlfcn.h>
#include <stdio.h>
#define HAL_PATH "/vendor/lib/libled.so"
namespace android {
int (*led_open)(void);
int (*led_ctl)(int id, int stat);
/*
* Class: com_android_hardware_LedService_bkp
* Method: native_leds_ctrl
* Signature: (IZ)I
*/
JNIEXPORT jint JNICALL jni_leds_ctrl
(JNIEnv *env, jclass cls, jint id, jboolean on){
if (on)
return led_ctl(id, 1); //调用hal层接口,控制led
else
return led_ctl(id, 0);
}
static JNINativeMethod method_table[] = {
{
"native_leds_ctrl", "(IZ)I", (void*)jni_leds_ctrl }
};
int register_android_server_LedService(JNIEnv *env)
{
void *handle;
/* 加载hal库*/
handle = dlopen(HAL_PATH, RTLD_LAZY);
if(!handle){
fprintf(stderr, "%s\n", dlerror());
return -1;
}
//获得hal层接口
led_open = (int (*)(void))dlsym(handle, "led_open");
led_ctl = (int (*)(int id, int stat))dlsym(handle, "led_ctl");
if (!led_open || !led_ctl) {
ALOGI(LOG_TAG,"get hal interface failed\n");
}
led_open();
return jniRegisterNativeMethods(env, "com/android/hardware/LedService",
method_table, NELEM(method_table));
}
};
在/frameworks/base/services/core/jni/onload.cpp里注册LedService
修改Android.mk
编译
book@book-virtual-machine:/work/android-5.0.2/frameworks/base/services$ mmm