1. C++层的核心服务(Core Service)
2. Java层的系统服务(SDK-based Service)
核心服务(Core Service)是Android框架里最接近内核的部分,通常运行在独立的进程(Process)里,使用C++实现,是让上层Java应用程序使用驱动和硬件设备的重要管道。在开机过程中,就可以启动核心服务,让众多应用程序来共同使用。
Java层服务顾名思义即为从 Java层提供的服务,它与 C++层的服务不同之处在于其服务进程的运行由 ServiceManager统一维护。
以MediaPlayerService为例,两种服务的关系如下图:
二、下面分别总结一下如何在Android系统中添加核心服务和Java层服务
1. 添加C++层的核心服务(Core Service)
假设要添加一个服务DemoService
(1)创建相关的目录
进入android源码的frameworks/base目录,新建自己的目录,假设为demoService,再在这个目录中建立两个子目录demoServer和libDemoService
demoServer目录存放服务的启动程序文件,编译后将生成为可执行文件,在系统启动的时候运行
libDemoService目录存放服务的实现文件,编译后将生成为动态链接库,由可执行程序调用
(2)编写服务的实现文件
进入libDemoService目录,创建三个文件:DemoService.h、DemoService.cpp和Android.mk
DemoService.h的内容如下:
#ifndef ANDROID_DEMOSERVICE_H #define ANDROID_DEMOSERVICE_H #include <utils/threads.h> #include <utils/RefBase.h> #include <utils/Log.h> #include <binder/IInterface.h> #include <binder/Parcel.h> namespace android { class DemoService : public BBinder {//继承BBinder,实现本地接口 public: static void instantiate(); DemoService(); virtual ~DemoService(); virtual status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t); }; };//namespace #endif
DemoService.cpp的内容如下:
注意在DemoService::instantiate()中调用 defaultServiceManager()->addService(String16("demo.service"), new DemoService()),将名字为"demo.service"的服务注册到ServiceManager中。ServiceManager根据名字返回给客户端相应的服务,如果找不到该名字对应的服务,则返回空。#include <binder/IServiceManager.h> #include <binder/IPCThreadState.h> #include "DemoService.h" namespace android { //把自己注册到ServiceManager中 void DemoService::instantiate() { defaultServiceManager()->addService( String16("demo.service"), new DemoService()); } DemoService::DemoService() { ALOGV("DemoService created"); } DemoService::~DemoService() { ALOGV("DemoService destroyed"); } //服务具体的本地实现,功能实现都应该放在这里面,通过传入执行代码(code)的不同来执行不同的操作,上层映射为不同的API。 status_t DemoService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { case XX: {//根据code的不同执行不同的操作 xxxxxxx } break; case YY: { yyyyyyy } break; default: return BBinder::onTransact(code, data, reply, flags); } } };//namespace
Android.mk的内容如下:
LOCAL_PATH:= $(call my-dir) # # libDemoService # include $(CLEAR_VARS) LOCAL_SRC_FILES := \ DemoService.cpp \ $(JNI_H_INCLUDE) LOCAL_SHARED_LIBRARIES := \ libcutils \ libutils \ libbinder \ libandroid_runtime \ LOCAL_PRELINK_MODULE := false LOCAL_MODULE := libDemo include $(BUILD_SHARED_LIBRARY) # 表示编译为动态库
编译:mmm frameworks/base/demoService/libDemoService/,生成libDemo.so库文件
(3)编写可执行程序文件
进入demoServer目录,创建两个文件:DemoServer.cpp和Android.mk
DemoServer.cpp的内容如下:
以上为底层服务的标准操作。关键是调用DemoService::instantiate()把DemoService服务注册到ServiceManager中。#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 "../libDemoService/DemoService.h" using namespace android; int main(int argc, char** argv) { sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm = defaultServiceManager();//获取ServiceManager的代理接口 ALOGI("ServiceManager: %p", sm.get()); DemoService::instantiate();//把自己添加到ServiceManager中 ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); }
Android.mk的内容如下:
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := \ DemoServer.cpp \ LOCAL_SHARED_LIBRARIES := \ libDemo \ libutils \ libbinder \ LOCAL_MODULE:= DemoServer include $(BUILD_EXECUTABLE) # 编译为可执行文件
编译:mmm frameworks/base/demoService/demoServer/,生成可执行文件DemoServer.
(4)实现服务进程开机自动运行
将编译生成的可执行文件DemoServer和动态链接库文件libDemo.so分别拷贝到开发板的/system/bin和system/lib目录(模拟器上相当于make snod)
修改启动脚本<android source>/system/core/rootdir/init.rc文件,使之在开机时启动服务DemoServer
## 将/system/bin/DemoServer作为一个服务启动,服务的名称为DemoService(这个名称只是为了方便自己识别而已) service DemoService /system/bin/DemoServer
2.添加Java层的系统服务(SDK-based Service)
(1)定义服务的接口
Binder机制要求提供服务的一方必须实现一个具有跨进程访问能力的接口,以便使用服务的一方可以通过这个服务接口来访问它,因此,在实现服务之前,我们首先要定义它的服务接口。Android系统提供了一种描述语言来定义具有跨进程访问能力的服务接口,这种描述语言称为Android接口描述语言(Android Interface Definition Language,AIDL)。以AIDL定义的服务接口文件是以aidl为后缀名的,在编译时,编译系统会将它们转换成一个java文件,然后再对它们进行编译。
在目录/frameworks/base/core/java/android/app下增加IDemoManager.aidl
package android.app; interface IDemoManager { …… void setVolume(int iValue); int getVolume(); …… }
注意,这是一个aidl文件,编译后会生成一个IDemoManager.java。我们来看一下这个文件的内容隐藏着什么奥秘,可以这么神奇地支持进程间通信。
我们可以看到IDemoManager.aidl这个文件编译后的真面目,原来就是根据IDemoManager接口的定义生成相应的Stub和Proxy类,这个就是我们熟悉的Binder机制的内容了,即实现这个DemoManagerService的server必须继承于这里的IDemoManager.Stub类,而这个DemoManagerService的远程接口就是这里的IDemoManager.Stub.Proxy对象获得的IDemoManager接口。接下来的内容,我们就可以看到IDemoManager.Stub和IDemoManager.Stub.Proxy是怎么创建或者使用的。/* * This file is auto-generated. DO NOT MODIFY. * Original file: frameworks/base/core/java/android/app/IDemoManager.aidl */ package android.app; public interface IDemoManager extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements android.app.IDemoManager { private static final java.lang.String DESCRIPTOR = "android.app.IDemoManager"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an android.app.IDemoManager interface, * generating a proxy if needed. */ public static android.app.IDemoManager asInterface(android.os.IBinder obj) { if ((obj==null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin!=null)&&(iin instanceof android.app.IDemoManager))) { return ((android.app.IDemoManager)iin); } return new android.app.IDemoManager.Stub.Proxy(obj); } @Override public android.os.IBinder asBinder() { return this; } @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { switch (code) { …… case TRANSACTION_setVolume: { data.enforceInterface(DESCRIPTOR); int _arg0; _arg0 = data.readInt(); this.setVolume(_arg0); reply.writeNoException(); return true; } case TRANSACTION_getVolume: { data.enforceInterface(DESCRIPTOR); int _result = this.getVolume(); reply.writeNoException(); reply.writeInt(_result); return true; } …… } return super.onTransact(code, data, reply, flags); } private static class Proxy implements android.app.IDemoManager { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } @Override public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } …… @Override public void setVolume(int iValue) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeInt(iValue); mRemote.transact(Stub.TRANSACTION_setVolume, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } @Override public int getVolume() throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); int _result; try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_getVolume, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); } finally { _reply.recycle(); _data.recycle(); } return _result; } …… } …… static final int TRANSACTION_setVolume = (android.os.IBinder.FIRST_CALL_TRANSACTION + 331); static final int TRANSACTION_getVolume = (android.os.IBinder.FIRST_CALL_TRANSACTION + 367); …… } …… public void setVolume(int iValue) throws android.os.RemoteException; public int getVolume() throws android.os.RemoteException; …… }
(2)在目录frameworks/base/services/java/com/android/server中增加服务类DemoManagerService,继承IDemoManager.Stub,并实现其中的函数
package com.android.server; import android.app.IDemoManager; import android.app.DemoManager; import android.content.Context; import android.util.Log; import android.util.Slog; …… public abstract class DemoManagerService extends IDemoManager.Stub { private static final String TAG = "DemoManagerService"; protected final Context mContext; …… public DemoManagerService(Context context) { mContext = context; Slog.w(TAG, "DemoManagerService is constructed!"); } protected void finalize() throws Throwable { try { } finally { close(); super.finalize(); } } …… public void setVolume(int iValue){ Slog.v(TAG, "SetVolume"); pushInteger(iValue); invoke("SetVolume"); } public int getVolume(){ boolean result; Slog.v(TAG, "GetVolume"); result = invoke("GetVolume"); if(result == true){ return getInteger(); } return 0; } …… }
(3)启动服务
在frameworks/base/services/java/com/android/server/SystemServer.java文件中,定义了SystemServer类。SystemServer对象是在系统启动的时候创建的,它被创建的时候会启动一个线程来创建系统中的服务,并且把它们添加到Service Manager中去,所以,这里将DemoManagerService也加入其中
…… import com.android.server.DemoManagerService; import com.android.server.DemoManagerServicePolicy; class ServerThread { …… public void initAndLoop() { …… DemoManagerService demo = null; …… Slog.i(TAG, "demo Manager"); demo = new DemoManagerServicePolicy(context); ServiceManager.addService(Context.DEMO_SERVICE, demo); ActivityManagerService.self().setDemoManager(demo); …… final DemoManagerService demoF = demo; …… try { if (demoF != null) demoF.systemReady(); } catch (Throwable e) { reportWtf("Notifying DemoManagerService running", e); } …… } …… } public class SystemServer { …… /** * Called to initialize native system services. */ private static native void nativeInit(); public static void main(String[] args) { …… // Initialize native services. nativeInit(); // This used to be its own separate thread, but now it is // just the loop we run on the main thread. ServerThread thr = new ServerThread(); thr.initAndLoop(); } }
我们可以看到,在ServerThread.initAndLoop函数中,创建了DemoManagerService并添加到Service Manager中。
(4)在/frameworks/base/core/java/android/content/Context.java中增加表示服务名称的字符串常量
public static final String DEMO_SERVICE = "demo";
(5)在/frameworks/base/core/java/android/app中增加DemoManager.java
package android.app; …… public class DemoManager { …… private final IDemoManager mService; /** * package private on purpose */ DemoManager(IDemoManager service) { mService = service; } …… public void setVolume(int iValue){ try{ mService.setVolume(iValue); }catch(RemoteException ex){ } } public int getVolume(){ try{ return mService.getVolume(); }catch(RemoteException ex){ } return 0; } …… }
(6)在/frameworks/base/core/java/android/app/ContextImpl.java文件的ContextImpl类的静态块中增加
package android.app; …… class ReceiverRestrictedContext extends ContextWrapper { …… } /** * Common implementation of Context API, which provides the base * context object for Activity and other application components. */ class ContextImpl extends Context { …… static { …… registerService(DEMO_SERVICE, new StaticServiceFetcher() { public Object createStaticService() { IBinder b = ServiceManager.getService(DEMO_SERVICE); IDemoManager service = IDemoManager.Stub.asInterface(b); return new DemoManager(service); }}); …… } …… }
(7)在/frameworks/base/Android.mk中
下增加LOCAL_SRC_FILES += \
core/java/android/app/IDemoManager.aidl \
(8)这样,重新编译出SDK,然后基于此SDK开发应用程序就可以使用刚刚增加的服务了。
比如,在应用程序中:
import android.app.DemoManager; …… DemoManager tm = (DemoManager) getSystemService(DEMO_SERVICE); tm.getVolume(); ……