Android添加底层核心服务

1. 为什么要写底层核心服务呢?

因为底层核心服务是 Android框架里最接近 Linux/Driver的部分。为了充分发挥硬件设备的差异化特性,核心服务是让上层 Java应用程序来使用 Driver/HW Device 特色的重要管道。例如 Media Telephone等底层硬件。

在开机过程中,就可以启动核心服务(汉字输入法服务等),让众多应用程序来共同使用。

由于共用,所以能有效降低 Java应用程序的大小( Size)。

2. 核心服务与 Java 层的 Service有何区别和关系?

Android具有两层服务

--Java SDK-based Service

--C++层的 Code Service



3. 编写自己的核心服务( C++ 层)

1). 要点

核心服务通常在独立的进程( Process )里执行。

必须提供 IBinder 接口,让应用程序可以进行跨进程的绑定( Binding )和调用。

因为共用,所以必须确保多线程安全( Thread-safe )。

使用 C++ 来实现,并调用 IServiceManager::addService() 函数添加到系统的 Binder Driver 里。

上层应用程序通过 ServiceManager 获取该服务。

上层应用程序通过 IBinder::transact() 函数来与核心服进行数据交互。

2). 添加服务

下面详细介绍如何添加一个底层服务到系统中,假设服务名为 AddService ,其用途是对传入的参数加上 1000 ,并返回结果。

服务实现

进入 android 源码 的目录 frameworks/base ,在该目录下建立自己的目录,假设为 addservice ,再在这个目录中建立两个子目录 addserver libaddservice addserver 用于存放服务的启动文件,其最终的生成为可执行文件,在系统启动的时候运行, libaddservice 用于存放服务的实现文件,最终会生成动态链接库,有 addserver 调用。

首先,服务的实现文件包括两个文件, AddService.h AddService.cpp

以下是 AddService.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 AddService : public BBinder{// BBinder 派生,实现本地接口

public:

static int instantiate();

AddService();

virtual ~AddService();

virtual status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t);

};

}; //namespace

#endif

然后是服务的实现文件 AddService.cpp

#include "AddService.h"

#include <binder/IServiceManager.h>

#include <binder/IPCThreadState.h>

namespace android {

static struct sigaction oldact;

static pthread_key_t sigbuskey;

// 把自己注册到系统中

int AddService::instantiate() {

LOGE("AddService instantiate");

int r = defaultServiceManager()->addService(

String16("guilh.add"), new AddService());// 这里主要是把 //AddSerice 这个服务添加到 Binder Driver 中服务名为 guilh.add

LOGE("AddService r = %d/n", r);

return r;

}

// 构造函数

AddService::AddService()

{

LOGV("AddService created");

mNextConnId = 1;

pthread_key_create(&sigbuskey, NULL);

}

// 析构函数

AddService::~AddService()

{

pthread_key_delete(sigbuskey);

LOGV("AddService destroyed");

}

// 这个是服务具体的本地实现,功能实现都应该放在这里面,通过传入执行代码( code // 的不同来执行不同的操作,上层隐射为不同的 api

status_t AddService::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

以下是编译服务的 Android.mk ,和上面的 cpp 放在一起。

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= /

AddService.cpp

LOCAL_C_INCLUDES := /

$(JNI_H_INCLUDE)

LOCAL_SHARED_LIBRARIES := /

libcutils /

libutils /

libbinder /

libandroid_runtime

LOCAL_PRELINK_MODULE := false

LOCAL_MODULE := libAdd

include $(BUILD_SHARED_LIBRARY) #这一行表示编译为动态库

在命令行中退出到 android/目录级 加载编译环境 . build/envsetup.sh

然后 lunch

然后在 cd /android/frameworks/base/addservice/ libaddservice/ 目录 输入 mm

之后在 out 目录产出 libAdd.so 文件。

在此 完成核心服务第一步。

服务进程实现

进入到 cd /android/frameworks/base/addservice/addserver/ 目录

增加一个文件 addserver.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 "../libaddservice/AddService.h"

//#include <libadd/AddService.h>

using namespace android;

int main(int argc, char** argv)

{

sp<ProcessState> proc(ProcessState::self());

sp<IServiceManager> sm = defaultServiceManager();//取得 ServiceManager

LOGI("ServiceManager: %p", sm.get());

AddService::instantiate();//把自己添加到 ServiceManager

ProcessState::self()->startThreadPool();//启动缓冲池

IPCThreadState::self()->joinThreadPool();//这里是把服务添加到 Binder闭合循环进程中

}

以上为底层服务的标准操作。

下面是这个服务 makefile

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= /

addserver.cpp

LOCAL_SHARED_LIBRARIES := /

libAdd /

libutils /

libbinder

LOCAL_MODULE:= addserver

include $(BUILD_EXECUTABLE)//编译为可执行文件

退出后当前目录执行 mm即可在 out目录的 system/bin下产出 addserver可执行文件。

实现服务进程开机自动运行

进入到 /android/system/core/rootdir/目录中有个 init.rc文件

vi init.rc

service中添加

service addservice /system/bin/addserver // /system/bin/addserver作为一个服务启动,服务的名称为 addservice(这个不重要)。

最后退出到 android/目录下执行全编译:

输入 . build/envsetup.sh

Lunch

Make

完成之后

Emulator打开模拟器

打开另一个 shell终端 输入 adb shell 进入模拟器模式 如果 adbshell系统提示没有发现该命令 就在 android/out/host/linux-x86/bin/中输入 ./adb shell

在输入 ps 查看进程 找到是否有 addserver进程

如果有就成功一半。

测试我们的服务

随便在 android/packages/apps 建立一个简单的应用程序,

这里可以直接在 eclipse 中建立好工程 拷贝到 android/packages/apps 中,然后为应用添加一个 Android.mk 文件,可以从其他应用中拷贝来修改。

在应用程序中测试服务的代码:

private void test(){

try{

IBinder binder = ServiceManager.getService("guilh.add");// 取得服务

Parcel data = Parcel.obtain();

Parcel reply = Parcel.obtain();

if(binder == null)

Log.d(TAG,"failed to get service");

data.writeInt(Process.myPid());// 固定操作

data.writeInt(100);// 传入参数

binder.transact(0, data, reply, 0);// 执行远程调用

Log.d(TAG,"result="+reply.readInt());// 验证结果

}catch(Exception e){

Log.d(TAG,e.toString());

}

(以上部分资料来源于高焕堂 android 核心服务,欢迎提出您的意见及建议)

更多相关文章

  1. 一款常用的 Squid 日志分析工具
  2. GitHub 标星 8K+!一款开源替代 ls 的工具你值得拥有!
  3. RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
  4. Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
  5. 【Android】_音乐列表_仿网易云音乐播放器2(读取本地mp3)
  6. 在BeagleBoard XM 开发板上运行Android
  7. Android将应用程序指定默认语言
  8. Android(安卓)APK反编译方法(可以获取APK xml和android Manifest,j
  9. 关于Android(安卓)studio的报错无法download某些文件的解决方法

随机推荐

  1. Android简单的利用MediaRecorder进行录音
  2. Android(安卓)Activity生命周期浅谈
  3. android 状态栏(StatusBar)
  4. android 读取本地图片生成 bitmap
  5. Android(安卓)自定义感光器控件SolarProg
  6. Android访问资源
  7. Android(安卓)studio 3.1.2 开发环境搭建
  8. Android(安卓)字体设置-Typeface讲解
  9. AS Gradle构建工具与Android(安卓)plugin
  10. GitHub上优秀Android(安卓)UI Library