问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

如何在Android中添加系统服务

发布网友 发布时间:2022-04-23 04:48

我来回答

1个回答

热心网友 时间:2022-04-11 20:41

在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 = 0; i < sNextPerContextServiceCacheIndex; i++) {
cache.add(null);
}
} else {
service = cache.get(mContextCacheIndex);
if (service != null) {
return service;
}
}
//调用重载的createService函数,返回的就是TestServiceManager对象
service = createService(ctx);
cache.set(mContextCacheIndex, service);
return service;
}
}
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
女人梦见蛇的七大预兆解梦 PHOTOSHOP 怎么把眼睛点大 这些月销量10000+的防晒霜,是噱头还是真的好用? 大宝水凝保湿防晒露适合哪些肤质的人使用? 拥有人口过亿的国家最多的大洲是( )A.非洲B.亚洲C.欧洲D.大洋 世界国家最多的大洲是:( ) A.亚洲 B.大洋州 C.非洲 D.欧 拥有人口过亿的国家最多的大洲是:( ) A.非洲 B.亚洲 C.欧洲 D.大洋 餐厅一般中餐都有哪些摆台要求和标准 如何做味道正宗的中餐? 河南文科跟理科高考分数线相差多少 如何在Android设备上调试项目 “我不想说”原唱是谁? 怎样在Android 设备登陆? 如何在Android系统添加联系人 嘉实策略增长基金好吗? 嘉实基金12月7日要发行一只新的基金,不知道好不好 嘉实策略增长基金现在已经涨到了1.08600了 请问:要涨到多少的时候就可以抛啊? 请行家帮忙分析下嘉实策略增长这个基金!我想赎回! 嘉实策略增长基金 嘉实旗下哪些基金好? 为什么我的基金嘉实策略增长不能修改分红方式 我想买个基金 打算是嘉实增长和嘉实策略混合选个 每月定投200到400适合买吗 ,望专家指教。。。。 嘉实策略做长期定投好不好呢 嘉实策略增长这个基金到底怎么样啊? 嘉实策略/嘉实增长/嘉实成长三选一? 中国邮政的嘉实策略增长基金怎么样,高手请详细介绍下,谢谢! 请行家帮忙分析下嘉实策略增长这个基金!听说快发行了! 嘉实策略增长基金属于那种类型?股票型和混合型那种风险更高? 大家认为,刚发行完的嘉实策略增长基金,前景如何? 现在购买嘉实策略增长基金怎么样? 一首经典老歌《我不想说》永远经典,听哭了多少 如何在android系统中开启自己的服务 如何在Android系统中集成第三方软件 求杨钰莹《我不想说》mp3音乐百度云资源 如何在Android中打开一个窗口 如何在android 建立linux环境 求画质清晰的我不想说 杨钰莹(2002演唱会)种子下载,谢谢 如何在android上运行Python代码 杨钰莹的我不想说是几几年唱的 如何在Android上编写高效的Java代码 我不想说链接(mp3杨钰莹) 如何评价杨钰莹《我不想说》这首歌? 如何在Android下使用JNI 如何在Android中使用汇编语言 如何在android studio 《我不想说,我是一只鸡》的原歌叫什么名字? 如何在Android中使用OpenCV 《我不想说》是哪部电视剧主题曲? 如何在android开发使用ACTION 母乳性黄疸怎么判断?