① 首先提供接口文件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类中定义的常量,也就是给服务定义的名字,使用常量方便获取服务,而不需要记住注册服务时用的名字,且想换名字时只需改一个常量的值。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)