1. 程式人生 > >android—如何新增一個系統服務

android—如何新增一個系統服務

前面分析過binder的實現流程,binder的實現包含了java和c++兩部分,所以service的實現也包括java和c++兩種,那麼應該如何去自己實現並新增一個service?

c++中新增service

下面以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, eDisplayIdHdmi = 1 }; /* 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;
            }
        }