Binder核心原理与架构设计-开篇

36 篇文章 0 订阅
16 篇文章 0 订阅

Binder核心原理与架构设计

这篇文章主要分析一下Binder, 我们身边可能有很多做好几年Android 开发的 却对Binder 了解不深,着重于应用层面的开发和API的调用。而现实的开发或者面试如果对Binder了解不深的话可以说很难进入高级工程师的行列。 所以说如果真正对系统底层了解比较深入的话 进程间通信是必知必会的, 就让我们开始吧。

简单一句话Binder是什么, 就是IPC (Inter-Process Communication) 就是进程间通信。

本文分析的源码基于Android-28

由于本文涉及可能设计一些底层的源码, 篇幅可能有那么一丢丢长。
本文主要分以下几个部分展开

  1. 为什么要用多进程
  2. AIDL类的结构分析
  3. 系统服务管理器的简单解析
  4. 总结
  5. 参考资料

1. 为什么要用多进程

了解IPC之前 , 可能会有人说为什么(毛)要用多进程呢, 大家都在一个进程内,多温馨,多和谐?

要回答这个问题,可以很简单的一句话 世界上的操作系统大家都是多进程的,别问为什么 你也用吧。

我觉得主要原因有以下几点:

  1. 不够安全.
    我们知道C或者C++ 可以进行内存的操作。 我们的Java也可以通过反射进行内存的操作。 所谓的外挂,或者修改器 就是基于此原理做成的。
  2. 效率不够高。
    可以深入的理解为,我们都知道一个进程可以有多个线程, 但是只会有一个主线程。当所有的任务都共享这么一个主线程进行切换的话,那么同一时间只会有一个任务处于主线程执行中。 简单来说 那么就会很卡。卡的亲娘也会不认识了。

这种语言叫做AIDL语言 就是我们常说的接口定义语言(Android Interface Define Language), 这个接口定语言,两端声明的aidl文件 ,包名必须一样。 在自己

这个东西是我们Android中基础里边都会的。

那他们是如何进行通信的呢?

2. AIDL类的结构分析

在底层写了个Binder 驱动, 这是提供给系统中不同进程之间进行通信的。 这就类似于我们常见的快递公司。 例如 如果进程A 在北京, 进程B 在上海 , 那么Binder 就像顺丰快递。 如果进程A需要和进程B进行通信, 则需要借助顺丰发送数据,文件。 就相当于两个进程之间的桥梁。 其实就是类似于常见的C/S 架构 。

所有的AIDL接口 都是继承自 IInterface的, 也就是说所有的aidl都是IInterface的子孙, 我们看一下该类的结构 ,分两部分, 一个是Stub,另一个是Proxy 。

所以我们明白了每个aidl 都是用来和Binder进行通信的接口。

Proxy 负责向Binder 发送数据, Proxy 去连接Binder , 告诉Binder 我要调用B进程中的

所有的Stub 是个静态抽象内部类并且继承自Binder 并且实现了 IInterface 接口

我们定义了一个aidl文件作为两个进程通信约定的接口信息

// BinderLearn.aidl
package com.greencheng.android.parent;

// Declare any non-default types here with import statements

interface BinderLearn {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);

    /**
     *  query student score 
     */
    int queryScore(int stuNo, String name );
   /**
    *  testBinder  
    */
    void testBinder(String nameforTest);
}

build之后自动生成一个了BinderLearn.java 也不算长, 一起贴出来分析一下。
为了方便阅读格式化了一下。

/*
 * This file is auto-generated.  DO NOT MODIFY. 文档是自动生成的不要修改 , 我们既然要研究这,当然要修改。 
 * Original file: /androiddev/bindertest/app/src/main/aidl/com/bindertest/BinderLearn.aidl
 */
package com.bindertest;
// Declare any non-default types here with import statements
/ 这个接口就是继承自IInterface ,换句话说系统中所有的基于binder通信的aidl 类的祖师爷都是IInterface

public interface BinderLearn extends android.os.IInterface {
    /**
     * Local-side IPC implementation stub class.
     * 本地端的IPC 实现 , stub class   继承自 Binder类, 实现了其外部类 
     * 这是一个静态抽象内部类 
     */
    public static abstract class Stub extends android.os.Binder implements com.bindertest.BinderLearn {
         这是一个写死的私有的静态常量 descriptor ,内容就是包含包名的类全路径
        private static final java.lang.String DESCRIPTOR = "com.bindertest.BinderLearn";

        /**
         * Construct the stub at attach it to the interface.
         */
        public Stub() {
             把DESCRIPTOR 与Binder 绑定
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an com.bindertest.BinderLearn interface,
         * generating a proxy if needed.
         */
        public static com.bindertest.BinderLearn asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
              先查询本地的接口信息 , 通过 DESCRIPTOR 来查询 
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.bindertest.BinderLearn))) {
                /// 强转返回 
                return ((com.bindertest.BinderLearn) iin);
            }
              如果本地也没有查出来 就直接返回 Proxy对象  
            return new com.bindertest.BinderLearn.Stub.Proxy(obj);
        }

        @Override
        public android.os.IBinder asBinder() {
            return this;
        }

        //  当在A进程中Proxy 调用了mRemote.transact 对应的code值 , 在B进程中的Stub 中的onTransact就会被回调。  根据code 类型分别进入要执行的代码。  通过 reply 需要返回的数据信息 , 写回异常。 
        @Override
        public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
            java.lang.String descriptor = DESCRIPTOR;
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(descriptor);
                    return true;
                }
                case TRANSACTION_basicTypes: {
                    data.enforceInterface(descriptor);
                    int _arg0;
                    _arg0 = data.readInt();
                    long _arg1;
                    _arg1 = data.readLong();
                    boolean _arg2;
                    _arg2 = (0 != data.readInt());
                    float _arg3;
                    _arg3 = data.readFloat();
                    double _arg4;
                    _arg4 = data.readDouble();
                    java.lang.String _arg5;
                    _arg5 = data.readString();
                    this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);
                    reply.writeNoException();
                    return true;
                }
                case TRANSACTION_queryScore: {
                     校验接口数据
                    data.enforceInterface(descriptor);
                    int _arg0;
                    _arg0 = data.readInt();
                    java.lang.String _arg1;
                    _arg1 = data.readString();
                    /// 读取数据, 调用queryScore方法,并且返回
                    int _result = this.queryScore(_arg0, _arg1);
                    reply.writeNoException();
                    reply.writeInt(_result);
                    return true;
                }
                case TRANSACTION_testBinder: {
                    data.enforceInterface(descriptor);
                    java.lang.String _arg0;
                    _arg0 = data.readString();
                    this.testBinder(_arg0);
                    reply.writeNoException();
                    return true;
                }
                default: {
                    return super.onTransact(code, data, reply, flags);
                }
            }
        }
        
       /**
        *  私有静态内部类 实现了 BinderLearn接口 ,  实现了aidl中定义的方法。 
        */
        private static class Proxy implements com.bindertest.BinderLearn {
            private android.os.IBinder mRemote;

            Proxy(android.os.IBinder remote) {
                mRemote = remote;
            }

            @Override
            public android.os.IBinder asBinder() {
                return mRemote;
            }

            public java.lang.String getInterfaceDescriptor() {
                return DESCRIPTOR;
            }

            /**
             * Demonstrates some basic types that you can use as parameters
             * and return values in AIDL.
             */
            @Override
            public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeInt(anInt);
                    _data.writeLong(aLong);
                    _data.writeInt(((aBoolean) ? (1) : (0)));
                    _data.writeFloat(aFloat);
                    _data.writeDouble(aDouble);
                    _data.writeString(aString);
                    mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            /// 查询分数
            @Override
            public int queryScore(int stuNo, java.lang.String name) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                //  发送  Parcel 内部维护了一个池对象 , 
                android.os.Parcel _reply = android.os.Parcel.obtain();
                ///   回复消息 , 由 Parcel中的池对象生成 。 
                
                int _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeInt(stuNo);
                    _data.writeString(name);
                     mRemote.transact  调用发送信息 注意这里的TRANSACTION_queryScore 传递的是需要调用的code int类型 。 
                    mRemote.transact(Stub.TRANSACTION_queryScore, _data, _reply, 0);
                    
                    _reply.readException();
                    _result = _reply.readInt();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            @Override
            public void testBinder(java.lang.String nameforTest) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(nameforTest);
                      mRemote.transact  调用发送信息 注意这里的TRANSACTION_testBinder 传递的是需要调用的code int类型 。 
                    mRemote.transact(Stub.TRANSACTION_testBinder, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
        }

        static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_queryScore = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
        static final int TRANSACTION_testBinder = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
        
          这里声明的常量值 为First_call_transation   + 0  , 1, 2, 就是方法在类中的声明顺序。
    }

    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException;

    public int queryScore(int stuNo, java.lang.String name) throws android.os.RemoteException;

    public void testBinder(java.lang.String nameforTest) throws android.os.RemoteException;
}

以上是整个自动生成的BinderLearn类

    /**
     * Convenience method for associating a specific interface with the Binder.
     * After calling, queryLocalInterface() will be implemented for you
     * to return the given owner IInterface when the corresponding
     * descriptor is requested.
     */
    public void attachInterface(@Nullable IInterface owner, @Nullable String descriptor) {
        mOwner = owner;
        mDescriptor = descriptor;
    }

调用父类Binder类的attachInterface方法, 将 owner和 descriptor 存储为父类的全局变量。

看一下Binder通信的简单流程图:
在这里插入图片描述
这里有两个进程, 进程A和进程B,同时声明了BinderLearn.aidl 生成的类结构上边分析清楚了。
与底层注册 进程A和进程B在注册过程中通过构造函数关联和aidl.asInterface 进程底层Binder的注册。
进程A和进程B之间数据通信。 A和B可以看做A是Client, B进程是Server。

进程A和进程B中的Stub 属于接受来自底层Binder引用的调用,在 onTransact中 根据调用方法编号进行处理。 如果需要回调或者返回值,通过底层Binder引用调用进程B的mRemote.XX方法。

3. 系统服务管理器的简单解析

我们知道我们的系统中有很多应用进程, 例如微信、QQ、支付宝、微博、等等这么多的系统进程都是要使用系统提供的Service的, 也就是说是需要跨进程调用的。
稍等一秒钟,我们思考一下,为什么不把每个应用进程需要使用到的Service 放到每个应用进程中呢?

  1. 假如说微信、QQ、支付宝 在发消息的时候 需要输入法、 这时候如果每个应用进程都打开一个输入法,会很好性能。 如果一个应用使用了很多种系统服务,如果同时都打开的话会造成大量系统资源的浪费。 于是我们静静地思考了一下,嗯、嗯 、确实没有输入法同一个手机里同一时间打开多个的情况(分屏机制除外)。
  2. 另外再考虑一下,假如说微信、QQ 、支付宝 都打开了输入法, 如果一个进程修改过输入法,导致了另一个进程使用时候的信息泄露的话,会发生系统性风险。

所以说Binder机制的跨进程是Android系统的基石毫不为过。

再来一张两千万的图:
在这里插入图片描述
我们看图中以Binder底层机制为基础之上的, 一系列系统级服务,由SystemService进行注册绑定,提供给应用层各个进程使用, 在源码中或者在我们日常开发中 常用的Context.getSystemService(xxxx)。

我们简单看一下Context结构,
在这里插入图片描述
Context 是个抽象类,包含了系统中使用的各种方法,包括获取MainLooper, contentResolver, packageManager 等等。

ContextWrapper 继承自Context , 为什么这么设计的呢, 看一下注释

/**
 * Proxying implementation of Context that simply delegates all of its calls to
 * another Context.  Can be subclassed to modify behavior without changing
 * the original Context.
 在这里这个类做了一个简单的代理 实现的方法和Context 一样 。 只是委托给了其他对象。 
 */
public class ContextWrapper extends Context {
    Context mBase;

    public ContextWrapper(Context base) {
        mBase = base;
    }
    
    /**
     * Set the base context for this ContextWrapper.  All calls will then be
     * delegated to the base context.  Throws
     * IllegalStateException if a base context has already been set.
     * 
     * @param base The new base context for this wrapper.
     */
    protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }

    /**
     * @return the base context as set by the constructor or setBaseContext
     */
    public Context getBaseContext() {
        return mBase;
    }
}

查一下源码不难发现 真正实现了Context的类是ContextImpl , 看名字就知道这哥们儿就是实现了Context ContextImpl.java 中包含了 ReceiverRestrictedContext 和 ContextImpl类, ReceiverRestrictedContext这个类继承自ContextWrapper , 用于注册广播接收者, 当然其具体的调用囊括在了ContextImpl 的getReceiverRestrictedContext方法中。

在ContextImpl中我们找到了获取系统方法的Context.getSystemService(xxxx),
代码如下:

 @Override
    public Object getSystemService(String name) {
        return SystemServiceRegistry.getSystemService(this, name);
    }

    @Override
    public String getSystemServiceName(Class<?> serviceClass) {
        return SystemServiceRegistry.getSystemServiceName(serviceClass);
    }

再看一下SystemServiceRegistry中的实现 。
在静态代码块中注册了一系列服务

static{

    registerService(Context.ACTIVITY_SERVICE, ActivityManager.class,
            new CachedServiceFetcher<ActivityManager>() {
        @Override
        public ActivityManager createService(ContextImpl ctx) {
            return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
        }});

    registerService(Context.ALARM_SERVICE, AlarmManager.class,
            new CachedServiceFetcher<AlarmManager>() {
        @Override
        public AlarmManager createService(ContextImpl ctx) throws ServiceNotFoundException {
            IBinder b = ServiceManager.getServiceOrThrow(Context.ALARM_SERVICE);
            IAlarmManager service = IAlarmManager.Stub.asInterface(b);
            return new AlarmManager(service, ctx);
        }});
}

/**
 * Creates an array which is used to cache per-Context service instances.
 */
public static Object[] createServiceCache() {
    return new Object[sServiceCacheSize];
}

/**
 * Gets a system service from a given context.
 */
public static Object getSystemService(ContextImpl ctx, String name) {
    ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
    return fetcher != null ? fetcher.getService(ctx) : null;
}

/**
 * Gets the name of the system-level service that is represented by the specified class.
 */
public static String getSystemServiceName(Class<?> serviceClass) {
    return SYSTEM_SERVICE_NAMES.get(serviceClass);
}

/**
 * Statically registers a system service with the context.
 * This method must be called during static initialization only.
  
 */
private static <T> void registerService(String serviceName, Class<T> serviceClass,
        ServiceFetcher<T> serviceFetcher) {
    SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
    SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
}

/**
 * Base interface for classes that fetch services.
 * These objects must only be created during static initialization.
 */
static abstract interface ServiceFetcher<T> {
    T getService(ContextImpl ctx);
}

/**
 * Override this class when the system service constructor needs a
 * ContextImpl and should be cached and retained by that context.
 */
static abstract class CachedServiceFetcher<T> implements ServiceFetcher<T> {
    private final int mCacheIndex;

    CachedServiceFetcher() {
        // Note this class must be instantiated only by the static initializer of the
        // outer class (SystemServiceRegistry), which already does the synchronization,
        // so bare access to sServiceCacheSize is okay here.
        mCacheIndex = sServiceCacheSize++;
    }

    @Override
    @SuppressWarnings("unchecked")
    public final T getService(ContextImpl ctx) {
        final Object[] cache = ctx.mServiceCache;
        final int[] gates = ctx.mServiceInitializationStateArray;

        for (;;) {
            boolean doInitialize = false;
            synchronized (cache) {
                // Return it if we already have a cached instance.
                T service = (T) cache[mCacheIndex];
                if (service != null || gates[mCacheIndex] == ContextImpl.STATE_NOT_FOUND) {
                    return service;
                }

                // If we get here, there's no cached instance.

                // Grr... if gate is STATE_READY, then this means we initialized the service
                // once but someone cleared it.
                // We start over from STATE_UNINITIALIZED.
                if (gates[mCacheIndex] == ContextImpl.STATE_READY) {
                    gates[mCacheIndex] = ContextImpl.STATE_UNINITIALIZED;
                }

                // It's possible for multiple threads to get here at the same time, so
                // use the "gate" to make sure only the first thread will call createService().

                // At this point, the gate must be either UNINITIALIZED or INITIALIZING.
                if (gates[mCacheIndex] == ContextImpl.STATE_UNINITIALIZED) {
                    doInitialize = true;
                    gates[mCacheIndex] = ContextImpl.STATE_INITIALIZING;
                }
            }

            if (doInitialize) {
                // Only the first thread gets here.

                T service = null;
                @ServiceInitializationState int newState = ContextImpl.STATE_NOT_FOUND;
                try {
                    // This thread is the first one to get here. Instantiate the service
                    // *without* the cache lock held.
                    service = createService(ctx);
                    newState = ContextImpl.STATE_READY;

                } catch (ServiceNotFoundException e) {
                    onServiceNotFound(e);

                } finally {
                    synchronized (cache) {
                        cache[mCacheIndex] = service;
                        gates[mCacheIndex] = newState;
                        cache.notifyAll();
                    }
                }
                return service;
            }
            // The other threads will wait for the first thread to call notifyAll(),
            // and go back to the top and retry.
            synchronized (cache) {
                while (gates[mCacheIndex] < ContextImpl.STATE_READY) {
                    try {
                        cache.wait();
                    } catch (InterruptedException e) {
                        Log.w(TAG, "getService() interrupted");
                        Thread.currentThread().interrupt();
                        return null;
                    }
                }
            }
        }
    }

    public abstract T createService(ContextImpl ctx) throws ServiceNotFoundException;
}

private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES = new HashMap<Class<?>, String>();
private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS = new HashMap<String, ServiceFetcher<?>>();
private static int sServiceCacheSize;
    
    

在SYSTEM_SERVICE_NAMES 和 SYSTEM_SERVICE_FETCHERS 一个是保存了Service Name , 一个 保存了ServiceFetchers。
我们看一下 CachedServiceFetcher , 这个类就是实现了ServiceFetcher接口,
在getService 方法中会循环在Cache中找到对应的service index 找到对应的Service。 当然如果没有找到的话 就调用createService 。
这个实现就为代码结构留足了空间。 不同的Service 有不同的create方式。
举个栗子

  new CachedServiceFetcher<ActivityManager>() {
            @Override
            public ActivityManager createService(ContextImpl ctx) {
                return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
            }}

不解释,是不是很简单。
对了 创建系统Service缓存的方法是这个

 /**
     * Creates an array which is used to cache per-Context service instances.
     */
    public static Object[] createServiceCache() {
        return new Object[sServiceCacheSize];
    }
 

调用时机在ContextImpl

    // The system service cache for the system services that are cached per-ContextImpl.
    final Object[] mServiceCache = SystemServiceRegistry.createServiceCache();

想了一会儿, 是不是感觉少了点什么,系统的一系列Service通过SystemService 注册到了binder驱动中,并且缓存在了数组中。 那么SystemService是如何被注册的呢?


/**
 * Basic interface for finding and publishing system services.
 *
 * An implementation of this interface is usually published as the
 * global context object, which can be retrieved via
 * BinderNative.getContextObject().  An easy way to retrieve this
 * is with the static method BnServiceManager.getDefault().
 *
 * @hide
 */
public interface IServiceManager extends IInterface
{
    /**
     * Retrieve an existing service called @a name from the
     * service manager.  Blocks for a few seconds waiting for it to be
     * published if it does not already exist.
     */
    IBinder getService(String name) throws RemoteException;

    /**
     * Retrieve an existing service called @a name from the
     * service manager.  Non-blocking.
     */
    IBinder checkService(String name) throws RemoteException;

    /**
     * Place a new @a service called @a name into the service
     * manager.
     */
    void addService(String name, IBinder service, boolean allowIsolated, int dumpFlags)
            throws RemoteException;

    /**
     * Return a list of all currently running services.
     */
    String[] listServices(int dumpFlags) throws RemoteException;

    /**
     * Assign a permission controller to the service manager.  After set, this
     * interface is checked before any services are added.
     */
    void setPermissionController(IPermissionController controller)
            throws RemoteException;

    static final String descriptor = "android.os.IServiceManager";
}

哎呀 我去 这不就是aidl 定义的那个最根儿上的接口吗? 由于篇幅限制精简的 。
我们找到了这个接口的Stub 类 ServiceManagerNative 继承自Binder 实现了 IServiceManager ,当然里边也有Proxy哥们儿。

/**
 * Native implementation of the service manager.  Most clients will only
 * care about getDefault() and possibly asInterface().
 * @hide
 */
public abstract class ServiceManagerNative extends Binder implements IServiceManager
{
    /**
     * Cast a Binder object into a service manager interface, generating
     * a proxy if needed.
     */
    static public IServiceManager asInterface(IBinder obj)
    {
        if (obj == null) {
            return null;
        }
        IServiceManager in =
            (IServiceManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        return new ServiceManagerProxy(obj);
    }

    public ServiceManagerNative()
    {
        attachInterface(this, descriptor);
    }

    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
    {
        try {
            switch (code) {
                case IServiceManager.GET_SERVICE_TRANSACTION: {
                    data.enforceInterface(IServiceManager.descriptor);
                    String name = data.readString();
                    IBinder service = getService(name);
                    reply.writeStrongBinder(service);
                    return true;
                }

                case IServiceManager.CHECK_SERVICE_TRANSACTION: {
                    data.enforceInterface(IServiceManager.descriptor);
                    String name = data.readString();
                    IBinder service = checkService(name);
                    reply.writeStrongBinder(service);
                    return true;
                }

                case IServiceManager.ADD_SERVICE_TRANSACTION: {
                    data.enforceInterface(IServiceManager.descriptor);
                    String name = data.readString();
                    IBinder service = data.readStrongBinder();
                    boolean allowIsolated = data.readInt() != 0;
                    int dumpPriority = data.readInt();
                    addService(name, service, allowIsolated, dumpPriority);
                    return true;
                }

                case IServiceManager.LIST_SERVICES_TRANSACTION: {
                    data.enforceInterface(IServiceManager.descriptor);
                    int dumpPriority = data.readInt();
                    String[] list = listServices(dumpPriority);
                    reply.writeStringArray(list);
                    return true;
                }

                case IServiceManager.SET_PERMISSION_CONTROLLER_TRANSACTION: {
                    data.enforceInterface(IServiceManager.descriptor);
                    IPermissionController controller =
                            IPermissionController.Stub.asInterface(
                                    data.readStrongBinder());
                    setPermissionController(controller);
                    return true;
                }
            }
        } catch (RemoteException e) {
        }

        return false;
    }

    public IBinder asBinder()
    {
        return this;
    }
}

class ServiceManagerProxy implements IServiceManager {
    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;
    }

    public IBinder asBinder() {
        return mRemote;
    }

    public IBinder getService(String name) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
        IBinder binder = reply.readStrongBinder();
        reply.recycle();
        data.recycle();
        return binder;
    }

    public IBinder checkService(String name) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        mRemote.transact(CHECK_SERVICE_TRANSACTION, data, reply, 0);
        IBinder binder = reply.readStrongBinder();
        reply.recycle();
        data.recycle();
        return binder;
    }

    public void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority)
            throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        data.writeStrongBinder(service);
        data.writeInt(allowIsolated ? 1 : 0);
        data.writeInt(dumpPriority);
        mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
        reply.recycle();
        data.recycle();
    }

    public String[] listServices(int dumpPriority) throws RemoteException {
        ArrayList<String> services = new ArrayList<String>();
        int n = 0;
        while (true) {
            Parcel data = Parcel.obtain();
            Parcel reply = Parcel.obtain();
            data.writeInterfaceToken(IServiceManager.descriptor);
            data.writeInt(n);
            data.writeInt(dumpPriority);
            n++;
            try {
                boolean res = mRemote.transact(LIST_SERVICES_TRANSACTION, data, reply, 0);
                if (!res) {
                    break;
                }
            } catch (RuntimeException e) {
                // The result code that is returned by the C++ code can
                // cause the call to throw an exception back instead of
                // returning a nice result...  so eat it here and go on.
                break;
            }
            services.add(reply.readString());
            reply.recycle();
            data.recycle();
        }
        String[] array = new String[services.size()];
        services.toArray(array);
        return array;
    }

    public void setPermissionController(IPermissionController controller)
            throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeStrongBinder(controller.asBinder());
        mRemote.transact(SET_PERMISSION_CONTROLLER_TRANSACTION, data, reply, 0);
        reply.recycle();
        data.recycle();
    }

    private IBinder mRemote;
}

这里的方法就不再一一看了,我们大概明白了SystemService 这哥们儿也是个AIDL 进程间通信 ,也是通过了Binder驱动注册在系统内的。 这也为SystemService管理系统的一系列service 提供了基础。

  1. 从ServiceManagerNative,可以看到,它也是一个抽象类,继承Binder,实现IServiceManager接口。于是它必然会实现asInterface()、asBinder()等Binder所需要的接口方法。但因为它本质上只是起到Proxy作用,作为一个抽象类,它并不可能被实例化,除非有一个非抽象类继承它并实现它所缺少的方法。这种实现在代码层面上没有意义,我们从后面的分析servicemanager的Native实现时也可以看得出来,于是我们虽然看到了onTransact()实现,但实际上它不起作用。

  2. 这是整个ServiceManagerNative类实现的最有意义的一行。虽然这一行与其他基于IBinder实现的远程类没什么不同,但这一行提供了Proxy接口,这个Proxy接口,则是其他System Service所需要的访问接口。在ServiceManagerNative类的asInterface()方法里,我们会创建并返回一个Proxy对象ServiceManagerPoxy。

  3. ServiceManagerProxy对象里实现就没什么特殊之处了。跟会通过Binder访问到Remote Service的其他远程方法一样,会将本地需要调用的方法,将方法名与参数打包,将得到的命令通过Binder发送出去,然后再等着远程执行的返回。

/**
 * Private and debugging Binder APIs.
 * 
 * @see IBinder
 */
public class BinderInternal {
    private static final String TAG = "BinderInternal";
    
     /**
     * Return the global "context object" of the system.  This is usually
     * an implementation of IServiceManager, which you can use to find
     * other services.
     * 获取系统全局的global Context 
     */
    public static final native IBinder getContextObject();
    
}

public final class ServiceManager {
    private static final String TAG = "ServiceManager";

    private static IServiceManager sServiceManager;
    private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();

    private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }

        // Find the service manager
        sServiceManager =ServiceManagerNative.asInterface(BinderInternal.getContextObject());
        /// 通过ServiceManagerNative
        return sServiceManager;
    }
}

通过BinderInternal.getContextObject() 获取IBinder , 同时ServiceManagerNative 调用 asInterface 创建sServiceManager。 同时ServiceManager 对于系统中的各种服务,统一由SystemService 进行统一管理。当然其中包含了输入法。

4. 总结

网上的大神很多,按理来说实在轮不到我来写Binder这样偏底层的文章。 也实在不敢班门弄斧,但是学的东西比较多,比较杂,如果长时间不整理一下,不总结一下 就会还回去了。 如果有写不对的地方,欢迎大家批评指正。

5. 参考资料

  1. 任玉刚的Android开发艺术探索 Binder 相关章节
  2. Android系统源码
  3. 罗升阳blog

由于篇幅限制,我们下篇见。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值