一、Android系统中具有两层服务:
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的内容如下:
#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
注意在DemoService::instantiate()中调用 defaultServiceManager()->addService(String16("demo.service"), new DemoService()),将名字为"demo.service"的服务注册到ServiceManager中。ServiceManager根据名字返回给客户端相应的服务,如果找不到该名字对应的服务,则返回空。
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的内容如下:
#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();
}
以上为底层服务的标准操作。关键是调用DemoService::instantiate()把DemoService服务注册到ServiceManager中。
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。我们来看一下这个文件的内容隐藏着什么奥秘,可以这么神奇地支持进程间通信。
/*
* 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;
……
}
我们可以看到IDemoManager.aidl这个文件编译后的真面目,原来就是根据IDemoManager接口的定义生成相应的Stub和Proxy类,这个就是我们熟悉的Binder机制的内容了,即实现这个DemoManagerService的server必须继承于这里的IDemoManager.Stub类,而这个DemoManagerService的远程接口就是这里的IDemoManager.Stub.Proxy对象获得的IDemoManager接口。接下来的内容,我们就可以看到IDemoManager.Stub和IDemoManager.Stub.Proxy是怎么创建或者使用的。
(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();
……