受疫情影响,自己工作目前又比较忙,很长时间没有更细博客了,最近看了一下底层服务,尝试着添加了一个底层服务,之前写过一个文章是 Android在java层添加服务进行通讯,对Java层服务感兴趣的同学可以去看一下
Android 7.1 添加一个进程间通讯的系统服务(java层)
本次添加一个底层服务,目的是为了应用程序可以获取此服务 与 底层服务和外部设备进行通讯 .
分为大概几个步骤
1.添加文件
2.编译文件
3.将文件打到ROM中
4.添加sepolicy权限
5.测试权限
一:添加文件
本次涉及的文件如下图所示:
frameworks/base$ tree customcamera 显示文件夹结构
customcamera
├── customcamera //编写可执行文件
│ ├── Android.mk
│ └── customcamera.cpp
└── libcustomcamera //服务的具体实现类
├── CustomCamera.cpp
└── CustomCamera.h
2 directories, 4 files
1.创建文件夹 customcamera 以及两个子文件夹 customcamera 和 libcustomcamera
首先在 libcustomcamera文件夹下创建 CustomCamera.cpp 和 CustomCamera.h 因为是简单的Demo 代码写的比较简单.
-----CustomCamera.h 内容如下:
#ifndef ANDROID_GUILH_ADD_SERVICE_H
#define ANDROID_GUILH_ADD_SERVICE_H
#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <utils/threads.h>
namespace android {
class CustomCamera: public BBinder{// 从 BBinder 派生,实现本地接口
public:
static int instantiate();
CustomCamera();
virtual ~CustomCamera();
virtual status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t);
};
}; //namespace
#endif
------CustomCamera.cpp
#include "CustomCamera.h"
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
namespace android {
static struct sigaction oldact;
static pthread_key_t sigbuskey;
// 把自己注册到系统中
int CustomCamera::instantiate() {
ALOGW("CustomCamera instantiate");
int r = defaultServiceManager()->addService(
String16("custom_camera"), new CustomCamera());//服务添加到 Binder Driver 中服务名为 custom_camera
ALOGW("CustomCamera r = %d/n", r);
return r;
}
// 构造函数
CustomCamera::CustomCamera()
{
ALOGW("CustomCamera created");
pthread_key_create(&sigbuskey, NULL);
}
// 析构函数
CustomCamera::~CustomCamera()
{
pthread_key_delete(sigbuskey);
ALOGW("CustomCamera destroyed");
}
// 这个是服务具体的本地实现,功能实现都应该放在这里面,通过传入执行代码( code ) // 的不同来执行不同的操作,上层隐射为不同的 api 。
status_t CustomCamera::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){
switch(code) {
case 0: {// 根据 code 的不同执行不同的操作
pid_t pid = data.readInt32();
int num = data.readInt32();
num = num + 1000;
reply->writeInt32(num);
return NO_ERROR;
}
break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}};
//namespace
到这一步可以先在libcustomcamera本文件夹下建立一个makefile文件 测试当前写的CustomCamera.cpp 是否正确,当然也可以后期测试,这里就进行后期测试.
之后在customcamera 文件夹下创建 customcamera.cpp 和 Android.mk 文件.
------customcamera.cpp内容如下
#include <sys/types.h>
#include <unistd.h>
#include <grp.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>
#include <private/android_filesystem_config.h>
#include "../libcustomcamera/CustomCamera.h"
using namespace android;
int main(int argc, char** argv)
{
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();//取得 ServiceManager
ALOGW("CustomCamera ServiceManager: %p", sm.get());
CustomCamera::instantiate();//把自己添加到 ServiceManager中
ProcessState::self()->startThreadPool();//启动缓冲池
IPCThreadState::self()->joinThreadPool();//这里是把服务添加到 Binder闭合循环进程中
}
------Android.mk 内容
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := ../libcustomcamera/CustomCamera.cpp \
customcamera.cpp \
LOCAL_CFLAGS := -D__STDC_CONSTANT_MACROS -Wl,-Map=test.map -g -Wno-unused-parameter -Wno-unused-variable
LOCAL_CONLYFLAGS := -std=c11
LOCAL_SHARED_LIBRARIES := libcutils \
libsysutils \
libutils \
libbinder \
libui \
libgui \
liblog
LOCAL_LDLIBS := -llog
LOCAL_MODULE := custom_camera
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES += $(LOCAL_PATH)
#编译为可执行文件
include $(BUILD_EXECUTABLE)
到此文件编写完毕.
二.编译文件
之后返回到源码根目录 执行如下
~:source build/envsetup.sh
~:lunch XX<需要编译的目标版本>
然后回到 frameworks/base/customcamera/customcamera 文件夹 执行 mm 命令,进行单模块编译.
此时应该会看到如下图所示内容: successfully 编译成功 (因为代码简单也就五六秒钟)
然后到上图对应的目录下去查找可以看到 :custom_camera 已经在存在了 (红色框内)
三. 打到ROM 中
1.因为我们是在framework/base下面创建的文件Android.mk 系统全编译的时候会自动拷贝到 out目录下的 system/bin下
这样打ROM的时候会把编译好的 custom_camera 带到系统ROM里面.
2.如果我们是在外部提前编译好的 custom_camera 将custom_camera放到某一个文件夹下, 在系统的对应的mk中添加拷贝代码.
比如我的是高通的代码 添加 路径为 device/qcom/msmxxx/msmxxx.mk文件,在文件中增加拷贝custom_camera代码如下:
PRODUCT_COPY_FILES += \
<自己存放custom_camera的路径>/custom_camera:system/bin/custom_camera
例如如下面的代码就是拷贝custom_camera 到system/文件夹下
PRODUCT_COPY_FILES += \
out/target/product/msm8953_64/system/bin/custom_camera:system/bin/custom_camera
这句话的意思就是标示 如果编译系统的时候 将这个文件 拷贝到 out/target/product/msmxxxx/system/bin/custom_camera
四.启动服务
添加启动服务的代码 文件路径为 device/qcom/msmXXX/init.target.rc 其它平台的可能是其它的 .rc 但是逻辑是一样的
先修改权限
#修改权限 增加的代码
chmod 0777 /system/bin/custom_camera
#系统代码不必关注
chmod 0660 /sys/devices/soc.0/78b7000.i2c/i2c-3/3-0020/input/input0/secure_touch_enable
增加开机启动服务
#启动我们的服务,开机启动
service custom_camera /system/bin/custom_camera
class core
user root
group root
oneshot
五.测试服务
//在应用程序中测试服务的代码:
private void test(){
try{
IBinder binder = ServiceManager.getService("custom_camera");// 取得服务
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
if(binder == null)
Log.d(TAG,"failed to get custom_camera");
data.writeInt(Process.myPid());// 固定操作
data.writeInt(100);// 传入参数
binder.transact(0, data, reply, 0);// 执行远程调用
Log.d(TAG," custom_camer aresult="+reply.readInt());// 验证结果
}catch(Exception e){
Log.d(TAG,e.toString());
}
六.添加selinux权限
Android 7.1 添加一个进程间通讯的系统服务(java层) 文章的后半部分有介绍,这里就不再过多赘述
主要涉及如下几个文件
#主要是修改 neverallow 内容
#-mcu_service
system/sepolicy/domain.te
#/system/bin/custom_camera u:object_r:custom_camera_service_exec:s0
system/sepolicy/file_contexts
# custom_camera u:custom_camera_service_exec:s0
system/sepolicy/custom_camera.te # 拷贝别的te修改名字就行
# custom_camera u:object_r:custom_camera_service_service:s0
system/sepolicy/service_contexts # 与 file_contexts 相对应