您的位置:首页 > 其它

Binder杂谈——getSystemService

2015-05-19 18:58 393 查看
Client想要播放Audio,首先要获得AudioManager,如下方式:接下来就一步步分析

mAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE);//2.1分析

           mAudioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
AudioManager.ADJUST_LOWER,

                     AudioManager. FLAG_PLAY_SOUND|AudioManager. FLAG_SHOW_UI);//2.3分析

1
getSystemService()@ContextImple.java
public Object getSystemService(String name) {

        ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);

        return fetcher == null ? null : fetcher.getService(this);

    }
SYSTEM_SERVICE_MAP是盛装string 和 ServiceFetcher的HashMap
HashMap<String, ServiceFetcher> SYSTEM_SERVICE_MAP
那就是通过String可以找到相关ServiceFethcher。
在ContextImpl.java的静态代码装得知,这个SYSTEM_SERVICE Map是这里put.
static
{
...
registerService(AUDIO_SERVICE, new ServiceFetcher() {

                public Object createService(ContextImpl ctx) {

                    return new AudioManager(ctx);//得到AudioManager的实例

                }});
...
}

private static void registerService(String serviceName, ServiceFetcher fetcher) {

     ...

     SYSTEM_SERVICE_MAP.put(serviceName, fetcher);

}
由上可知:getSystemService(string),主要是通过string查找HashMap找到AudioManager的实例。其实是得到SystemFetcher,所以需要(AudioManager)强制转换一下。
string AUDIO_SERVICE 是与 AudioService是使用同一个名字,但是一个是实例AudioManager
,另外一个是实例化AudioService
SystemServer.java
erviceManager.addService(Context.AUDIO_SERVICE, new AudioService(context));

2 AudioManager.java
AudioManager构造函数没有做什么实际工作,仅是构造对象。

3mAudioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_LOWER, AudioManager.FLAG_PLAY_SOUND|AudioManager.FLAG_SHOW_UI)
=>

service.adjustStreamVolume(streamType, direction, flags,
                        mContext.getOpPackageName());
这里肯定是通过binder通讯调到AudioService.java里面adjustStreamVolume函数,今天不解释函数逻辑,深扒是如何通过binder通讯与AudioService这个进程(暂且讲是进程)通信的。

其中service在函数开始赋值,是一个IAudioService接口
 IAudioService service = getService();
=>

    private static IAudioService getService()
    {
...
        IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);//part1
        sService = IAudioService.Stub.asInterface(b);//part2
        return sService;
    }
在系统中,Client与ServiceManager通讯也是一种Binder通讯。如下图:



先来看part1
 ServiceManager.getService(Context.AUDIO_SERVICE);

=>
public static IBinder getService(String name) {

...

                return getIServiceManager().getService(name);

...

    }
=>先看getIServiceManager(),这是获取ServiceManager的过程。
    private static IServiceManager getIServiceManager() {

...

        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());

        return sServiceManager;

    }

BinderInternal.getContextObject()红色字体的函数可以置换为new BpBinder(0);所以返回的是一个IBinder类型。不信,那么就深入
=>
getContextObject()@BinderInternal.java这是一个Native函数
public static final native IBinder getContextObject();
=>getContextObject@android_util_Binder.cpp
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)

{

    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);

    return javaObjectForIBinder(env, b);

}
=>
调用ProcessState::self()的getContextObject(NULL);其中self()是返回ProcessState的实例,这里是一个单例模式,不深入究,但要注意的是,这里会去打开驱动 /dev/binder,并映射mmap BINDER_VM_SIZE(2M-8k)的size到进程空间。这是跨进程通信的基础。
直接看函数getContextObject;
=>keep dig
getContextObject@ProcessState.cpp
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)

{

    return getStrongProxyForHandle(0);

}

=>
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)

{

...

            if (handle == 0) {

                Parcel data;

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

                        0, IBinder::PING_TRANSACTION, data, NULL, 0);//这里会调用waitForResponse->talkWithDirver()来与BinderDrive通讯。
...

            }

            b = new BpBinder(handle); //看到没,这个b最终返回给上层上去。所以,BinderInternal.getContextObject()红色字体的函数可以置换为new BpBinder(0) 

...

        }
终于出栈了,回到我们入栈的地方

    private static IServiceManager getIServiceManager() {

...

        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());

        return sServiceManager;

    }

其实,我们可以再深入一点,new BpBinder(0);其中handle=0 做了什么事?

BpBinder.cpp

BpBinder::BpBinder(int32_t handle)

    : mHandle(handle) //mHandle=0,有什么用?先放在这

    , mAlive(1)

    , mObitsSent(0)

    , mObituaries(NULL)

{

    extendObjectLifetime(OBJECT_LIFETIME_WEAK);

    IPCThreadState::self()->incWeakHandle(handle);

}

 
接下来,继续看ServiceManagerNativi.asInterface(new BpBinder(0));//这是在Java层

 static public IServiceManager asInterface(IBinder obj)
    {
...
        return new ServiceManagerProxy(obj);//return new ServiceManagerProxy(new BpBinder(0));
    }
=>

    public ServiceManagerProxy(IBinder remote) {

        mRemote = remote;//mRemote = new BpBinder(0);

    }

还是在part1,
getIServiceManager().getService(name);
我们分析了前半部getIServiceManager,返回的是一个new BpBinder(0);并赋给mRemote;这我们就拿到ServiceManager的代理。
接下来getServie(name);即在ServiceManagerNative.java中调用
 public IBinder getService(String name) throws RemoteException {
...
mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);//调用的就不BpBinder.transact()
...
}

=>BpBinder.cpp
status_t BpBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
...
        status_t status = IPCThreadState::self()->transact(
            mHandle, code, data, reply, flags);//mHandle就是在new BpBinder那里赋值的,即为0
...
}
=>直接看IPCThreadState.cpp
status_t IPCThreadState::transact(int32_t handle,

                                  uint32_t code, const Parcel& data,

                                  Parcel* reply, uint32_t flags)

{
...
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
     ->把一些传输用的数据写进mOut这个Parcel
...
err = waitForResponse(reply);
     ->调用talkWithDriver();
     ->使用mOut 打包好的数据与BinderDriver通讯;并把返回值写到reply,用来获取传输的状态正确与否
...

}
这样在Clinet端要做的工作基本完成了,接下来就是Server端也是与Driver通讯,拿到Client传输过来的命令和data,然后做相应的处理。

接下来看ServiceManager的Server端
是由这里启动的init.rc,这是native service
451 service servicemanager /system/bin/servicemanager                                                                                                          

452     class core

453     user system

454     group system

455     critical

456     onrestart restart healthd

457     onrestart restart zygote

458     onrestart restart media

459     onrestart restart surfaceflinger

460     onrestart restart drm

service_manager.c

int main(int argc, char **argv)

{

...
    bs = binder_open(128*1024);//这里打开/dev/binder,并mmap 128K的内核空间到进程空间 

...

    svcmgr_handle = svcmgr;

    binder_loop(bs, svcmgr_handler);

    return 0;

}

在binder_loop会去与driver通信,并是一个for(;;)死循环处理。读取相关信息,并交由svcmgr_handler做进一步处理,那来看看svcmgr_handler
int svcmgr_handler(struct binder_state *bs,

                   struct binder_txn *txn,

                   struct binder_io *msg,

                   struct binder_io *reply)

{

 ...

    case SVC_MGR_GET_SERVICE:

    case SVC_MGR_CHECK_SERVICE://请相信我,getSrvice()会走到这里来,真的。不相信?那就要分析Binder驱动了,请参考红茶哥的分析,对Binder部分分析相当到位:http://my.oschina.net/youranhongcha/blog/152233

        s = bio_get_string16(msg, &len);

        ptr = do_find_service(bs, s, len, txn->sender_euid);

        if (!ptr)

            break;

        bio_put_ref(reply, ptr);//处理后,把结果写到reply

        return 0;

...

    return 0;

}

看到没,就这样完成一次通信。

有几个疑问?有些已经有答案,有些还没有?

servicemanager的Server端,mmap是128k,但其它服务或者client使用都是mmap 2M-4K?

who help me?
在Java层,为什么需要定义一个接口文件(比较IActivityManager.java)?

答:a,接口的核心作用即规范,Srever端和Client端全部要implents这个接口ActivityManagerNative implemetns IActivityManager;  ActivityManagerService extends ActivityManagerNative,相当于实现了接口;

b,这个接口(IActivityManager)implements IInterface,使用了asBinder函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: