Binder 학습을 통해 Service Manager 객체 가져오기

11790 단어
저희는 역시...MediaServer.cpp는 삽입점입니다.
int main(int argc, char** argv)
{
    sp<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> sm = defaultServiceManager();
    LOGI("ServiceManager: %p", sm.get());
    waitBeforeAdding( String16("media.audio_flinger") );
    AudioFlinger::instantiate();
    waitBeforeAdding( String16("media.player") );
    MediaPlayerService::instantiate();
    waitBeforeAdding( String16("media.camera") );
    CameraService::instantiate();
    waitBeforeAdding( String16("media.audio_policy") );
    AudioPolicyService::instantiate();
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
}

 
첫 마디부터 시작해 봅시다. sp는 여기에서Process State의 바늘로 이해할 수 있을 뿐입니다. 그리고proc의 바늘 변수를 정의합니다.
ProcessState::self()를 다시 한 번 살펴보자. 함수 이름을 통해 모두가 하나의 단일 모드임을 알 수 있다.self로 프로세스 내의 전체 대상을 만들고 코드를 보자.
 
sp<ProcessState> ProcessState::self()
{
    if (gProcess != NULL) return gProcess;
    
    AutoMutex _l(gProcessMutex);
    if (gProcess == NULL) gProcess = new ProcessState;
    return gProcess;
}

그렇지!결과적으로 ProcessState 객체가 반환됩니다.
그럼 AutoMutex는 어디에서 신성한가요? 여기서 우리는 코드를 보지 않고 너무 멀리 가지 않도록 하겠습니다. 제가 직접 여러분께 말씀드리자면 하나의 라인이 동기화되는 메커니즘입니다.
관련 실현 코드:frameworks/base/include/utils/threads.h, 관심 있는 신발동은 볼 수 있어요.
 
자, 이제 ProcessState의 구조 함수를 살펴보겠습니다. 또 무엇을 했을까요?
ProcessState::ProcessState()
    : mDriverFD(open_driver())
    , mVMStart(MAP_FAILED)
    , mManagesContexts(false)
    , mBinderContextCheckFunc(NULL)
    , mBinderContextUserData(NULL)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
{
    if (mDriverFD >= 0) {
        // XXX Ideally, there should be a specific define for whether we
        // have mmap (or whether we could possibly have the kernel module
        // availabla).
#if !defined(HAVE_WIN32_IPC)
        // mmap the binder, providing a chunk of virtual address space to receive transactions.
        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
        if (mVMStart == MAP_FAILED) {
            // *sigh*
            LOGE("Using /dev/binder failed: unable to mmap transaction memory.
"); close(mDriverFD); mDriverFD = -1; } #else mDriverFD = -1; #endif } LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating."); }

첫 번째 문장은 Binder의 핵심인 것 open 입니다.driver().
static int open_driver()
{
    int fd = open("/dev/binder", O_RDWR);
    if (fd >= 0) {
        fcntl(fd, F_SETFD, FD_CLOEXEC);
        int vers;
        status_t result = ioctl(fd, BINDER_VERSION, &vers);
        if (result == -1) {
            LOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
            close(fd);
            fd = -1;
        }
        if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
            LOGE("Binder driver protocol does not match user space protocol!");
            close(fd);
            fd = -1;
        }
        size_t maxThreads = 15;
        result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
        if (result == -1) {
            LOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
        }
    } else {
        LOGW("Opening '/dev/binder' failed: %s
", strerror(errno)); } return fd; }

이곳에는 두 가지 중요한 개념이 있는데 첫 번째는 Binder 드라이브를 켜서 FD를 얻는 것이고 두 번째는 Binder 프로세스가 지원하는 라인의 최대 값을 가리킨다.
 
자, Process State의 구조 함수로 돌아가면 일부 구성원 변수를 초기화하는 것 이외에 Binder에 가상 메모리를 설정하는 것을 볼 수 있다. 이 메모리를 구분하는 목적은 클라이언트와 서버가 통신할 때의 데이터 저장에 있다.
 
이어서 Main 을 보도록 하겠습니다.MediaServer main 함수의 두 번째 문장인 spsm =default Service Manager();정의를 살펴보십시오.
sp<IServiceManager> defaultServiceManager()
{
    if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
    
    {
        AutoMutex _l(gDefaultServiceManagerLock);
        if (gDefaultServiceManager == NULL) {
            gDefaultServiceManager = interface_cast<IServiceManager>(
                ProcessState::self()->getContextObject(NULL));
        }
    }
    
    return gDefaultServiceManager;
}

여기는 또 하나의 예입니다. 먼저 Process State::self()->get Context Object(NULL)가 무엇입니까?
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
{
    return getStrongProxyForHandle(0);
}

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp<IBinder> result;

    AutoMutex _l(mLock);

    handle_entry* e = lookupHandleLocked(handle);

    if (e != NULL) {
        // We need to create a new BpBinder if there isn't currently one, OR we
        // are unable to acquire a weak reference on this current one.  See comment
        // in getWeakProxyForHandle() for more info about this.
        IBinder* b = e->binder;
        if (b == NULL || !e->refs->attemptIncWeak(this)) {
            b = new BpBinder(handle); 
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
            // This little bit of nastyness is to allow us to add a primary
            // reference to the remote proxy when this team doesn't have one
            // but another team is sending the handle to us.
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }

    return result;
}

ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)
{
    const size_t N=mHandleToObject.size();
    if (N <= (size_t)handle) {
        handle_entry e;
        e.binder = NULL;
        e.refs = NULL;
        status_t err = mHandleToObject.insertAt(e, N, handle+1-N);
        if (err < NO_ERROR) return NULL;
    }
    return &mHandleToObject.editItemAt(handle);
}

위의 코드에서 getContextObject(NULL)가handle==0의 BpBinder를 되돌려받았다는 것을 알 수 있습니다. 
사실 여기서 우리는 Binder와 통신하는 Binder 대상인 BpBinder를 끌어냈다. 이것은 클라이언트의 Binder 에이전트이다. 클라이언트가 Binder와 통신하려면 반드시 그것을 빌려야 한다. 그러면 클라이언트와 대응하는 서비스 측에도 Binder와 통신하는 구성 요소가 있겠지?서두르지 말고 문제를 가지고 계속 가자.
그럼 인터페이스 한번 더 볼까요?cast는 어떻게 정의합니까?
IIterface에 정의됩니다.h,IServiceManager.cpp가 IIterface에 어떻게 인용되는지 다른 문장을 매개 변수로 설정할 수 있습니다.
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
    return INTERFACE::asInterface(obj);
}

우리는 IService Manager가 들어갔다가 다시 돌아왔기 때문에 IService Manager에서 asInterface라는 방법을 찾아야 하는데 결국 찾지 못했다.
사실 MFC 같은 거 하나 소홀히 하셨잖아요.
IServiceManager에서.h에서는 다음과 같은 매크로 함수를 참조합니다.
DECLARE_META_INTERFACE(ServiceManager);
#define DECLARE_META_INTERFACE(INTERFACE)                               \
    static const android::String16 descriptor;                          \
    static android::sp<I##INTERFACE> asInterface(                       \
            const android::sp<android::IBinder>& obj);                  \
    virtual const android::String16& getInterfaceDescriptor() const;    \
    I##INTERFACE();                                                     \
    virtual ~I##INTERFACE();      

이 정의는 asInterface에서 Ibinder의 바늘 대상의 주소를 받을 수 있습니다. 만약에 위의 코드를 되돌려준다면, 우리가 이전에 전송한 매개 변수는 BpBinder이고, BpBinder는 Ibinder를 계승하고, 되돌려준 것은 IService Manager입니다.이어서 이 asInterface의 실현을 살펴봅시다!
IServiceManager.cpp에서도 IIterface가 호출되었습니다.h의 매크로 정의:
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager"); 
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \
    const android::String16 I##INTERFACE::descriptor(NAME);             \
    const android::String16&                                            \
            I##INTERFACE::getInterfaceDescriptor() const {              \
        return I##INTERFACE::descriptor;                                \
    }                                                                   \
    android::sp<I##INTERFACE> I##INTERFACE::asInterface(                \
            const android::sp<android::IBinder>& obj)                   \
    {                                                                   \
        android::sp<I##INTERFACE> intr;                                 \
        if (obj != NULL) {                                              \
            intr = static_cast<I##INTERFACE*>(                          \
                obj->queryLocalInterface(                               \
                        I##INTERFACE::descriptor).get());               \
            if (intr == NULL) {                                         \
                intr = new Bp##INTERFACE(obj);                          \
            }                                                           \
        }                                                               \
        return intr;                                                    \
    }                                                                   \
    I##INTERFACE::I##INTERFACE() { }                                    \
    I##INTERFACE::~I##INTERFACE() { }    

Interface가 되돌아오는 것이 바로 BpService Manager이기 때문에 앞의default Service Manager가 얻은 것이 바로 이 대상입니다. 그래서 우리는 그것이 무엇인지 다시 찾아보겠습니다.
class BpServiceManager : public BpInterface<IServiceManager>
{
public:
    BpServiceManager(const sp<IBinder>& impl)
        : BpInterface<IServiceManager>(impl)
    {
    }

    virtual sp<IBinder> getService(const String16& name) const
    {
        unsigned n;
        for (n = 0; n < 5; n++){
            sp<IBinder> svc = checkService(name);
            if (svc != NULL) return svc;
            LOGI("Waiting for service %s...
", String8(name).string()); sleep(1); } return NULL; } virtual sp<IBinder> checkService( const String16& name) const { Parcel data, reply; data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); data.writeString16(name); remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply); return reply.readStrongBinder(); } virtual status_t addService(const String16& name, const sp<IBinder>& service) { Parcel data, reply; data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); data.writeString16(name); data.writeStrongBinder(service); status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply); return err == NO_ERROR ? reply.readExceptionCode() : err; } virtual Vector<String16> listServices() { Vector<String16> res; int n = 0; for (;;) { Parcel data, reply; data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); data.writeInt32(n++); status_t err = remote()->transact(LIST_SERVICES_TRANSACTION, data, &reply); if (err != NO_ERROR) break; res.add(reply.readString16()); } return res; } };

BpService Manager의 구조 함수에서 BpInterface (impl) 를 초기화하는 것을 주의하십시오. impl은 BpBinder입니다. 누구에게 부여되었는지 봅시다. BpRefBase의 mRemote이고, 우리가 BpService Manager에서 호출한remote () 는 되돌아오는 mRemote입니다.

좋은 웹페이지 즐겨찾기