Android IPC 通讯机制源码分析 一

来源:互联网 发布:人工神经网络 知乎 编辑:程序博客网 时间:2024/04/30 09:13
Android IPC 通讯机制源码分析 一
2008年12月06日 星期六 10:36

Android IPC 通讯机制源码分析
----Albertchen

Binder通信简介:
    Linux系统中进程间通信的方式有:socket, named pipe,message queque, signal,share memory。Java系统中的进程间通信方式有socket, named pipe等,android应用程序理所当然可以应用JAVA的IPC机制实现进程间的通信,但我查看android的源码,在同一终端上的应用软件的通信几乎看不到这些IPC通信方式,取而代之的是Binder通信。Google为什么要采用这种方式呢,这取决于Binder通信方式的高效率。 Binder通信是通过linux的binder driver来实现的,Binder通信操作类似线程迁移(thread migration),两个进程间IPC看起来就象是一个进程进入另一个进程执行代码然后带着执行的结果返回。Binder的用户空间为每一个进程维护着一个可用的线程池,线程池用于处理到来的IPC以及执行进程本地消息,Binder通信是同步而不是异步。
    Android中的Binder通信是基于Service与Client的,所有需要IBinder通信的进程都必须创建一个IBinder接口,系统中有一个进程管理所有的system service,Android不允许用户添加非授权的System service,当然现在源码开发了,我们可以修改一些代码来实现添加底层system Service的目的。对用户程序来说,我们也要创建server,或者Service用于进程间通信,这里有一个ActivityManagerService管理JAVA应用层所有的service创建与连接(connect),disconnect,所有的Activity也是通过这个service来启动,加载的。ActivityManagerService也是加载在Systems Servcie中的。
    Android虚拟机启动之前系统会先启动service Manager进程,service Manager打开binder驱动,并通知binder kernel驱动程序这个进程将作为System Service Manager,然后该进程将进入一个循环,等待处理来自其他进程的数据。用户创建一个System service后,通过defaultServiceManager得到一个远程ServiceManager的接口,通过这个接口我们可以调用addService函数将System service添加到Service Manager进程中,然后client可以通过getService获取到需要连接的目的Service的IBinder对象,这个IBinder是Service的BBinder在binder kernel的一个参考,所以service IBinder 在binder kernel中不会存在相同的两个IBinder对象,每一个Client进程同样需要打开Binder驱动程序。对用户程序而言,我们获得这个对象就可以通过binder kernel访问service对象中的方法。Client与Service在不同的进程中,通过这种方式实现了类似线程间的迁移的通信方式,对用户程序而言当调用Service返回的IBinder接口后,访问Service中的方法就如同调用自己的函数。
下图为client与Service建立连接的示意图

 

 


首先从ServiceManager注册过程来逐步分析上述过程是如何实现的。

ServiceMananger进程注册过程源码分析:
Service Manager Process(Service_manager.c):
    Service_manager为其他进程的Service提供管理,这个服务程序必须在Android Runtime起来之前运行,否则Android JAVA Vm ActivityManagerService无法注册。
int main(int argc, char **argv)
{
    struct binder_state *bs;
    void *svcmgr = BINDER_SERVICE_MANAGER;

    bs = binder_open(128*1024); //打开/dev/binder 驱动

    if (binder_become_context_manager(bs)) {//注册为service manager in binder kernel
        LOGE("cannot become context manager (%s)/n", strerror(errno));
        return -1;
    }
    svcmgr_handle = svcmgr;
    binder_loop(bs, svcmgr_handler);
    return 0;
}
首先打开binder的驱动程序然后通过binder_become_context_manager函数调用ioctl告诉Binder Kernel驱动程序这是一个服务管理进程,然后调用binder_loop等待来自其他进程的数据。BINDER_SERVICE_MANAGER是服务管理进程的句柄,它的定义是:
/* the one magic object */
#define BINDER_SERVICE_MANAGER ((void*) 0)
如果客户端进程获取Service时所使用的句柄与此不符,Service Manager将不接受Client的请求。客户端如何设置这个句柄在下面会介绍。

CameraSerivce服务的注册(Main_mediaservice.c)
int main(int argc, char** argv)
{
    sp<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> sm = defaultServiceManager();
    LOGI("ServiceManager: %p", sm.get());
    AudioFlinger::instantiate();             //Audio 服务
    MediaPlayerService::instantiate();       //mediaPlayer服务
    CameraService::instantiate();             //Camera 服务
    ProcessState::self()->startThreadPool(); //为进程开启缓冲池
    IPCThreadState::self()->joinThreadPool(); //将进程加入到缓冲池
}

CameraService.cpp
void CameraService::instantiate() {
    defaultServiceManager()->addService(
            String16("media.camera"), new CameraService());
}
创建CameraService服务对象并添加到ServiceManager进程中。


client获取remote IServiceManager IBinder接口:
sp<IServiceManager> defaultServiceManager()
{
    if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
   
    {
        AutoMutex _l(gDefaultServiceManagerLock);
        if (gDefaultServiceManager == NULL) {
            gDefaultServiceManager = interface_cast<IServiceManager>(
                ProcessState::self()->getContextObject(NULL));
        }
    }
    return gDefaultServiceManager;
}
任何一个进程在第一次调用defaultServiceManager的时候gDefaultServiceManager值为Null,所以该进程会通过ProcessState::self得到ProcessState实例。ProcessState将打开Binder驱动。
ProcessState.cpp
sp<ProcessState> ProcessState::self()
{
    if (gProcess != NULL) return gProcess;
   
    AutoMutex _l(gProcessMutex);
    if (gProcess == NULL) gProcess = new ProcessState;
    return gProcess;
}

ProcessState::ProcessState()
: mDriverFD(open_driver()) //打开/dev/binder驱动
...........................
{
}

sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
{
    if (supportsProcesses()) {
        return getStrongProxyForHandle(0);
    } else {
        return getContextObject(String16("default"), caller);
    }
}
Android是支持Binder驱动的所以程序会调用getStrongProxyForHandle。这里handle为0,正好与Service_manager中的BINDER_SERVICE_MANAGER一致。
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; //第一次调用该函数b为Null
        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;
}
第一次调用的时候b为Null所以会为b生成一BpBinder对象:
BpBinder::BpBinder(int32_t handle)
    : mHandle(handle)
    , mAlive(1)
    , mObitsSent(0)
    , mObituaries(NULL)
{
    LOGV("Creating BpBinder %p handle %d/n", this, mHandle);

    extendObjectLifetime(OBJECT_LIFETIME_WEAK);
    IPCThreadState::self()->incWeakHandle(handle);
}

void IPCThreadState::incWeakHandle(int32_t handle)
{
    LOG_REMOTEREFS("IPCThreadState::incWeakHandle(%d)/n", handle);
    mOut.writeInt32(BC_INCREFS);
    mOut.writeInt32(handle);
}
getContextObject返回了一个BpBinder对象。
interface_cast<IServiceManager>(
                ProcessState::self()->getContextObject(NULL));

template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
    return INTERFACE::asInterface(obj);
}
将这个宏扩展后最终得到的是:
sp<IServiceManager> IServiceManager::asInterface(const sp<IBinder>& obj)    
    {                                                                   
        sp<IServiceManager> intr;                                          
        if (obj != NULL) {                                              
            intr = static_cast<IServiceManager*>(                          
                obj->queryLocalInterface(                               
                        IServiceManager::descriptor).get());               
            if (intr == NULL) {                                         
                intr = new BpServiceManager(obj);                          
            }                                                           
        }                                                               
        return intr;
}
返回一个BpServiceManager对象,这里obj就是前面我们创建的BpBInder对象。

client获取Service的远程IBinder接口
以CameraService为例(camera.cpp):
const sp<ICameraService>& Camera::getCameraService()
{
    Mutex::Autolock _l(mLock);
    if (mCameraService.get() == 0) {
        sp<IServiceManager> sm = defaultServiceManager();
        sp<IBinder> binder;
        do {
            binder = sm->getService(String16("media.camera"));
            if (binder != 0)
                break;
            LOGW("CameraService not published, waiting...");
            usleep(500000); // 0.5 s
        } while(true);
        if (mDeathNotifier == NULL) {
            mDeathNotifier = new DeathNotifier();
        }
        binder->linkToDeath(mDeathNotifier);
        mCameraService = interface_cast<ICameraService>(binder);
    }
    LOGE_IF(mCameraService==0, "no CameraService!?");
    return mCameraService;
}
由前面的分析可知sm是BpCameraService对象://应该为BpServiceManager对象
    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 sevice %s.../n", 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();
}
这里的remote就是我们前面得到BpBinder对象。所以checkService将调用BpBinder中的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;
}
mHandle为0,BpBinder继续往下调用IPCThreadState:transact函数将数据发给与mHandle相关联的Service Manager Process。
status_t IPCThreadState::transact(int32_t handle,
                                  uint32_t code, const Parcel& data,
                                  Parcel* reply, uint32_t flags)
{
   ............................................................
    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);
        }
       ..............................
   
    return err;
}

通过writeTransactionData构造要发送的数据
status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
    int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{
    binder_transaction_data tr;

    tr.target.handle = handle; //这个handle将传递到service_manager
    tr.code = code;
    tr.flags = bindrFlags;
。。。。。。。。。。。。。。
}
waitForResponse将调用talkWithDriver与对Binder kernel进行读写操作。当Binder kernel接收到数据后,service_mananger线程的ThreadPool就会启动,service_manager查找到CameraService服务后调用binder_send_reply,将返回的数据写入Binder kernel,Binder kernel。
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
    int32_t cmd;
    int32_t err;

    while (1) {
        if ((err=talkWithDriver()) < NO_ERROR) break;
      
..............................................    
}
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
   ............................................
#if defined(HAVE_ANDROID_OS)
        if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
            err = NO_ERROR;
        else
            err = -errno;
#else
        err = INVALID_OPERATION;
#endif
...................................................
}
通过上面的ioctl系统函数中BINDER_WRITE_READ对binder kernel进行读写。

 


类别:android原创 | | 添加到搜藏 | 分享到i贴吧 | 浏览(3723) | 评论 (26)
 
上一篇:Android 应用初始化及窗体事件的...    下一篇:Android IPC 通讯机制源码分析 ...
 
 
最近读者:
登录后,您就出现在这里。   davidwjxworld_harveyobiwonglianwei_wanganly_junbmflss曹县小伙kikicat0_0 
 
网友评论:
1
网友:may
2009年03月25日 星期三 17:04 | 回复
Hi, Albert
看了您的文章,我有些不懂,有几个问题想请教下:
1. 您说:"Binder通信是同步而不是异步"
Binder 通信是进程A发送消息/命令给Binder Kervel后,就被挂起.要等待service manager找到了它所要的service后,让Binder Kernel再叫起进程A,并回复给她所要的service在Kernel中的IBinder对象.
这种需要等待的通信方式,就是您所说的同步吗?
异步方式,是进程发送消息后,可以去做其他的事情,不需要在那里等待消息的回复,是吗?

2.您讲解了进程A 与 服务B 之间的连接,建立连接的部分,我看懂了,可是当进程A 得到Service B 在kernel中的IBinder对象后,他们是怎样进行下一步的通信的,我还没有看明白.不知您是否可以再跟我解释下?(.后面部分,您的文字写的要少些,所以我没看得很明白.)

3.对照源码,看完您的文章,我还是不理解您说的"Binder通信方式的高效率"体现在哪里? 是否可以给我讲个例子或者打个比喻呢?

期待您的回复!Thanks in advance!

May
 
2

blackdeam2
2009年04月11日 星期六 11:15 | 回复
由于前段时间非常忙,没来维护blog。
关于你说的
1:这里需要补充,Binder通讯是可以选择同步还是异步的,通过IBinder对象的transact方法中的flag来设定,如FLAG_ONEWAY异步。 所谓异步就是调用了这个方法后立即返回而不用等待结果。

2: A得到Service B的对象后 其通讯过程和建立连接的时候是一样的,A使用B的Binder对象通过IPCThread与B通讯。 A调用transact后,就通过Binder驱动,进入B进程线程池中然后切换到B的OnTransact方法中。

3:这个高效也是Google说的,具体体现在哪儿,以我的理解是: 与socket 通讯比较,socket通信是通过文件系统封装的,而Binder是通过线程的切换来通讯的。 文件系统的效率应该要低一些吧。 这是我的感觉。
 
3
网友:May
2009年04月16日 星期四 18:30 | 回复
谢谢您的回复.我又懂了一些.呵呵!
不好意思,我还有些疑问想请教您.
1.BpBinder 和 BBinder 都继承了IBinder,
进程A 得到Service B 在kernel中的IBinder对象,您说这个IBinder对象是一个远程的BBinder对象.
进程A会去调用下面的connect连接到Service:
virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient)
    {
        .......       
       remote()->transact(BnCameraService::CONNECT, data, &reply);
        return interface_cast<ICamera>(reply.readStrongBinder());
    }
那这里remote() 应该是一个BBinder对象,remote()->transact()实际上就是调用BBinder::transact(),对吗?
而BBinder::transact 调用了BBinder:onTransact, 因为多态性,实际调用的是BnCameraService::onTransact(),对吗?
 
4

blackdeam2
2009年04月21日 星期二 16:33 | 回复
不完全这样,我们得到的binder 对象其实是在驱动中重新生成的Binder对象,因为对驱动来说他得到的每一个binder对象必须是唯一的,所以你看到的binder实际上是驱动返回的新的binder对象。 当我们的线程得到Service B的binder对象后,在访问的时候会通过IPCThread调用驱动重新获得这个Service B的真正的Binder对象。 这样通过Service B的线程池就切入到真正的处理函数了。  你上面的分析把driver这个过程忽略了。  大体上的原理你是说对了。
 
6
网友:oddstone
2009年07月04日 星期六 12:29 | 回复
由前面的分析可知sm是BpCameraService对象
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
应该是BpServiceManager对象吧
 
7

kikicat0_0
2009年07月14日 星期二 08:58 | 回复
2009-07-04 12:29 | 回复
由前面的分析可知sm是BpCameraService对象
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
应该是BpServiceManager对象吧
=====================================
顶,我也觉得LZ笔误了。到那一步只能是BpServiceManager,直到最后跟Binder做通讯后,得到BBinder,通过interface_case才最终转变成BpCameraService
 
8

blackdeam2
2009年07月15日 星期三 10:31 | 回复
大家看得还是蛮仔细的,这个是我很久以前刚开始做项目的时候弄得,写的有些急,那个地方那个确实得到的是BpServiceManager对象。 错误我会改过来,免得误导人
 
9

kikicat0_0
2009年07月15日 星期三 14:06 | 回复
这偏文章是介绍C++层面的Binder IPC,有没有介绍Java层面的Binder IPC呢?
 
10

blackdeam2
2009年07月15日 星期三 23:23 | 回复
你仔细看看 其实java层面的binder 最终都是call的 c++层面的函数。android_util_binder.cpp定义了一些JNI的接口供java调用,在BinderInternal.java中通过native 函数getContextObject就是得到c++层面的Ibinder对象,所以只要真的理解了c++层面的Binder, java层面不就好理解了吗? java层面无非是又封装了一下, 最终他还是要通过JNI调用c++的函数。     
 
11

kikicat0_0
2009年07月16日 星期四 08:54 | 回复
因为不太确定Java层面是不是只是对从C++层面get到的IBinder对象做一个包裹,还有有没有其他额外的动作。现在LZ这么一说,我了了
很感谢LZ的耐心回复。

对了,有没有AIDL的介绍?貌似跟IPC有关啊
 
12
网友:tt
2009年07月23日 星期四 09:23 | 回复
你好,关于sp这个类别,我看了它的实现,但是一直没看懂,能给我讲解下吗.比如sp<IServiceManager>这些代表什么意思呢,谢谢!
 
13
网友:xdsoftware
2009年07月26日 星期日 14:12 | 回复
您好,我有一点没有后看懂,实在很不好意思,能不能麻烦您稍微提点以下,
哪怕一点点都行,我实在看了很长时间。不好意思。。
1》interface_cast<IServiceManager>(
                ProcessState::self()->getContextObject(NULL)); template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
    return INTERFACE::asInterface(obj);
}
你说的这个宏,为什么展开后就成了那个样子了?
我不知道是不是很浅显的一个问题,但我看了好长时间,都没有弄懂。
 
14
网友:xdsoftware
2009年07月26日 星期日 14:12 | 回复
2》那这里remote() 应该是一个BBinder对象,remote()->transact()实际上就是调用BBinder::transact(),对吗?
而BBinder::transact 调用了BBinder:onTransact, 因为多态性,实际调用的是BnCameraService::onTransact(),对吗?
上面这段话是网友May说的,对么?我在这里其实弄了很长时间,都没有弄懂,他真正的ipc是怎么调用的,

真的可能要占用您已些时间,但真的希望您能稍微提点以下。

谢谢。
 
15

blackdeam2
2009年07月26日 星期日 20:03 | 回复
一:sp是智能指针,你可以把它看成obj的指针对象一样的。  

二:BBinder:onTransact, 因为多态性,实际调用的是BnCameraService::onTransact(), 这个不对,并不是因为多态调用了BnCameraService::onTransactiont,应该是:
通过remote->transact() 通过binder驱动,切换到BnCameraService所在对象的进程然后调用了BnCameraService中的onTransaction函数。
bi
 
16
网友:bluecloudy
2009年07月31日 星期五 17:25 | 回复
你好
前面一个网友问了
1.BpBinder 和 BBinder 都继承了IBinder,
进程A 得到Service B 在kernel中的IBinder对象,您说这个IBinder对象是一个远程的BBinder对象.
我对这个地方有些疑问,还请lz指点一下
前面的代码分析:
服务的注册是通过

CameraService.cpp
void CameraService::instantiate() {
    defaultServiceManager()->addService(
            String16("media.camera"), new CameraService());
}
创建CameraService服务对象并添加到ServiceManager进程中。
而defaultServiceManager()
中生成是一个BpBinder

那Service B 在kernel中的IBinder对象为什么是BBinder而不是BpBinder呢?
 
17

blackdeam2
2009年07月31日 星期五 22:56 | 回复
其实在传递的过程中都只是IBinder指针,这个指针对一个进程来说就像是socket的ID一样,唯一的。所以不管这个IBinder是BBinder还是BpBinder, 他们的都是在重构BpBinder或者BBinder的时候把IBinder作为参数传入。
至于为何添加到serviceMananger中的是BBinder因为对于cameraservice来说
CamerService继承了BnCameraService,而BnCameraService继承了BBinder


继承BBinder与BpBinder的区别:
对于service需要继承BBinder因为service为消息响应所以有OnTransact函数
对于client需要发送消息所以有transact函数 因而继承BpBinder。

camera的client:
当通过defaultServiceManager->getService()取得IBinder对象后,通过
interface_cast<ICameraService>(binder);重构得到了BpCameraService对象,BpCameraService继承了BpBinder所以最后通过binder驱动切入到另一个进程
 
18
网友:niurou
2009年08月05日 星期三 13:38 | 回复
您好!请教一个问题。在得到bpxxxservice之后,要到servicemanage进行注册,注册后成为bnxxxservice,对吗?bp怎么转换为bn的呢?谢谢您
 
19
匿名网友
2009年08月30日 星期日 23:34 | 回复
回复niurou:我不是博主,不过我想我可以回答你的问题。在servicemanager中注册的是一个IBinder对象。客户端请求得到这个IBinder对象,通过interface_cast转换为BpXXXService对象。调用方法的时候就进入这个BpXXXService类的相应方法函数,调用transact,这个函数进入了驱动程序。在服务端的程序会在驱动读到这个请求,把传过来的IBinder对象转化为BnXXXService对象,然后就调用方法的真正实现了。
另外,我也有问题想问问博主,不知道有没有时间回答:
我看了Binder比较长的时间了,有个问题一直困扰我,在Binder中,它的回调是如何实现的。Binder是同步的,在客户端也没有相应的线程来监听。但是我在上层的AIDL编程中确实是可以注册回调的。但是在底层它的机制实现中我却看不到这点。我开始以为是服务端发回调也像客户端发请求一样,它利用客户端的IBinder对象发送请求。但是做了一个实验,没有成功。
 
20

blackdeam2
2009年09月01日 星期二 21:08 | 回复
我在文章中已经说过,使用Binder接口的线程, 就会创建一个线程池,这个线程池也是一个线程,类似于后台运行一样。client 得到了server的remote binder 在通讯的时候通过transact切换到server的线程池(这一步是通过驱动完成的,具体可以看binder driver的源码),通过驱动也找到remote binder在这个server中的本地Binder对象然后传入server的线程池, 一旦切换到server得线程池,server就可以通过ibinder 构造出binder的对象如cameraServcie,然后就调用了OnTransact 函数。
 
21

blackdeam2
2009年09月01日 星期二 21:21 | 回复
明白了binder通讯原理实现客户端与server得双向通讯其实很简单的。 你需要做的是
1: 在Client端 创建一个内部类实现Server的功能
2: Client端将内部类的Ibinder 发送给Server
3: Server记录这个Ibinder
 
22

davidwjx
2010年01月19日 星期二 20:25 | 回复
你好, Albert, 不知道现在问这个问题是不是有些晚哦,看看你这篇blog 最后更新都已经是好几个月前了。汉~~~落后这么多...
由于项目需要,现在我们需要用Java设计一个media player, 这个player 通过jni 调用我们底层的自己的 sdk, 而绕过Android 自带的 MediaPlayerService。实际的情况是我们碰到了一系列的麻烦,比如 AudioSink 该如何创建,怎么样根AudioFlinger 打交道,等等。
(字数限制,未完,待续,sorry...)

 
23

davidwjx
2010年01月19日 星期二 20:27 | 回复
目前我们的方法是直接New 一个 AudioOutput(Declared in MediaPlayerService.h) 对象,试图通过这样的一种方式取得AudioFlinger 的control & management. 实际的情况是,this way cannot work correctly.
然后,在看了你的‘IPC 机制分析 一 二‘, 得到启发需要创建自己的Service, 以达到跟AudioFlinger 交互的目的。 可是在看了service_manager.c 后发现只有
以下
 
24

davidwjx
2010年01月19日 星期二 20:28 | 回复
    { AID_MEDIA, "media.audio_flinger" },
    { AID_MEDIA, "media.player" },
    { AID_MEDIA, "media.camera" },
    { AID_MEDIA, "media.audio_policy" },
    { AID_RADIO, "radio.phone" },
    { AID_RADIO, "radio.sms" },
    { AID_RADIO, "radio.phonesubinfo" },
    { AID_RADIO, "radio.simphonebook" },
    { AID_RADIO, "phone" },
    { AID_RADIO, "isms" },
    { AID_RADIO, "iphonesubinfo" },
    { AID_RADIO, "simphonebook" },
services are permitted to register themselves to ServerManager.
 
25

davidwjx
2010年01月19日 星期二 20:28 | 回复
那就产生了一个疑虑, One User App (*.apk) 以 JNI 的方式可以将自己注册为服务进程吗?我们必须要保证的一点是,把这样的一个app.apk 直接装到它those devices running Cupcake (or Eclair, but not BOTH)就可以work, 那就意味着 we cannot & should not modify and ource of the default android to match this kind of requirements, otherwise the app.apk cannot work correctly on the devices runnnig the default Android. So it's possible for us to design the app.apk with such the way? If no, could you please give any hint or advise to us? ANY clues are appreciated much!

BRs,
David
 
26

blackdeam2
2010年01月26日 星期二 10:26 | 回复
回复davidwjx:blog很久没有更新了,因为时间上的缘故,也因为最近的工作与android无关。09年的大部分时间是在做协议栈,不过很快又要回到android上来了。这里的几篇文章都是当初在学习android的时候自己整理的,所以有些不太正确,很担心理解上的错误会让初学的人,花费更多的时间。
 
27

blackdeam2
2010年01月26日 星期二 10:39 | 回复
回复davidwjx:关于你说想自己设计一个media player是完全可行的,我曾经做了一个很简单的fm radio service,正如你看到的service_manager中代码一样,allowed的结构体是可以添加的,至少我以前用的android1.2是可以的。 所以你可以添加一个属于你自己的service。 有个问题也如你想知道的:如果你添加的JNI的接口不是android 默认的接口,那么你自己的应用如果调用了这些JNI接口,你的应用将无法在其他android device上运行。 但你现在只要重新设计一个java 应用层的media player是否这样?如果是的话,那些底层的东西你不必关注,你只要在自己的应用中声明你需要的native函数就可以了。 如果你想完全重新设计一个media player service的底层解码器,而又想你自己的应用能在不同的device上正常run, 你可以尝试按android默认的audio service接口来porting你的media player service。