7.1系统Hal层添加服务流程
一.hardware层编写
1.准备工作
确保物理设备正常连接,cd dev/目录下查看可用设备,可以看到设备dev路径,如果遇到打开设备PemissionDenied问题,进入system/core/rootdir/uenentd.rc,添加/dev/xxx 0666 root root 权限
2.hardware目录新建硬件服务
2.1在源码根目录下:hardware/libhardware/include/hardware 新建het.h丶IDeviceCallback.h丶types.h文件
het.h
#ifndef _HARDWARE_IHET_H
#define _HARDWARE_IHET_H
#include <stdint.h>
#include <strings.h>
#include <sys/cdefs.h>
#include <sys/types.h>
#include "IDeviceCallback.h"
#include <hardware/hardware.h>
#include <utils/Thread.h>
#include <cutils/log.h>
#include <cutils/atomic.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <linux/input.h>
#include<string>
#include "types.h"
__BEGIN_DECLS
#define IHET_HARDWARE_MODULE_ID "het"
#define VL6180_IOCTL_INIT _IO('p', 0x01)
bool threadLoop();
int open_ranging_device(int on);
void get_event(int fd);
void event_callback(int what, std::string msg);
struct ihet_module_t {
struct hw_module_t common;
};
typedef struct ihet_device {
struct hw_device_t common;
int fd;
std::string(*setState)(struct ihet_device *ihet_module,const DeviceType& type);
std::string(*getState)(struct ihet_device *ihet_module,int32_t type);
bool(*setCallback)(struct ihet_device *ihet_module,const android::sp<IDeviceCallback>& callback);
void(*release)();
} ihet_device_t;
__END_DECLS
#endif
IDeviceCallback.h
#ifndef _HARDWARE_IDEVICECALLBACK_H
#define _HARDWARE_IDEVICECALLBACK_H
#include <stdint.h>
#include <sys/types.h>
#include "types.h"
#include <stdio.h>
#include <utils/RefBase.h>
using namespace android;
class IDeviceCallback : public LightRefBase<IDeviceCallback>
{
private:
public:
IDeviceCallback();
~IDeviceCallback();
void onDeviceEvent(DeviceEvent __event);
};
IDeviceCallback::IDeviceCallback()
{
}
IDeviceCallback::~IDeviceCallback()
{
}
void IDeviceCallback::onDeviceEvent(DeviceEvent __event){
}
#endif
types.h
#ifndef _HARDWARE_TYPES_H
#define _HARDWARE_TYPES_H
#include <stdint.h>
#include <string>
struct DeviceType{
int32_t type;
int32_t state;
};
struct DeviceEvent{
int32_t what;
std::string msg;
};
2.2在源码目录下:hardware/libhardware/modules 新建het目录,在该目录下新建het.cpp 和 Android.mk 文件
het.cpp
#define LOG_TAG "Het_cpp"
#include <hardware/Het.h>
#include <hardware/hardware.h>
#include <cutils/atomic.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <stdlib.h>
#include <linux/types.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <cutils/log.h>
#include <malloc.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <math.h>
#define DOOR_PATH "/dev/door"
#define LOCK_P_PATH "/dev/lock_p"
#define LOCK_N_PATH "/dev/lock_n"
#define CHARGER_PATH "/dev/charger"
#define UV_LAMP_PATH "/dev/uv_lamp"
#define RANGING_PATH "/dev/ranging"
#define THERMOMETRY_PATH "/dev/thermometry"
#define DEVICE_NAME "/dev/het"
#define MODULE_NAME "het"
#define MODULE_AUTHOR "nailliu@gmail.com"
android::sp<IDeviceCallback> mCallback = nullptr;
bool m_exit = true;
int range_fd = -1, event_fd = -1;
int g_bl_fd = 0;
int g_btn_fd = 0;
int g_bat_fd = 0;
static int read_int(char const *path) {
int fd;
static int already_warned;
already_warned = 0;
ALOGE("read_int: path %s", path);
fd = open(path, O_RDWR);
if (fd >= 0) {
int result;
int amt = read(fd, &result, 4);
ALOGE("read_int: result %d", result);
close(fd);
return amt == -1 ? -1 : result;
} else {
if (already_warned == 0) {
ALOGE("read_int failed to open %s\n", path);
already_warned = 1;
}
return -1;
}
}
static int write_int(char const *path, int value) {
int fd;
static int already_warned;
already_warned = 0;
ALOGE("write_int: path %s, value %d", path, value);
fd = open(path, O_RDWR);
if (fd >= 0) {
int amt = write(fd, &value, sizeof(int));
close(fd);
return amt == -1 ? -errno : 0;
} else {
if (already_warned == 0) {
ALOGE("write_int failed to open %d, %s\n", fd, path);
already_warned = 1;
}
return -errno;
}
}
static std::string het_setState(struct ihet_device *dev,const DeviceType& type) {
int ret = 0;
char buffer[20];
memset(buffer, 0, sizeof(buffer));
if (type.type == 0) {
ret = write_int(LOCK_P_PATH, type.state);
ret = write_int(LOCK_N_PATH, !type.state);
} else if (type.type == 1) {
ret = write_int(UV_LAMP_PATH, type.state);
} else if (type.type == 2) {
ret = open_ranging_device(type.state);
} else if (type.type == 3) {
ret = write_int(THERMOMETRY_PATH, type.state);
} else if (type.type == 5) {
ret = write_int(LOCK_P_PATH, 0);
ret = write_int(LOCK_N_PATH, 0);
}
return "";
}
static std::string het_getState(struct ihet_device *dev,int32_t type) {
int ret = 0;
char buffer[20];
memset(buffer, 0, sizeof(buffer));
ALOGE("getState: %d", type);
if (type == 0) {
ret = read_int(DOOR_PATH);
} else if (type == 1) {
ret = read_int(CHARGER_PATH);
}
return "";
}
static bool het_setCallback(struct ihet_device *dev,const android::sp<IDeviceCallback>& callback) {
mCallback = callback;
bool res = false;
if(mCallback != nullptr) {
ALOGE("setCallback: done");
res = true;
}
return res;
}
static void het_release() {
m_exit = true;
ALOGE("release:");
return;
}
bool threadLoop(){
ALOGI("threadLoop====\n");
int ret;
char buf[] = "/dev/input/event1";
DeviceEvent event;
range_fd = open(RANGING_PATH, O_RDWR);
if (range_fd < 0) {
ALOGE("open dev RANGING_PATH err!\n");
event_callback(-1, "open dev RANGING_PATH err");
return false;
}
ALOGI("threadLoop range_fd = %d\n", range_fd);
ret = ioctl(range_fd, VL6180_IOCTL_INIT);
if (ret == -1) {
ALOGE("ioctl VL6180_IOCTL_INIT : %s\n", strerror(errno));
event_callback(-1, "ioctl VL6180_IOCTL_INIT");
close(range_fd);
range_fd = -1;
return false;
}
ALOGI("threadLoop ret = %d\n", ret);
usleep(200 * 1000);
ALOGI("threadLoop ret1 = %d\n", ret);
event_fd = open(buf, O_RDONLY);
if (event_fd < 0) {
ALOGE("%s opened event =%d \n", buf, event_fd);
event_callback(-1, "opened event failed");
close(range_fd);
range_fd = -1;
return false;
}
m_exit = false;
while (!m_exit) {
get_event(event_fd);
}
if (range_fd > 0) {
close(range_fd);
range_fd = -1;
}
if (event_fd > 0) {
close(event_fd);
event_fd = -1;
}
ALOGE("threadLoop: exit");
return false;
}
int open_ranging_device(int on) {
ALOGI("open_ranging_device = %d\n", on);
if (on == 0) {
ALOGI("open_ranging_device m_exit = %d\n", m_exit);
ALOGI("open_ranging_device range_fd = %d\n", range_fd);
ALOGI("open_ranging_device event_fd = %d\n", event_fd);
m_exit = true;
return 0;
} else {
if (range_fd > 0 && event_fd > 0 && !m_exit) {
ALOGE("range_fd =%d, event_fd =%d m_exit =%d\n", range_fd, event_fd, m_exit);
return 0;
}
ALOGI("open_ranging_device m_exit = %d\n", m_exit);
ALOGI("open_ranging_device range_fd = %d\n", range_fd);
ALOGI("open_ranging_device event_fd = %d\n", event_fd);
run("read_event_thread");
}
return 0;
}
void get_event(int fd) {
int ret;
struct input_event event;
if (fd < 0) {
return;
}
ret = read(fd, &event, sizeof(event));
switch (event.type) {
case EV_ABS:
if (event.code == ABS_HAT1X) {
ALOGI("ABS_HAT1X range_mm = %d\n", event.value);
event_callback(event.code, std::to_string(event.value));
} else if (event.code == ABS_HAT1Y) {
ALOGE("ABS_HAT1Y errorStatus= %d\n", event.value);
if (event.value == 0) {
break;
event_callback(event.code, std::to_string(event.value));
} else if (event.code == ABS_HAT3Y) {
break;
}
break;
default:
break;
}
return;
}
}
void event_callback(int what, std::string msg) {
DeviceEvent event;
event.what = what;
event.msg = msg;
if(mCallback != nullptr) {
mCallback->onDeviceEvent(event);
}
return;
}
static int het_device_close(struct hw_device_t* device) {
struct ihet_device* ihet_device = (struct ihet_device*)device;
if(ihet_device) {
close(ihet_device->fd);
free(ihet_device);
}
return 0;
}
static int het_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device) {
struct ihet_device* dev;dev = (struct ihet_device*)malloc(sizeof(struct ihet_device));
if(!dev) {
ALOGE("Hello Stub: failed to alloc space");
return -EFAULT;
}
memset(dev, 0, sizeof(struct ihet_device));
dev->common.tag = HARDWARE_DEVICE_TAG;
dev->common.version = 0;
dev->common.module = (hw_module_t*)module;
dev->common.close = het_device_close;
dev->setState = het_setState;
dev->getState = het_getState;
dev->setCallback = het_setCallback;
dev->release = het_release;
if((dev->fd = open(DEVICE_NAME, O_RDWR)) == -1) {
ALOGE("Het Stub: failed to open /dev/het -- %s.", strerror(errno));free(dev);
return -EFAULT;
}
*device = &(dev->common);
ALOGI("Het Stub: open /dev/het successfully.");
return 0;
}
static struct hw_module_methods_t ihet_module_methods = {
.open = het_device_open,
};
struct ihet_module_t HAL_MODULE_INFO_SYM = {
common: {
tag: HARDWARE_MODULE_TAG,
version_major: 1,
version_minor: 0,
id: IHET_HARDWARE_MODULE_ID,
name: MODULE_NAME,
author: MODULE_AUTHOR,
methods: &ihet_module_methods,
}
};
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := het.default
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_SRC_FILES := Het.cpp
LOCAL_SHARED_LIBRARIES := liblog libcutils
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
2.3在源码根目录下:hardware/libhardware/modules 修改Android.mk 添加het 文件夹名
hardware_modules := gralloc hwcomposer audio nfc nfc-nci local_time \
power usbaudio audio_remote_submix camera usbcamera consumerir sensors vibrator \
tv_input fingerprint input vehicle thermal vr het
include $(call all-named-subdir-makefiles,$(hardware_modules))
2.4编译hardware的.so库
在源码根目录下执行:mmm hardware/libhardware/modules/het/ 会对het 模块进行编译
在源码根目录下产生 out/target/product/rk3288/obj/lib/het.default.so.toc
3.编写JNI,提供JAVA和C/C++交互接口
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include <utils/misc.h>
#include <cutils/log.h>
#include <hardware/hardware.h>
#include <hardware/iic.h>
#include <stdio.h>
namespace android
{
struct iic_device *iic_dev = NULL;
static void iic_setVal(JNIEnv* env, jobject clazz, jint slaveAddr, jint regAddr, jint databuf) {
if(!iic_dev) {
ALOGE("iic JNI: device is not open.");
}
iic_dev->iic_write(iic_dev,slaveAddr,regAddr,databuf);
}
static jint iic_getVal(JNIEnv* env, jobject clazz,jint slaveAddr, jint regAddr) {
unsigned char data[1] = {0};
iic_dev->iic_read(iic_dev,slaveAddr,regAddr,data);
if(!iic_dev) {
ALOGE("iic JNI: device is not open.");
}
return data[0];
}
/*通过硬件模块ID来加载指定的硬件抽象层模块并打开硬件*/
static jboolean iic_init(JNIEnv* env, jclass clazz) {
iic_module_t *module;
int err;
err = hw_get_module(IIC_HARDWARE_MODULE_ID,(const struct hw_module_t**)&module);
if (err != 0) {
ALOGE("Error acquiring iic hardware module: %d", err);
return 0;
}
err = iic_open(&(module->common), &iic_dev);
if (err != 0) {
ALOGE("Error opening iic hardware module: %d", err);
return 0;
}
ALOGE("iic device is opening...");
return 1;
}
/*JNI方法表*/
static const JNINativeMethod method_table[] = {
{"init_native", "()Z", (void*)iic_init},
{"setVal_native", "(III)V", (void*)iic_setVal},
{"getVal_native", "(II)I", (void*)iic_getVal},
};
/*注册JNI方法*/
int register_android_server_IICService(JNIEnv *env) {
return jniRegisterNativeMethods(env, "com/android/server/IICService", method_table, NELEM(method_table));
}
};
在源码根目录下:frameworks/base/services/core/jni
- 新建com_android_server_HETService.cpp,然后需要让Android启动时加载此jni模块
- 在同目录下修改onload.cpp: 在namespace android中添加一行: int register_android_server_HETService(JNIEnv *env);
- 在JNI_onLoad方法中添加一行: register_android_server_HETService(env);
- 在同目录下修改Android.mk: LOCAL_SRC_FILES增加一行: $(LOCAL_REL_DIR)/com_android_server_HETService.cpp \
在源码根目录下执行:mmm frameworks/base/services/core/jni 对该模块进行编译
二.编写系统服务JAVA代码
1.定义好服务可以调用的方法的aidl
在源码根目录下:frameworks/base/core/java/android/os/het
1)新建IHetService.aidl丶DeviceListenerEvent.aidl和IDeviceEventListener.aidl文件
2)修改frameworks/base下的Android.mk编译文件,在LOCAL_SRC_FILES中增加
core/java/android/os/IHetService.aidl和 \core/java/android/os/het/IDeviceEventListener.aidl \
IHetService.aidl
package android.os.het;
import android.os.het.IDeviceEventListener;
interface IHetService {
String setState(int type, int state);
String getState(int type);
boolean setDeviceEventListener(IDeviceEventListener listener);
void release();
}
DeviceListenerEvent.aidl
package android.os.het;
parcelable DeviceListenerEvent;
IDeviceEventListener.aidl
package android.os.het;
import android.os.het.DeviceListenerEvent;
interface IDeviceEventListener {
void onEvent (inout DeviceListenerEvent event);
}
在源码根目录下执行:mmm frameworks/base 对该模块进行编译
2.实现DeviceListenerEvent.aidl和IDeviceEventListener.aidl的Java方法
2.1在源码根目录下:frameworks/base/core/java/android/os/het,编写DeviceEventListener.java和DeviceListenerEvent.java
DeviceEventListener.java
package android.os.het;
/**
* android.os.het
*
* 2020/6/29
*/
public abstract class DeviceEventListener extends IDeviceEventListener.Stub {
}
DeviceListenerEvent.java
package android.os.het;
import android.os.Parcel;
import android.os.Parcelable;
public class DeviceListenerEvent implements Parcelable {
private int what;
private String msg;
public DeviceListenerEvent(int what, String msg) {
this.what = what;
this.msg = msg;
}
public DeviceListenerEvent(Parcel in) {
what = in.readInt();
msg = in.readString();
}
public void setWhat(int what) {
this.what = what;
}
public void setMsg(String msg) {
this.msg = msg;
}
public int getWhat() {
return what;
}
public String getMsg() {
return msg;
}
public static final Creator<DeviceListenerEvent> CREATOR = new Creator<DeviceListenerEvent>() {
@Override
public DeviceListenerEvent createFromParcel(Parcel in) {
return new DeviceListenerEvent(in);
}
@Override
public DeviceListenerEvent[] newArray(int size) {
return new DeviceListenerEvent[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(what);
dest.writeString(msg);
}
public void readFromParcel(Parcel dest) {
what = dest.readInt();
msg = dest.readString();
}
}
2.2编写HetManager.java提供给上层访问
HetManager.java
package android.os.het;
import android.os.RemoteException;
import android.util.Log;
import android.os.het.IHetService;
import android.content.Context;
public class HetManager {
private final Context mContext;
private IHetService mService;
public static final String TAG = "HetManager";
public HetManager(IHetService server) {
Log.d(TAG, "HetManager: ");
mContext = null;
mService = server;
}
public HetManager(Context context, IHetService server) {
Log.d(TAG, "HetManager: ");
mContext = context;
mService = server;
}
public String setState(int type, String state) {
Log.d(TAG, "setState: " + type + " " + state);
try {
if (mService != null) {
return mService.setState(type, state);
}
} catch (RemoteException e) {
e.printStackTrace();
}
return "";
}
public String getState(int type) {
Log.d(TAG, "getState: " + type);
try {
if (mService == null) {
return null;
}
return mService.getState(type);
} catch (RemoteException e) {
e.printStackTrace();
}
return "service connect failed";
}
public boolean setDeviceListener(DeviceEventListener listener) {
Log.d(TAG, "setDeviceListener: ");
try {
if (mService == null) {
return false;
}
return mService.setDeviceEventListener(listener);
} catch (RemoteException e) {
e.printStackTrace();
return false;
}
}
public void release() {
Log.d(TAG, "release: ");
try {
if (mService != null) {
mService.release();
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
3.编写上层使用的Service
3.1在源码根目录下:frameworks/base/services/core/java/com/android/server,添加HetService.java
HetService.java
package com.android.server.het;
import android.content.Context;
import android.hardware.het.V1_0.IHet;
import android.hardware.het.V1_0.DeviceType;
import android.hardware.het.V1_0.IDeviceCallback;
import android.hardware.het.V1_0.DeviceEvent;
import android.os.RemoteException;
import android.os.het.DeviceListenerEvent;
import android.os.het.IDeviceEventListener;
import android.os.het.IHetService;
import android.util.Log;
public class HetService extends IHetService.Stub {
private String TAG = "HetService";
private final Context mContext;
private IHet halService ;
public HetService(Context context){
mContext = context;
try {
halService = IHet.getService();
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public String setState(int type, String state) throws RemoteException {
DeviceType deviceType = new DeviceType();
deviceType.type = type;
deviceType.state = state;
return halService.setState(deviceType);
}
@Override
public String getState(int type) throws RemoteException {
return halService.getState(type);
}
@Override
public boolean setDeviceEventListener(IDeviceEventListener listener) throws RemoteException {
Log.d(TAG, "setDeviceEventListener: ");
DeviceCallback callback = new DeviceCallback(listener);
return halService.setCallback(callback);
}
@Override
public void release() throws RemoteException {
Log.d(TAG, "release: ");
halService.release();
}
class DeviceCallback extends IDeviceCallback.Stub{
IDeviceEventListener mIDeviceEventListener;
DeviceCallback (IDeviceEventListener listener){
mIDeviceEventListener = listener;
}
@Override
public void onDeviceEvent(DeviceEvent event) throws RemoteException {
Log.d(TAG, "onDeviceEvent: ");
DeviceListenerEvent deviceListenerEvent = new DeviceListenerEvent(event.what,event.msg);
mIDeviceEventListener.onEvent(deviceListenerEvent);
}
}
}
3.2修改frameworks/base/services/java/com/android/server下的SystemServer.java在private void startOtherServices() 添加HetService
import com.android.server.HetService;
private void startOtherServices() {
HetService het = null;
boolean disableHet = SystemProperties.getBoolean("config.disable_het", false);
try {
Slog.i(TAG, "het Service");
het = new HetService(context);
ServiceManager.addService("het", het);
} catch (Throwable e) {
Slog.e(TAG, "Failure starting HetService", e);
}
}
在源码根目录下执行:mmm frameworks/base/services 对该模块进行编译
3.3添加服务安全策略se
在源码system/sepolicy/service.te新增
type yyy, system_api_service, system_server_service, service_manager_type;
在源码system/sepolicy/service_contexts新增
xxx u:object_r:yyy:s0
三、应用层调用service
1.在源码/out/target/common/obj/JAVA_LIBRARIES/framework_intermediates路径下拷贝classes.jar到工程libs目录并引用,即可使用该服务
|