Android N 添加系统服务Freg
2017-05-18 17:49
561 查看
本文是基于《Android系统源代码情景分析》第二章 硬件抽象层
代码是在MTK N版本上编译通过的,如果是原生代码,相关路径会有所变化。
老罗的代码是Android 2.3的,驱动代码在最新的N版本上已经编译不过了,所以重新修改了下,同时添加selinux权限,并实现了一个fregd守护进程。
原始的代码是FregService是通过JNI->HAL->驱动来读写/dev/freg的,新加了fregd守护进程,这样FregService就可以通过binder->HAL->驱动来读写/dev/freg了。
fregd是仿造system/core/fingerprintd写的。
源码下载
以下是新添加的selinux权限,具体语法可查看老罗相关的文章
device/mediatek/common/sepolicy/basic/device.te
device/mediatek/common/sepolicy/basic/file_contexts
device/mediatek/common/sepolicy/basic/service.te
device/mediatek/common/sepolicy/basic/service_contexts
device/mediatek/common/sepolicy/basic/freg.te
创建一个fregd可执行文件,在init.rc里启动,会添加一个名为android.os.IFregDaemon的系统服务。
IFregDaemon.h
IFregDaemon.cpp
FregDaemonProxy.h
FregDaemonProxy.cpp
fregd.cpp
Android.mk
添加到init.rc里,debug.fregd属性用于debug时手动开启和停止服务
添加对应的framework接口,顺序必须与IFregDaemon.h里的枚举一致。
core/java/android/os/IFregDaemon.aidl
在FregService添加对应的方法
frameworks/base/services/java/com/android/server/FregService
添加到编译系统里去
frameworks/base/Android.mk
这样FregSevice就可以通过fregd去读写驱动了。
推荐文章
Binder系列8—如何使用Binder
代码是在MTK N版本上编译通过的,如果是原生代码,相关路径会有所变化。
老罗的代码是Android 2.3的,驱动代码在最新的N版本上已经编译不过了,所以重新修改了下,同时添加selinux权限,并实现了一个fregd守护进程。
原始的代码是FregService是通过JNI->HAL->驱动来读写/dev/freg的,新加了fregd守护进程,这样FregService就可以通过binder->HAL->驱动来读写/dev/freg了。
fregd是仿造system/core/fingerprintd写的。
源码下载
以下是新添加的selinux权限,具体语法可查看老罗相关的文章
device/mediatek/common/sepolicy/basic/device.te
type freg_device, dev_type;
device/mediatek/common/sepolicy/basic/file_contexts
/dev/freg(/.*)? u:object_r:freg_device:s0 /system/bin/fregd u:object_r:fregd_exec:s0
device/mediatek/common/sepolicy/basic/service.te
type freg_service, service_manager_type; type fregd_service, service_manager_type;
device/mediatek/common/sepolicy/basic/service_contexts
freg u:object_r:freg_service:s0 android.os.IFregDaemon u:object_r:fregd_service:s0
device/mediatek/common/sepolicy/basic/freg.te
#java服务FregService需要添加的权限 #for FregService allow system_server freg_device:chr_file {read write}; allow system_server freg_device:chr_file {open}; allow system_server freg_service:service_manager {add}; allow untrusted_app freg_service:service_manager {find}; allow system_app freg_service:service_manager {find}; #domain 切换 #init_daemon_domain(mediaserver) #这个是一个TE操作宏, 简单来说就是当init fork子进程执行fregd_exec 这个类型的执行档时, 其domain从init切换到fregd. #守护进程fregd需要添加的权限 #for fregd type fregd, domain; type fregd_exec, exec_type, file_type; init_daemon_domain(fregd) #system/bin/fregd u:object_r:fregd_exec:s0 allow fregd freg_device:chr_file {open read write}; allow fregd fregd_service:service_manager {add}; allow fregd servicemanager:binder {call transfer}; allow system_server fregd_service:service_manager {find}; allow system_server fregd:binder {call}; allow servicemanager fregd:dir {search}; allow servicemanager fregd:process {getattr}; allow servicemanager fregd:file {read open};
创建一个fregd可执行文件,在init.rc里启动,会添加一个名为android.os.IFregDaemon的系统服务。
IFregDaemon.h
#ifndef IFREG_DAEMON_H_1 #define IFREG_DAEMON_H_1 #include <binder/IInterface.h> #include <binder/Parcel.h> namespace android { /* * Abstract base class f f69a or native implementation of FregService. * * Note: This must be kept manually in sync with IFregDaemon.aidl */ class IFregDaemon : public IInterface, public IBinder::DeathRecipient { public: enum { SET_VAL = IBinder::FIRST_CALL_TRANSACTION + 0, GET_VAL = IBinder::FIRST_CALL_TRANSACTION + 1, OPEN_HAL = IBinder::FIRST_CALL_TRANSACTION + 2, CLOSE_HAL = IBinder::FIRST_CALL_TRANSACTION + 3, INIT = IBinder::FIRST_CALL_TRANSACTION + 4, }; IFregDaemon() { } virtual ~IFregDaemon() { } virtual const android::String16& getInterfaceDescriptor() const; // Binder interface methods virtual void init() = 0; virtual int32_t getVal() = 0; virtual int32_t setVal(int32_t val) = 0; virtual int64_t openHal() = 0; virtual int32_t closeHal() = 0; // DECLARE_META_INTERFACE - C++ client interface not needed static const android::String16 descriptor; }; class BnFregDaemon: public BnInterface<IFregDaemon> { public: virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); }; } // namespace android #endif // IFREG_DAEMON_H_
IFregDaemon.cpp
#include <inttypes.h> #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> #include <binder/PermissionCache.h> #include <utils/String16.h> #include <utils/Looper.h> #include <hardware/hardware.h> #include <hardware/freg.h> #include "IFregDaemon.h" namespace android { const android::String16 IFregDaemon::descriptor("android.os.IFregDaemon"); const android::String16& IFregDaemon::getInterfaceDescriptor() const { return IFregDaemon::descriptor; } status_t BnFregDaemon::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { case SET_VAL: { CHECK_INTERFACE(IFregDaemon, data, reply); const int32_t val = data.readInt32(); const int32_t ret = setVal(val); reply->writeNoException(); reply->writeInt32(ret); return NO_ERROR; }; case GET_VAL: { CHECK_INTERFACE(IFregDaemon, data, reply); const int32_t ret = getVal(); reply->writeNoException(); reply->writeInt32(ret); return NO_ERROR; } case OPEN_HAL: { CHECK_INTERFACE(IFregDaemon, data, reply); const int64_t ret = openHal(); reply->writeNoException(); reply->writeInt64(ret); return NO_ERROR; } case CLOSE_HAL: { CHECK_INTERFACE(IFregDaemon, data, reply); const int32_t ret = closeHal(); reply->writeNoException(); reply->writeInt32(ret); return NO_ERROR; } case INIT: { CHECK_INTERFACE(IFregDaemon, data, reply); init(); reply->writeNoException(); return NO_ERROR; } default: return BBinder::onTransact(code, data, reply, flags); } }; }; // namespace android
FregDaemonProxy.h
#ifndef FREG_DAEMON_PROXY_H_ #define FREG_DAEMON_PROXY_H_ #include "IFregDaemon.h" namespace android { class FregDaemonProxy : public BnFregDaemon { public: static FregDaemonProxy* getInstance() { if (sInstance == NULL) { sInstance = new FregDaemonProxy(); } return sInstance; } // These reflect binder methods. virtual void init(); virtual int32_t getVal(); virtual int32_t setVal(int32_t val); virtual int64_t openHal(); virtual int32_t closeHal(); private: FregDaemonProxy(); virtual ~FregDaemonProxy(); static FregDaemonProxy* sInstance; freg_module_t const* mModule; freg_device_t* mDevice; void binderDied(const wp<IBinder>& who); }; } // namespace android #endif // FREG_DAEMON_PROXY_H_
FregDaemonProxy.cpp
#define LOG_TAG "fregd" #include <binder/IServiceManager.h> #include <hardware/hardware.h> #include <hardware/freg.h> #include <utils/Log.h> #include "FregDaemonProxy.h" namespace android { FregDaemonProxy* FregDaemonProxy::sInstance = NULL; FregDaemonProxy::FregDaemonProxy() : mModule(NULL), mDevice(NULL) {} FregDaemonProxy::~FregDaemonProxy() { closeHal(); } void FregDaemonProxy::init() {} int32_t FregDaemonProxy::getVal() { if(!mDevice) { ALOGE("Device freg is not open."); return 0; } int val = 0; mDevice->get_val(mDevice, &val); ALOGI("Get value %d from device freg.", val); return val; } int32_t FregDaemonProxy::setVal(int32_t value){ if(!mDevice) { ALOGE("Device freg is not open."); return -1; } int val = value; ALOGI("Set value %d to device freg.", val); mDevice->set_val(mDevice, val); return 0; } int64_t FregDaemonProxy::openHal() { const hw_module_t *hw_module = NULL; ALOGI("Initializing HAL stub freg......"); /*加载硬件抽象层模块freg*/ if(hw_get_module(FREG_HARDWARE_MODULE_ID, &hw_module) == 0) { ALOGI("Device freg found."); mModule = reinterpret_cast<const freg_module_t*>(hw_module); /*打开虚拟硬件设备freg*/ hw_device_t *device = NULL; if (mModule->common.methods->open(hw_module, FREG_HARDWARE_DEVICE_ID, &device) == 0) { ALOGI("Device freg is open."); mDevice = reinterpret_cast<freg_device_t*>(device); return reinterpret_cast<int64_t>(mDevice); } ALOGE("Failed to open device freg."); return 0; } ALOGE("Failed to get HAL stub freg."); return 0; } int32_t FregDaemonProxy::closeHal() { ALOG(LOG_VERBOSE, LOG_TAG, "nativeCloseHal()\n"); mDevice = NULL; return 0; } void FregDaemonProxy::binderDied(const wp<IBinder>& who) { ALOGD("binder died"); int err; if (0 != (err = closeHal())) { ALOGE("Can't close fingerprint device, error: %d", err); } if (who != NULL) {} } }
fregd.cpp
#define LOG_TAG "fregd" #include <cutils/log.h> #include <utils/Log.h> #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> #include <binder/PermissionCache.h> #include <utils/String16.h> #include <hardware/hardware.h> #include <hardware/freg.h> #include "FregDaemonProxy.h" int main() { ALOGI("Starting " LOG_TAG); android::sp<android::IServiceManager> serviceManager = android::defaultServiceManager(); android::sp<android::FregDaemonProxy> proxy = android::FregDaemonProxy::getInstance(); android::status_t ret = serviceManager->addService( android::FregDaemonProxy::descriptor, proxy); if (ret != android::OK) { ALOGE("Couldn't register " LOG_TAG " binder service!"); return -1; } /* * We're the only thread in existence, so we're just going to process * Binder transaction as a single-threaded program. */ android::IPCThreadState::self()->joinThreadPool(); ALOGI("Done"); return 0; }
Android.mk
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_CFLAGS := -Wall -Wextra -Werror -Wunused LOCAL_SRC_FILES := \ FregDaemonProxy.cpp \ IFregDaemon.cpp \ fregd.cpp LOCAL_MODULE := fregd LOCAL_SHARED_LIBRARIES := \ libbinder \ liblog \ libhardware \ libutils include $(BUILD_EXECUTABLE)
添加到init.rc里,debug.fregd属性用于debug时手动开启和停止服务
device/mediatek/mt6735/init.mt6735.rc service fregd /system/bin/fregd class main user system group system on property:debug.fregd=0 stop fregd on property:debug.fregd=1 start fregd
添加对应的framework接口,顺序必须与IFregDaemon.h里的枚举一致。
core/java/android/os/IFregDaemon.aidl
package android.os; /** * Communication channel from FregService to FregDaemon (fregd) * @hide */ interface IFregDaemon { int setVal(int val); int getVal(); long openHal(); int closeHal(); void init(); }
在FregService添加对应的方法
frameworks/base/services/java/com/android/server/FregService
private IFregDaemon mDaemon; private static final String FREGD = "android.os.IFregDaemon"; private IFregDaemon getFregDaemon() { if (mDaemon == null) { mDaemon = IFregDaemon.Stub.asInterface(ServiceManager.getService(FREGD)); if (mDaemon != null) { try { mHalDeviceId = mDaemon.openHal(); if (mHalDeviceId == 0) { Slog.w(TAG, "Failed to open Freg HAL!"); mDaemon = null; } } catch (RemoteException e) { Slog.e(TAG, "Failed to open fingeprintd HAL", e); mDaemon = null; // try again later! } } else { Slog.w(TAG, "Freg service not available"); } } return mDaemon; } public int getVal_fregd() { IFregDaemon daemon = getFregDaemon(); if (daemon == null) { Slog.w(TAG, "getVal_fregd: no fregd!"); return 0; } try { return daemon.getVal(); } catch (RemoteException e) { Slog.e(TAG, "getVal_fregd failed", e); } return 0; } public int setVal_fregd(int val){ IFregDaemon daemon = getFregDaemon(); if (daemon == null) { Slog.w(TAG, "setVal_fregd: no fregd!"); return 0; } try { return daemon.setVal(val); } catch (RemoteException e) { Slog.e(TAG, "setVal_fregd failed", e); } return 0; }
添加到编译系统里去
frameworks/base/Android.mk
LOCAL_SRC_FILES += \ core/java/android/os/IFregService.aidl \ core/java/android/os/IFregDaemon.aidl \
这样FregSevice就可以通过fregd去读写驱动了。
推荐文章
Binder系列8—如何使用Binder
相关文章推荐
- Android 添加系统服务
- Android 添加系统服务
- Android系统开发之一:添加系统级服务方法
- Android 添加系统服务
- [实践] Android5.1.1源码 - 在Framework中添加自定义系统服务
- 如何在Android中添加系统服务
- Android 5.0 添加系统服务后,启动的时候报安全错误
- 添加自定义android系统服务的方法
- 如何在Android中添加系统服务
- android上如何添加系统服务
- Android 添加系统串口服务步骤
- Android 添加系统服务
- Android 添加系统服务
- Android 添加系统服务
- Android 添加系统服务
- 【转】Android 添加系统服务
- android添加系统服务
- Android 添加系统服务
- 如何在Android中添加系统服务
- [实践] Android5.1.1源码 - 在Framework中添加自定义系统服务