如何在Android中添加系统服务

如何在Android中添加系统服务,第1张

在android中添加系统服务,下面以SurfaceComposer这个service为例,

① 首先提供接口文件ISurfaceComposer.h

//frameworks\native\include\gui\ISurfaceComposer.h

//首先是接口,c++实现是虚函数

class ISurfaceComposer: public IInterface {

public:

DECLARE_META_INTERFACE(SurfaceComposer)

// flags for setTransactionState()

enum {

eSynchronous = 0x01,

eAnimation = 0x02,

}

enum {

eDisplayIdMain = 0,

}

/* create connection with surface flinger, requires

* ACCESS_SURFACE_FLINGER permission

*/

virtual sp<ISurfaceComposerClient>createConnection() = 0

}

② 建立BnSurfaceComposer

建立BnSurfaceComposer,需要重写BBinder的onTransact函数。

class BnSurfaceComposer: public BnInterface<ISurfaceComposer>{

public:

enum {

// Note: BOOT_FINISHED must remain this value, it is called from

// Java by ActivityManagerService.

BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,

CREATE_CONNECTION,

CREATE_GRAPHIC_BUFFER_ALLOC,

CREATE_DISPLAY_EVENT_CONNECTION,

CREATE_DISPLAY,

DESTROY_DISPLAY,

GET_BUILT_IN_DISPLAY,

SET_TRANSACTION_STATE,

AUTHENTICATE_SURFACE,

BLANK,

UNBLANK,

GET_DISPLAY_INFO,

CONNECT_DISPLAY,

CAPTURE_SCREEN,

}

virtual status_t onTransact(uint32_t code, const Parcel&data,

Parcel* reply, uint32_t flags = 0)

}

③ Bpxxx的实现

frameworks\native\libs\gui\ISurfaceComposer.cpp中,

//Bp实现,代理端

class BpSurfaceComposer : public BpInterface<ISurfaceComposer>

{

public:

BpSurfaceComposer(const sp<IBinder>&impl)

: BpInterface<ISurfaceComposer>(impl)

{

}

//代理接口

virtual sp<ISurfaceComposerClient>createConnection()

{

uint32_t n

Parcel data, reply

data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor())

remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, &reply)

return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder())

}

}

④ Bnxxx的实现

//Bn端,即server端

status_t BnSurfaceComposer::onTransact(

uint32_t code, const Parcel&data, Parcel* reply, uint32_t flags)

{

switch(code) {

case CREATE_CONNECTION: {

CHECK_INTERFACE(ISurfaceComposer, data, reply)

//createConnection就是server端的实现函数

sp<IBinder>b = createConnection()->asBinder()

reply->writeStrongBinder(b)

return NO_ERROR

}

default: {

return BBinder::onTransact(code, data, reply, flags)

}

}

// should be unreachable

return NO_ERROR

}

⑤ 注册service

通过上面几步已经完成了service的建立,我们需要将service注册到service manager中。

class SurfaceFlinger : public BnSurfaceComposer,

//在frameworks\native\services\surfaceflinger\main_surfaceflinger.cpp中,

// publish surface flinger

sp<IServiceManager>sm(defaultServiceManager())

sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false)

⑥ 使用service

//首先获取代理端BpSurfaceComposer

sp<ISurfaceComposer>composer(ComposerService::getComposerService())

//直接调用代理BpSurfaceComposer的接口

sp<IGraphicBufferAlloc>alloc(composer->createGraphicBufferAlloc())

其中getComposerService()的实现为,

/*static*/ sp<ISurfaceComposer>ComposerService::getComposerService() {

ComposerService&instance = ComposerService::getInstance()

Mutex::Autolock _l(instance.mLock)

if (instance.mComposerService == NULL) {

ComposerService::getInstance().connectLocked()

assert(instance.mComposerService != NULL)

ALOGD("ComposerService reconnected")

}

return instance.mComposerService

}

void ComposerService::connectLocked() {

const String16 name("SurfaceFlinger")

//获取service,返回的mComposerService是BpSurfaceComposer,有了Bp就能直接调用代理接口了

while (getService(name, &mComposerService) != NO_ERROR) {

usleep(250000)

}

assert(mComposerService != NULL)

// Create the death listener.

class DeathObserver : public IBinder::DeathRecipient {

ComposerService&mComposerService

virtual void binderDied(const wp<IBinder>&who) {

ALOGW("ComposerService remote (surfaceflinger) died [%p]",

who.unsafe_get())

mComposerService.composerServiceDied()

}

public:

DeathObserver(ComposerService&mgr) : mComposerService(mgr) { }

}

mDeathObserver = new DeathObserver(*const_cast<ComposerService*>(this))

mComposerService->asBinder()->linkToDeath(mDeathObserver)

}

java添加service

Android为了方便开发人员,提供了AIDL工具,简化了编写service的难度。下面以添加TestService这个服务为例,

① 编写AIDL文件

package android.app

interface ITestService {

boolean enableWifi(boolean enabled)

}

TestService的AIDL文件提供了一个接口,enableWifi()。

② 创建TestService服务

TestService 服务需要继承ITestService.Stub类,这个类就是通过AIDL工具对①中的AIDL文件处理后产生的,

class TestService extends ITestService.Stub {

//实现接口

public boolean enableWifi(boolean enabled)

{

......

}

}

③ Context.java中添加service名字字符串

// Context.java中添加service名字字符串

public static final String TEST_SERVICE = "my_test"

④ 向ServiceManager中注册service

java中大部分的系统service都是在SystemServer中去向service manager注册的,

//ServiceManager注册service

// 在SystemServer.java中,模仿其他向ServiceManager添加service的方法

try {

TestService myService = new TestService(context)

ServiceManager.addService(Context.TEST_SERVICE, myService)

} catch (Throwable e) {

reportWtf("register my test service fail", e)

}

⑤创建服务对应的Manager

对于每一个service而言,通常会有一个相关的Manager。 Managers提供API给app使用,成为SDK的一部分,是apps和remote service的中间桥梁。Manager中的接口和Service中的接口必须一一对应。

public class TestServiceManager{

private final ITestService mService

private final Context mContext

//构造函数中传入的service,其实就是BpTestService

TestServiceManager(Context context,ITestService service) {

mContext = context

mService = service

}

public boolean enableWifi(boolean enabled) {

try {

return mService.enableWifi(enabled)

} catch (RemoteException ex) {

}

return false

}

}

到目前为止,我们只是完成了Service的注册,但是还没有使用,该如何使用?

⑥ contextImpl中注册Manager

一旦我们实现了service和对应的Manager,需要有一种方法在app中调用他们。前面说过,Manager会成为SDK的一部分,供我们调用,那么Manager和Service是如何联系起来的?首先需要将我们的service和mangager注册到execution context,即contextImpl中,

registerService(TEST_SERVICE, new ServiceFetcher() {

public Object createService(ContextImpl ctx) {

IBinder b = ServiceManager.getService(TEST_SERVICE)

//asInterface(BpBinder)后就是BpTestService

ITestService service = ITestService.Stub.asInterface(b)

//创建TestServiceManager,第二个参数为BpBpTestService

return new TestServiceManager(ctx.getOuterContext(), service)

}})

registerService的第二个参数是一个ServiceFetcher对象,这里直接在调用时,新建了一个ServiceFetcher类,重写了createService方法。

ContextImpl.java中的registerService()方法,其核心就是把servicename和ServiceFetcher对象放到一个Hash的键值对中。

private static void registerService(String serviceName, ServiceFetcher fetcher) {

if (!(fetcher instanceof StaticServiceFetcher)) {

fetcher.mContextCacheIndex = sNextPerContextServiceCacheIndex++

}

SYSTEM_SERVICE_MAP.put(serviceName, fetcher)

}

⑦ app如何使用service

那么app是如何调用的呢?

import android.app.TestServiceManager

import android.content.Context

TestServiceManager mTestServiceManager

mTestServiceManager=(TestServiceManager)context.getSystemService(Context.TEST_SERVICE)

然后直接调用TestServiceManager中的方法即可,其中的奥秘需要分析下getSystemService函数。

ContextImpl.java中,

@Override

public Object getSystemService(String name) {

ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name)

//从ServiceFetcher 中获取service

return fetcher == null ? null : fetcher.getService(this)

}

getService()函数的核心就是上面重写的createService()函数,返回的就是TestServiceManager对象,所以通过context.getSystemService返回的是Manager对象。

public Object getService(ContextImpl ctx) {

ArrayList<Object>cache = ctx.mServiceCache

Object service

synchronized (cache) {

if (cache.size() == 0) {

// Initialize the cache vector on first access.

// At this point sNextPerContextServiceCacheIndex

// is the number of potential services that are

// cached per-Context.

for (int i = 0i <sNextPerContextServiceCacheIndexi++) {

cache.add(null)

}

} else {

service = cache.get(mContextCacheIndex)

if (service != null) {

return service

}

}

//调用重载的createService函数,返回的就是TestServiceManager对象

service = createService(ctx)

cache.set(mContextCacheIndex, service)

return service

}

}

1、 撰写一个aidl文件,定义服务的接口,将在编译过程中通过aidl工具生成对应的java接口。一般系统服务的aidl文件都放在framework\base\core\java\android\os目录中。

以我所写的IMyTool.aidl为例。在.aidl中定义自己需要加入的方法,编写规则和java接口差不多,这里不多说。

2、 将aidl文件名添加到frameworks\base\目录下的Android.mk编译脚本文件中。

如:

LOCAL_SRC_FILES += \

core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl\

…\

core/java/android/os/IMyTool.aidl\

IMyTool.aidl即我加进去的aidl文件,加入后才能在make过程中编译到,否则将在后面的SystemServer添加系统服务时会报错提示找不到对应类。

3、 编写真正工作的服务类,继承IMyTool.Stub类(AIDL文件名.Stub,aidl生成的接口中的内部类,是一个Binder)。

服务类一般都放在framework\base\services\java\com\android\server目录中。

例如:

public class MyToolService extends IMyTool.Stub {

实现IMyTool.aidl中定义的接口。

}

4、 将自定义服务注册到SystemServer,使得开机过程中被添加。

在framework\base\services\java\com\android\server目录中的SystemServer中启动服务代码处加入:

try {

Slog.i(TAG, "MyToolService")

ServiceManager.addService(Context.MY_TOOL_SERVICE,new MyToolService(context))// MyToolService构造函数自己定义,一般都会用到Context

} catch(Throwable e) {

Slog.e(TAG, "Failure startingMyToolService", e)

}

上面代码中Context.MY_TOOL_SERVICE是自己在Context类中定义的常量,也就是给服务定义的名字,使用常量方便获取服务,而不需要记住注册服务时用的名字,且想换名字时只需改一个常量的值。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/bake/11955726.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-19
下一篇 2023-05-19

发表评论

登录后才能评论

评论列表(0条)

保存