如何在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

}

}

Android开机启动Service,需要使用BroadcastReceiver,Android系统,开机会发送一个开机广播,可以通过BroadcastReceiver来接收开机广播。

具体代码:

1.在配置文件AndroidManifest.xml中向系统注册receiver

<intent-filter>

<action android:name="android.intent.action.BOOT_COMPLETED" />

</intent-filter>

2.需要添加相应权限

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

3.在Receiver中就可以添加开机需要进行的 *** 作

public class BootCompletedReceiver extends BroadcastReceiver {

@Override

public void onReceive(Context context, Intent intent) {

}

}

4.执行开机后的 *** 作,Intent intent = new Intent(context,Service.class)context.startService(intent)这样即可开机启动Service了。

1. 在android/app/目录下创建接口文件IServiceTest.aidl

package android.app

oneway interface IServiceTest

{

void show()

}

2. 在Android.mk文件中的变量LOCAL_SRC_FILES中加入core/java/android/app/IServiceTest.aidl

如果要在sdk中发布这个服务就在变量aidl_files中加入一样的路径。

3. 通过aidl编译器编译IServiceTest.aidl,会生成一个IServiceTest.java文件。

4. 创建服务类ServiceTestSerice

class ServiceTestSerice extends IServiceTest.Stub{

private static final String TAG = “ServiceTestSerice”

Context mContext

public ServiceTestSerice(Context context){

mContext = context

}

public void show() throws RemoteException {

System.out.println(“My ServiceTestSerice”)

}

}

.5. 注册服务

Java系统服务在ServerThread类的run()方法中生成并注册到android平台,生成ServiceTestSerice实例对象,通过ServiceManager的addService方法将服务注册到系统中。

try{

serviceTestSerice = new ServiceTestSerice(context)

ServiceManager.addService(Context.SERVICE_TEST, serviceTestSerice)

} catch (Throwable t) {

}

ServiceTestSerice serviceTestSerice;

以上代码在ServerThread类的run()方法中。

在Context类中加入:

public static final StringSERVICE_TEST = “servicetest”

ServiceTestManager sServiceTestManager

6. 使用系统服务

编写一个ServiceTestManager类,为包装类。

public class ServiceTestManager{

private final IServiceTest mService

ServiceTestManager(IServiceTest service){

mService = service

}

public void test(){

try{

mService. show()

} catch (RemoteException ex){

}

}

}

7 提供应用层开发接口

在ContextImpl类中的getSystemService()方法中加入如下代码:

else if (SERVICE_TEST.equals(name)){

return getServiceTestManager()

}

private ServiceTestManager getServiceTestManager(){

synchronized(sSync) {

if (sServiceTestManager == null){

IBinder b = ServiceManager.getService(SERVICE_TEST)

IServiceTest service = IServiceTest.Stub.asInterface(b)

sServiceTestManager = new ServiceTestManager(service)

}

}

调用过程如下:

ServiceTestManager manager= (ServiceTestManager) getSystemService(Context. SERVICE_TEST)

manager.show()

8. 测试

make

make update-api 更新current.xml文件

生成system.imz文件,放到<ANDROID_SDK>/platform/android-20/images/目录下,

adb shell

service list


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

原文地址:https://54852.com/bake/11956365.html

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

发表评论

登录后才能评论

评论列表(0条)

    保存