1. 添加硬件访问服务接口
在目录frameworks/base/core/java/android/os中添加IFregService.aidl接口文件
IFregService.aidl文件如下
package android.os;
/**
* {@hide}
*/
interface IFregService{
void setVal(int val);
int getVal();
}
注: 注释中需要添加{@hide},不然会出现编译问题
同时,修改frameworks/base目录下的Android.mk文件,在LOCAL_SRC_FILES变量添加IFregService.aidl值,如下:
LOCAL_SRC_FILES += \
......
core/java/android/os/IFregService.aidl \
......
2. 实现硬件访问服务
在frameworks/base/services/core/java/com/android/server目录中添加FregService.java文件
FregService.java文件
package com.android.server;
import android.content.Context;
import android.os.IFregService;
import android.util.Slog;
/**
* @hide
*/
public class FregService extends IFregService.Stub{
private static final String TAG = "FregService";
private int mPtr = 0;
FregService(){
mPtr = freg_init_native();
if (0 == mPtr)
{
Slog.e(TAG, "Failed to initialize freg service.");
}
}
public void setVal(int val){
if (0 == mPtr){
Slog.e(TAG, "Freg service is not initialized.");
return;
}
setVal_native(mPtr, val);
}
public int getVal(){
if (0 == mPtr){
Slog.e(TAG, "Freg service is not initialized.");
return 0;
}
return getVal_native(mPtr);
}
private static native int freg_init_native();
private static native void setVal_native(int ptr, int val);
private static native int getVal_native(int ptr);
};
注: 注释中需要添加{@hide},不然会出现编译问题
3. 实现硬件访问服务的JNI接口
在frameworks/base/services/core/jni目录下添加com_android_server_FregService.cpp文件
com_android_server_FregService.cpp源文件
/*************************************************************************
* 文件: com_android_server_FregService.cpp
* 作者: fantasy
* 邮箱: fantasy@gmail.com
* 创建时间: 2016年07月23日 星期六 08时32分51秒
*************************************************************************/
#define LOG_TAG "FregServiceJNI"
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include <utils/misc.h>
#include <utils/Log.h>
#include <hardware/hardware.h>
#include <hardware/freg.h>
#include <stdio.h>
namespace android
{
/**
* 设置虚拟硬件设备freg的寄存器的值
*/
static void freg_setVal(JNIEnv *env, jobject clazz, jint ptr, jint value)
{
/**
* 将参数ptr转换为freg_device_t的结构体变量
*/
freg_device_t *device = (freg_device_t*)ptr;
if (!device)
{
ALOGE("Device freg is not open.");
return;
}
int val = value;
ALOGI("Set value %d to device freg.", val);
device->set_val(device, val);
}
/**
* 读取虚拟硬件设备freg的寄存器值
*/
static jint freg_getVal(JNIEnv *env, jobject clazz, jint ptr)
{
/**
* 将参数ptr转换为freg_device_t的结构体变量
*/
freg_device_t *device = (freg_device_t*)ptr;
if (!device)
{
ALOGE("Device freg is not open.");
return 0;
}
int val = 0;
device->get_val(device, &val);
ALOGI("Get value %d from device freg.", val);
return val;
}
/**
* 打开虚拟硬件设备freg
*/
static inline int freg_device_open(const hw_module_t *module, struct freg_device_t **device)
{
return module->methods->open(module, FREG_HARDWARE_DEVICE_ID, (struct hw_device_t**)device);
}
/**
* 初始化虚拟硬件设备freg
*/
static jint freg_init(JNIEnv *env, jclass clazz)
{
hw_module_t *module;
freg_device_t *device;
ALOGI("Initializing HAL stub freg......");
/**
* 加载硬件抽象层模块freg
*/
int err = hw_get_module(FREG_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module);
if (err)
{
ALOGE("Couldn't load %s module (%s)", FREG_HARDWARE_MODULE_ID, strerror(-err));
} else {
ALOGI("Device freg found.");
/**
* 打开虚拟硬件设备freg
*/
if (freg_device_open(module, &device) == 0)
{
ALOGI("Device freg is open.");
/**
* 将freg_device_t接口转换为整型值返回
*/
return (jint)device;
}
ALOGE("Failed to open device freg.");
return 0;
}
ALOGE("Failed to get HAL stub freg.");
return 0;
}
/**
* Java本地接口方法表
*/
static const JNINativeMethod method_table[] = {
{"freg_init_native", "()I", (void*)freg_init},
{"setVal_native", "(II)V", (void*)freg_setVal},
{"getVal_native", "(I)I", (void*)freg_getVal},
};
/**
* 注册Java本地接口方法
*/
int register_android_server_FregService(JNIEnv *env)
{
return jniRegisterNativeMethods(env, "com/android/server/FregService", method_table, NELEM(method_table));
}
}
同时,在目录frameworks/base/services/core/jni的onload.cpp文件中添加如下代码
#include "JNIHelp.h"
#include "jni.h"
#include "utils/Log.h"
#include "utils/misc.h"
namespace android {
......
int register_android_server_FregService(JNIEnv* env);
};
using namespace android;
4. 启动硬件访问服务
在frameworks/base/services/java/com/android/server目录下的SystemServer.java中,添加如下内容
private void startOtherServices() {
......
if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
......
try{
Slog.i(TAG, "Freg Service");
ServiceManager.addService("freg", new FregService());
} catch (Throwable e) {
Slog.e(TAG, "Failure staring Freg Service", e);
}
....
}
}
5. 相关权限配置
对/system/sepolicy目录下的如下文件进行相应修改
device.te
domain.te
file_contexts
service.te
service_contexts
system_app.te
system_server.te
untrusted_app.te
修改如下:
在device.te文件中添加
在domain.te文件中添加
allow domain freg_device:chr_file rw_file_perms;
在file_contexts文件中添加
/dev/freg u:object_r:freg_device:s0
在service.te中文件中添加
type freg_service, system_api_service, system_server_service, service_manager_type;
在service_contexts文件中添加
freg u:object_r:freg_service:s0
在system_server.te文件中添加
allow system_server freg_device:chr_file rw_file_perms;
在untrusted_app.te文件中添加
allow untrusted_app freg_service:service_manager find;
在system_app.te文件中添加
allow system_app freg_service:service_manager find;
不然APP中调用该freg_service服务时会出现问题,见:
http://blog.csdn.net/fantasy_wxe/article/details/52013922
参考
《Android系统源代码情景分析》第2.4节