注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

东东的博客

江南烟雨,同大家一起分享

 
 
 

日志

 
 

android binder 讲解(三)  

2011-04-28 11:38:07|  分类: android相关 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
第三部分 程序中Binder的具体实现 
  3.1 一个利用接口的具体实现 
    PermissionController也是libutils中定义的一个有关权限控制的接口,它一共包含两个文件:IPermissionController.h和IPermissionController.cpp这个结构在所有类的实现中都是类似的。 
     头文件IPermissionController.h的主要内容是定义IPermissionController接口和类BnPermissionController: 

Java代码 


class IPermissionController : public IInterface  
{  
public:  
    DECLARE_META_INTERFACE(PermissionController);  
    virtual bool   checkPermission(const String16& permission,int32_t pid, int32_t uid) = 0;  
    enum {  
        CHECK_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION  
    };  
};  
class BnPermissionController : public BnInterface  
{  
public:  
    virtual status_t    onTransact( uint32_t code,  
                                    const Parcel& data,  
                                    Parcel* reply,  
                                    uint32_t flags = 0);  
};  


    IPermissionController是一个接口类,只有checkPermission()一个纯虚函数。 
BnPermissionController继承了以BnPermissionController实例化模版类BnInterface。因 
此,BnPermissionController,事实上BnPermissionController双继承了BBinder和 
IPermissionController。 
    实现文件IPermissionController.cpp中,首先实现了一个BpPermissionController。 

Java代码 


class BpPermissionController : public BpInterface  
{  
public:  
    BpPermissionController(const sp& impl)  
        : BpInterface(impl)  
    {  
    }  
    virtual bool checkPermission(const String16& permission, int32_t pid, int32_t uid)  
    {  
        Parcel data, reply;  
        data.writeInterfaceToken(IPermissionController::  
                                       getInterfaceDescriptor());  
        data.writeString16(permission);  
        data.writeInt32(pid);  
        data.writeInt32(uid);  
        remote()->transact(CHECK_PERMISSION_TRANSACTION, data, &reply);  
        if (reply.readInt32() != 0) return 0;  
        return reply.readInt32() != 0;  
    }  
};  


IMPLEMENT_META_INTERFACE(PermissionController, "android.os.IPermissionController"); 
BpPermissionController继承了BpInterface,它本身是一个 
已经实现的类,而且并没有在接口中体现。这个类按照格式写就可以,在实现checkPermission()函数的过程中,使用Parcel作为传输数据 
的容器,传输中时候transact()函数,其参数需要包含枚举值CHECK_PERMISSION_TRANSACTION。 
IMPLEMENT_META_INTERFACE用于扶助生成。 
    BnPermissionController中实现的onTransact()函数如下所示: 

Java代码 


status_t BnPermissionController:: BnTransact(  
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)  
{  
    switch(code) {  
        case CHECK_PERMISSION_TRANSACTION: {  
            CHECK_INTERFACE(IPermissionController, data, reply);  
            String16 permission = data.readString16();  
            int32_t pid = data.readInt32();  
            int32_t uid = data.readInt32();  
            bool res = checkPermission(permission, pid, uid);  
            reply->writeInt32(0);  
            reply->writeInt32(res ? 1 : 0);  
            return NO_ERROR;  
        } break;  
        default:  
            return BBinder:: BnTransact(code, data, reply, flags);  
    }  
}  


     在onTransact()函数中根据枚举值判断数据使用的方式。注意,由于BnPermissionController也是继承了类 
IPermissionController,但是纯虚函数checkPermission()依然没有实现。因此这个 
BnPermissionController类并不能实例化,它其实也还是一个接口,需要一个实现类来继承它,那才是实现具体功能的类。 
  3.2 BnABC的实现 
    本地服务启动后将形成一个守护进程,具体的本地服务是由一个实现类继承BnABC来实现的,这个服务的名称通常叫做ABC。 
    在其中,通常包含了一个instantiate()函数,这个函数一般按照如下的方式实现: 
void ABC::instantiate() { 
    defaultServiceManager()->addService( 
            String16("XXX.ABC"), new ABC ()); 

    按照这种方式,通过调用defaultServiceManager()函数,将增加一个名为"XXX.ABC"的服务。 
    在这个defaultServiceManager()函数中调用了: 
ProcessState::self()->getContextObject(NULL)); 
    IPCThreadState* ipc = IPCThreadState::self(); 
   IPCThreadState::talkWithDriver() 
在ProcessState 类建立的过程中调用open_driver()打开 
驱动 
程序,在talkWithDriver()的执行过程中。 
  3.3 BpABC调用的实现 
    BpABC调用的过程主要通过mRemote()->transact() 来传输数据,mRemote()是BpRefBase的成员,它是一个IBinder。这个调用过程如下所示: 

   

Java代码 


mRemote()->transact()  
    Process::self()  
    IPCThreadState::self()->transact()  
    writeTransactionData()  
    waitForResponse()  
    talkWithDriver()  
    ioctl(fd, BINDER_WRITE_READ, &bwr)  


    在IPCThreadState::executeCommand()函数中,实现传输操作。

o IBinder接口

IBinder接口是对跨进程的对象的抽象。普通对象在当前进程可以访问,如果希望对象能被其它进程访问,那就必须实现IBinder接口。IBinder接口可以指向本地对象,也可以指向远程对象,调用者不需要关心指向的对象是本地的还是远程。

transact是IBinder接口中一个比较重要的函数,它的函数原型如下:

 


virtual status_t transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) = 0;  

virtual status_t transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) = 0;

android中的IPC的基本模型是基于客户/服务器(C/S)架构的。

客户端

请求通过内核模块中转

服务端

如果IBinder指向的是一个客户端代理,那transact只是把请求发送给服务器。服务端的IBinder的transact则提供了实际的服务。

o 客户端

BpBinder是远程对象在当前进程的代理,它实现了IBinder接口。它的transact函数实现如下:

 


status_t BpBinder::transact(  
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)  
{  
    // Once a binder has died, it will never come back to life.  
    if (mAlive) {  
        status_t status = IPCThreadState::self()->transact(  
            mHandle, code, data, reply, flags);  
        if (status == DEAD_OBJECT) mAlive = 0;  
        return status;  
    }   
   
    return DEAD_OBJECT;  
}  

status_t BpBinder::transact(

    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

{

    // Once a binder has died, it will never come back to life.

    if (mAlive) {

        status_t status = IPCThreadState::self()->transact(

            mHandle, code, data, reply, flags);

        if (status == DEAD_OBJECT) mAlive = 0;

        return status;

    }

 

    return DEAD_OBJECT;

}

参数说明:


code 是请求的ID号。
data 是请求的参数。
reply 是返回的结果。
flags 一些额外的标识,如FLAG_ONEWAY。通常为0。

transact只是简单的调用了IPCThreadState::self()的transact,在IPCThreadState::transact中:

 


status_t IPCThreadState::transact(int32_t handle,  
                                  uint32_t code, const Parcel& data,  
                                  Parcel* reply, uint32_t flags)  
{  
    status_t err = data.errorCheck();  
   
    flags |= TF_ACCEPT_FDS;  
   
    IF_LOG_TRANSACTIONS() {  
        TextOutput::Bundle _b(alog);  
        alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand "  
            << handle << " / code " << TypeCode(code) << ": "  
            << indent << data << dedent << endl;  
    }  
   
    if (err == NO_ERROR) {  
        LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),  
            (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");  
        err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);  
    }  
   
    if (err != NO_ERROR) {  
        if (reply) reply->setError(err);  
        return (mLastError = err);  
    }  
   
    if ((flags & TF_ONE_WAY) == 0) {  
        if (reply) {  
            err = waitForResponse(reply);  
        } else {  
            Parcel fakeReply;  
            err = waitForResponse(&fakeReply);  
        }  
   
        IF_LOG_TRANSACTIONS() {  
            TextOutput::Bundle _b(alog);  
            alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand "  
                << handle << ": ";  
            if (reply) alog << indent << *reply << dedent << endl;  
            else alog << "(none requested)" << endl;  
        }  
    } else {  
        err = waitForResponse(NULL, NULL);  
    }  
   
    return err;  
}  
   
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)  
{  
    int32_t cmd;  
    int32_t err;  
   
    while (1) {  
        if ((err=talkWithDriver()) < NO_ERROR) break;  
        err = mIn.errorCheck();  
        if (err < NO_ERROR) break;  
        if (mIn.dataAvail() == 0) continue;  
   
        cmd = mIn.readInt32();  
   
        IF_LOG_COMMANDS() {  
            alog << "Processing waitForResponse Command: "  
                << getReturnString(cmd) << endl;  
        }  
   
        switch (cmd) {  
        case BR_TRANSACTION_COMPLETE:  
            if (!reply && !acquireResult) goto finish;  
            break;  
   
        case BR_DEAD_REPLY:  
            err = DEAD_OBJECT;  
            goto finish;  
   
        case BR_FAILED_REPLY:  
            err = FAILED_TRANSACTION;  
            goto finish;  
   
        case BR_ACQUIRE_RESULT:  
            {  
                LOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT");  
                const int32_t result = mIn.readInt32();  
                if (!acquireResult) continue;  
                *acquireResult = result ? NO_ERROR : INVALID_OPERATION;  
            }  
            goto finish;  
   
        case BR_REPLY:  
            {  
                binder_transaction_data tr;  
                err = mIn.read(&tr, sizeof(tr));  
                LOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY");  
                if (err != NO_ERROR) goto finish;  
   
                if (reply) {  
                    if ((tr.flags & TF_STATUS_CODE) == 0) {  
                        reply->ipcSetDataReference(  
                            reinterpret_cast(tr.data.ptr.buffer),  
                            tr.data_size,  
                            reinterpret_cast(tr.data.ptr.offsets),  
                            tr.offsets_size/sizeof(size_t),  
                            freeBuffer, this);  
                    } else {  
                        err = *static_cast(tr.data.ptr.buffer);  
                        freeBuffer(NULL,  
                            reinterpret_cast(tr.data.ptr.buffer),  
                            tr.data_size,  
                            reinterpret_cast(tr.data.ptr.offsets),  
                            tr.offsets_size/sizeof(size_t), this);  
                    }  
                } else {  
                    freeBuffer(NULL,  
                        reinterpret_cast(tr.data.ptr.buffer),  
                        tr.data_size,  
                        reinterpret_cast(tr.data.ptr.offsets),  
                        tr.offsets_size/sizeof(size_t), this);  
                    continue;  
                }  
            }  
            goto finish;  
   
        default:  
            err = executeCommand(cmd);  
            if (err != NO_ERROR) goto finish;  
            break;  
        }  
    }  
   
finish:  
    if (err != NO_ERROR) {  
        if (acquireResult) *acquireResult = err;  
        if (reply) reply->setError(err);  
        mLastError = err;  
    }  
   
    return err;  
}  

status_t IPCThreadState::transact(int32_t handle,

                                  uint32_t code, const Parcel& data,

                                  Parcel* reply, uint32_t flags)

{

    status_t err = data.errorCheck();

 

    flags |= TF_ACCEPT_FDS;

 

    IF_LOG_TRANSACTIONS() {

        TextOutput::Bundle _b(alog);

        alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand "

            << handle << " / code " << TypeCode(code) << ": "

            << indent << data << dedent << endl;

    }

 

    if (err == NO_ERROR) {

        LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),

            (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");

        err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);

    }

 

    if (err != NO_ERROR) {

        if (reply) reply->setError(err);

        return (mLastError = err);

    }

 

    if ((flags & TF_ONE_WAY) == 0) {

        if (reply) {

            err = waitForResponse(reply);

        } else {

            Parcel fakeReply;

            err = waitForResponse(&fakeReply);

        }

 

        IF_LOG_TRANSACTIONS() {

            TextOutput::Bundle _b(alog);

            alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand "

                << handle << ": ";

            if (reply) alog << indent << *reply << dedent << endl;

            else alog << "(none requested)" << endl;

        }

    } else {

        err = waitForResponse(NULL, NULL);

    }

 

    return err;

}

 

status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)

{

    int32_t cmd;

    int32_t err;

 

    while (1) {

        if ((err=talkWithDriver()) < NO_ERROR) break;

        err = mIn.errorCheck();

        if (err < NO_ERROR) break;

        if (mIn.dataAvail() == 0) continue;

 

        cmd = mIn.readInt32();

 

        IF_LOG_COMMANDS() {

            alog << "Processing waitForResponse Command: "

                << getReturnString(cmd) << endl;

        }

 

        switch (cmd) {

        case BR_TRANSACTION_COMPLETE:

            if (!reply && !acquireResult) goto finish;

            break;

 

        case BR_DEAD_REPLY:

            err = DEAD_OBJECT;

            goto finish;

 

        case BR_FAILED_REPLY:

            err = FAILED_TRANSACTION;

            goto finish;

 

        case BR_ACQUIRE_RESULT:

            {

                LOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT");

                const int32_t result = mIn.readInt32();

                if (!acquireResult) continue;

                *acquireResult = result ? NO_ERROR : INVALID_OPERATION;

            }

            goto finish;

 

        case BR_REPLY:

            {

                binder_transaction_data tr;

                err = mIn.read(&tr, sizeof(tr));

                LOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY");

                if (err != NO_ERROR) goto finish;

 

                if (reply) {

                    if ((tr.flags & TF_STATUS_CODE) == 0) {

                        reply->ipcSetDataReference(

                            reinterpret_cast(tr.data.ptr.buffer),

                            tr.data_size,

                            reinterpret_cast(tr.data.ptr.offsets),

                            tr.offsets_size/sizeof(size_t),

                            freeBuffer, this);

                    } else {

                        err = *static_cast(tr.data.ptr.buffer);

                        freeBuffer(NULL,

                            reinterpret_cast(tr.data.ptr.buffer),

                            tr.data_size,

                            reinterpret_cast(tr.data.ptr.offsets),

                            tr.offsets_size/sizeof(size_t), this);

                    }

                } else {

                    freeBuffer(NULL,

                        reinterpret_cast(tr.data.ptr.buffer),

                        tr.data_size,

                        reinterpret_cast(tr.data.ptr.offsets),

                        tr.offsets_size/sizeof(size_t), this);

                    continue;

                }

            }

            goto finish;

 

        default:

            err = executeCommand(cmd);

            if (err != NO_ERROR) goto finish;

            break;

        }

    }

 

finish:

    if (err != NO_ERROR) {

        if (acquireResult) *acquireResult = err;

        if (reply) reply->setError(err);

        mLastError = err;

    }

 

    return err;

}

这里transact把请求经内核模块发送了给服务端,服务端处理完请求之后,沿原路返回结果给调用者。这里也可以看出请求是同步操作,它会等待直到结果返回为止。

在BpBinder之上进行简单包装,我们可以得到与服务对象相同的接口,调用者无需要关心调用的对象是远程的还是本地的。拿ServiceManager来说:
(frameworks/base/libs/utils/IServiceManager.cpp)

 


class BpServiceManager : public BpInterface  
{  
public:  
    BpServiceManager(const sp& impl)  
        : BpInterface(impl)  
    {  
    }  
...  
    virtual status_t addService(const String16& name, const sp& 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.readInt32() : err;  
    }  
...  
};  

class BpServiceManager : public BpInterface

{

public:

    BpServiceManager(const sp& impl)

        : BpInterface(impl)

    {

    }

...

    virtual status_t addService(const String16& name, const sp& 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.readInt32() : err;

    }

...

};

BpServiceManager实现了 IServiceManager和IBinder两个接口,调用者可以把BpServiceManager的对象看作是一个 IServiceManager对象或者IBinder对象。当调用者把BpServiceManager对象当作IServiceManager对象使 用时,所有的请求只是对BpBinder::transact的封装。这样的封装使得调用者不需要关心IServiceManager对象是本地的还是远 程的了。

客户通过defaultServiceManager函数来创建BpServiceManager对象:
(frameworks/base/libs/utils/IServiceManager.cpp)

 


sp<IServiceManager> defaultServiceManager()  
{  
    if (gDefaultServiceManager != NULL) return gDefaultServiceManager;   
   
    {  
        AutoMutex _l(gDefaultServiceManagerLock);  
        if (gDefaultServiceManager == NULL) {  
            gDefaultServiceManager = interface_cast<IServiceManager>(  
                ProcessState::self()->getContextObject(NULL));  
        }  
    }   
   
    return gDefaultServiceManager;  
}  

sp<IServiceManager> defaultServiceManager()

{

    if (gDefaultServiceManager != NULL) return gDefaultServiceManager;

 

    {

        AutoMutex _l(gDefaultServiceManagerLock);

        if (gDefaultServiceManager == NULL) {

            gDefaultServiceManager = interface_cast<IServiceManager>(

                ProcessState::self()->getContextObject(NULL));

        }

    }

 

    return gDefaultServiceManager;

}

先通过ProcessState::self()->getContextObject(NULL)创建一个Binder对象,然后通过 interface_cast和IMPLEMENT_META_INTERFACE(ServiceManager, “android.os.IServiceManager”)把Binder对象包装成 IServiceManager对象。原理上等同于创建了一个BpServiceManager对象。

ProcessState::self()->getContextObject调用ProcessState::getStrongProxyForHandle创建代理对象:

 


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;  
}  

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;

}

如果handle为空,默认为context_manager对象,context_manager实际上就是ServiceManager。
o 服务端
服务端也要实现IBinder接口,BBinder类对IBinder接口提供了部分默认实现,其中transact的实现如下:

 


status_t BBinder::transact(  
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)  
{  
    data.setDataPosition(0);   
   
    status_t err = NO_ERROR;  
    switch (code) {  
        case PING_TRANSACTION:  
            reply->writeInt32(pingBinder());  
            break;  
        default:  
            err = onTransact(code, data, reply, flags);  
            break;  
    }   
   
    if (reply != NULL) {  
        reply->setDataPosition(0);  
    }   
   
    return err;  
}  

status_t BBinder::transact(

    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

{

    data.setDataPosition(0);

 

    status_t err = NO_ERROR;

    switch (code) {

        case PING_TRANSACTION:

            reply->writeInt32(pingBinder());

            break;

        default:

            err = onTransact(code, data, reply, flags);

            break;

    }

 

    if (reply != NULL) {

        reply->setDataPosition(0);

    }

 

    return err;

}

PING_TRANSACTION请求用来检查对象是否还存在,这里简单的把 pingBinder的返回值返回给调用者。其它的请求交给onTransact处理。onTransact是BBinder里声明的一个 protected类型的虚函数,这个要求它的子类去实现。比如CameraService里的实现如下:

 


status_t CameraService::onTransact(  
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)  
{  
    // permission checks...  
    switch (code) {  
        case BnCameraService::CONNECT:  
            IPCThreadState* ipc = IPCThreadState::self();  
            const int pid = ipc->getCallingPid();  
            const int self_pid = getpid();  
            if (pid != self_pid) {  
                // we're called from a different process, do the real check  
                if (!checkCallingPermission(  
                        String16("android.permission.CAMERA")))  
                {  
                    const int uid = ipc->getCallingUid();  
                    LOGE("Permission Denial: "  
                            "can't use the camera pid=%d, uid=%d", pid, uid);  
                    return PERMISSION_DENIED;  
                }  
            }  
            break;  
    }  
   
    status_t err = BnCameraService::onTransact(code, data, reply, flags);  
   
    LOGD("+++ onTransact err %d code %d", err, code);  
   
    if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {  
        // the 'service' command interrogates this binder for its name, and then supplies it  
        // even for the debugging commands.  that means we need to check for it here, using  
        // ISurfaceComposer (since we delegated the INTERFACE_TRANSACTION handling to  
        // BnSurfaceComposer before falling through to this code).  
   
        LOGD("+++ onTransact code %d", code);  
   
        CHECK_INTERFACE(ICameraService, data, reply);  
   
        switch(code) {  
        case 1000:  
        {  
            if (gWeakHeap != 0) {  
                sp h = gWeakHeap.promote();  
                IMemoryHeap *p = gWeakHeap.unsafe_get();  
                LOGD("CHECKING WEAK REFERENCE %p (%p)", h.get(), p);  
                if (h != 0)  
                    h->printRefs();  
                bool attempt_to_delete = data.readInt32() == 1;  
                if (attempt_to_delete) {  
                    // NOT SAFE!  
                    LOGD("DELETING WEAK REFERENCE %p (%p)", h.get(), p);  
                    if (p) delete p;  
                }  
                return NO_ERROR;  
            }  
        }  
        break;  
        default:  
            break;  
        }  
    }  
    return err;  
}  

status_t CameraService::onTransact(

    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

{

    // permission checks...

    switch (code) {

        case BnCameraService::CONNECT:

            IPCThreadState* ipc = IPCThreadState::self();

            const int pid = ipc->getCallingPid();

            const int self_pid = getpid();

            if (pid != self_pid) {

                // we're called from a different process, do the real check

                if (!checkCallingPermission(

                        String16("android.permission.CAMERA")))

                {

                    const int uid = ipc->getCallingUid();

                    LOGE("Permission Denial: "

                            "can't use the camera pid=%d, uid=%d", pid, uid);

                    return PERMISSION_DENIED;

                }

            }

            break;

    }

 

    status_t err = BnCameraService::onTransact(code, data, reply, flags);

 

    LOGD("+++ onTransact err %d code %d", err, code);

 

    if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {

        // the 'service' command interrogates this binder for its name, and then supplies it

        // even for the debugging commands.  that means we need to check for it here, using

        // ISurfaceComposer (since we delegated the INTERFACE_TRANSACTION handling to

        // BnSurfaceComposer before falling through to this code).

 

        LOGD("+++ onTransact code %d", code);

 

        CHECK_INTERFACE(ICameraService, data, reply);

 

        switch(code) {

        case 1000:

        {

            if (gWeakHeap != 0) {

                sp h = gWeakHeap.promote();

                IMemoryHeap *p = gWeakHeap.unsafe_get();

                LOGD("CHECKING WEAK REFERENCE %p (%p)", h.get(), p);

                if (h != 0)

                    h->printRefs();

                bool attempt_to_delete = data.readInt32() == 1;

                if (attempt_to_delete) {

                    // NOT SAFE!

                    LOGD("DELETING WEAK REFERENCE %p (%p)", h.get(), p);

                    if (p) delete p;

                }

                return NO_ERROR;

            }

        }

        break;

        default:

            break;

        }

    }

    return err;

}

由此可见,服务端的onTransact是一个请求分发函数,它根据请求码(code)做相应的处理。

o 消息循环

服务端(任何进程都可以作为服务端)有一个线程监听来自客户端的请求,并循环处理这些请求。

如果在主线程中处理请求,可以直接调用下面的函数:

 


IPCThreadState::self()->joinThreadPool(mIsMain);  

IPCThreadState::self()->joinThreadPool(mIsMain);

如果想在非主线程中处理请求,可以按下列方式:

 


sp  
pan>= ProcessState::self();  
if (proc->supportsProcesses()) {  
    LOGV("App process: starting thread pool.\n");  
    proc->startThreadPool();  
}  

        sp

 proc = ProcessState::self();

        if (proc->supportsProcesses()) {

            LOGV("App process: starting thread pool.\n");

            proc->startThreadPool();

        }

startThreadPool的实现原理:

 


void ProcessState::startThreadPool()  
{  
    AutoMutex _l(mLock);  
    if (!mThreadPoolStarted) {  
        mThreadPoolStarted = true;  
        spawnPooledThread(true);  
    }  
}   
   
void ProcessState::spawnPooledThread(bool isMain)  
{  
    if (mThreadPoolStarted) {  
        int32_t s = android_atomic_add(1, &mThreadPoolSeq);  
        char buf[32];  
        sprintf(buf, "Binder Thread #%d", s);  
        LOGV("Spawning new pooled thread, name=%s\n", buf);  
        sp  
 t = new PoolThread(isMain);  
        t->run(buf);  
    }  
}  

void ProcessState::startThreadPool()

{

    AutoMutex _l(mLock);

    if (!mThreadPoolStarted) {

        mThreadPoolStarted = true;

        spawnPooledThread(true);

    }

}

 

void ProcessState::spawnPooledThread(bool isMain)

{

    if (mThreadPoolStarted) {

        int32_t s = android_atomic_add(1, &mThreadPoolSeq);

        char buf[32];

        sprintf(buf, "Binder Thread #%d", s);

        LOGV("Spawning new pooled thread, name=%s\n", buf);

        sp

 t = new PoolThread(isMain);

        t->run(buf);

    }

}

这里创建了PoolThread的对象,实现上就是创建了一个线程。所有的线程类都要实现threadLoop虚函数。PoolThread的threadLoop的实现如下:

 


virtual bool threadLoop()  
{  
    IPCThreadState::self()->joinThreadPool(mIsMain);  
    return false;  
}  

    virtual bool threadLoop()

    {

        IPCThreadState::self()->joinThreadPool(mIsMain);

        return false;

    }

上述代码,简而言之就是创建了一个线程,然后在线程里调用 IPCThreadState::self()->joinThreadPool函数。

 

  评论这张
 
阅读(1894)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017