zoukankan      html  css  js  c++  java
  • Binder机制,从Java到C (3. ServiceManager in Java)

    上一篇 Binder机制,从Java到C (2. IPC in System Service :AMS)  中提到 Application是通过ServiceManager找到了AMS 的service代理对象。那在这个之前当然是要先找到ServiceManager的代理对象,才能调用ServiceManager的服务嘛。下面就看看怎么来获得这个代理对象的吧:

    还记得上一篇调用的ServiceManager的方法吧:IBinder b = ServiceManager.getService("activity");

    那下面就來看一下ServiceManager.getService()是怎样的:
    /frameworks/base/core/java/android/os/ServiceManager.java

     1 public final class ServiceManager {
     2     ...
     3     private static IServiceManager getIServiceManager() {
     4         if (sServiceManager != null) {
     5             return sServiceManager;
     6         }
     7 
     8         // Find the service manager
     9         sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());  (1)
    10         return sServiceManager;
    11     }
    12 
    13     public static IBinder getService(String name) {
    14         try {
    15             IBinder service = sCache.get(name);
    16             if (service != null) {
    17                 return service;
    18             } else {
    19                 return getIServiceManager().getService(name);
    20             }
    21         } catch (RemoteException e) {
    22             Log.e(TAG, "error in getService", e);
    23         }
    24         return null;
    25     }

     说明:

    (1) :根据前两篇的分析,我们可以推測是在BinderInternal.getContextObject()中,找到了ServiceManagerBinderProxy,似乎和前面有些不同。接着看。

    那就接着看BinderInternal.getContextObject()有什麼不同:
    /framework/base/core/java/com/android/internal/os/BinderInternal.java

     1 public class BinderInternal {
     2     ….
     3     public static final native IBinder getContextObject();
     4     ….
     5 }
    

     会getContextObject()是个JNI方法, ServiceManager难道运行在native环境?答案是Yes! ServiceManager确实运行在Native环境。

    继续看,在/framework/base/core/jni/android_util_Binder.cpp找到了对应的方法:

    1 static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
    2  {
    3      sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
    4      return javaObjectForIBinder(env, b); //按照字面意思来看,就是把一个Native层的Binder代理对象转化成Java层的Binder代理对象
    5  }

    这个方法只有两句代码,第一句看着就是找一个IBinder对象啦,然后第二句,就是把一个Native里面的Binder代理对象转化成Java层的Binder代理对象,然后好返回给Java层。

    来看一下第一句代码,在/frameworks/native/libs/binder/ProcessState.cpp里:

    1 sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
    2 {
    3     return getStrongProxyForHandle(0);
    4 }

     里面的这一句代码就暂时先不展开了,不然没完没了了,這里按字面意思也可以看出,是根据一个handle來获得一个Native层的Binder代理对象。而0是一個default值。代表servicemanager的binder handle值。所以这里你给个0,就返回给你servicemanager的Binder代理对象

    那到这里,我們就认为通过BinderInternal.getContextObject(),获得了Native的一個binder 代理对象后,javaObjectForIBinder()会创建一个BinderProxy对象返回到Java层去。
    经过上面的分析,我们可以知道:ServiceManager的Stub端在Native层。ServiceManager的Proxy端在Java层

    结合前面两篇总结一下:
    1. Application通过AMS的static 方法,先得到ServiceManager的BinderProxy。
    2. 然后从ServiceManager获得AMS的BinderProxy,从而可以使用AMS的远程服务方法。
    3. Application通过AMS的远程服务方法,如bindservice(), 將Application Remote Service的BinderProxy提供给Activity,从而Activity可以远程调用这些remote service 的服务。

    现在可以串起来了吧。

  • 相关阅读:
    Notes about "Exploring Expect"
    Reuse Sonar Checkstyle Violation Report for Custom Data Analysis
    Eclipse带参数调试的方法
    MIT Scheme Development on Ubuntu
    Manage Historical Snapshots in Sonarqube
    U盘自动弹出脚本
    hg的常用配置
    Java程序员的推荐阅读书籍
    使用shared memory 计算矩阵乘法 (其实并没有加速多少)
    CUDA 笔记
  • 原文地址:https://www.cnblogs.com/zhangxinyan/p/3487847.html
Copyright © 2011-2022 走看看