系统源码学习之Binder

在这里插入图片描述
Binder类作为Bn端(native) ,BinderProxy 作为客户端的Bp的代表
BinderInternal 仅供Binder框架使用的类,它的内部有一个GcWather 类,该类是处理和Binder相关的垃圾回收的
java层同样提供一个用于承载通信的数据parcel类

在Android 系统中,在java初创时期,系统会提前注册一些JNI函数,通过register_android_os_Binder函数完成了java Binder 架构中最重要的三个类的初始化
Binder ,BinderInternal ,BinderProxy 类,初始化其实就是提前获取一些JNI层的使用信息

通过ActivityManagerService 来分析java层Binder的工作原理
分析步骤:
首先分析AMS如何将自己注册到ServiceManager
然后分析AMS如何响应客户端的Binder调用请求

起点为AMS.setSystemProcess()

public static final String ACTIVITY_SERVICE = "activity";
ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);

将AMS服务添加到ServiceManager中。整个Android系统中只有一个Native的ServiceManager(SM)进程,它统筹管理Android系统上的所有服务,成为一个服务的首要条件是先在SM中注册。

(1)向SM注册服务

public static void addService(String name, IBinder service) {
    
    
    try {
    
    
        getIServiceManager().addService(name, service, false);
    } catch (RemoteException e) {
    
    
        Log.e(TAG, "error in addService", e);
    }
}

首先搞清楚getIServiceManager返回什么?

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

    //调用asInterface ,传递的参数类型IBinder
    sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
    return sServiceManager;
}

参数为:BinderInternal.getContextObject()返回值

public static final native IBinder getContextObject();

getContextObject方法是native函数,获取的是指向Native进程中ServiceManager的BpProxy,但是这个不能由java层直接使用,通过javaObjectForIBinder()函数生成一个BinderProxy对象,并返回。(通过JNI BinderProxy 和native的BpProxy对象挂钩)

static public IServiceManager asInterface(IBinder obj)
{
    
     
    IServiceManager in =
        (IServiceManager)obj.queryLocalInterface(descriptor);
    return new ServiceManagerProxy(obj);
}

最终会调用到ServiceManagerProxy.addService方法

public ServiceManagerProxy(IBinder remote) {
    
    
    mRemote = remote;  //为刚才传入的BinderProxy 参数
}

public void addService(String name, IBinder service, boolean allowIsolated)
        throws RemoteException {
    
    
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IServiceManager.descriptor);
    data.writeString(name);
//下面的writeStrongBinder为特殊函数
    data.writeStrongBinder(service);
    data.writeInt(allowIsolated ? 1 : 0);
//此处调用的是BinderProxy的transact函数,为native函数
    mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
    reply.recycle();
    data.recycle();
}

在onStransact函数中响应,native层的代表是Binder,而ActivityManagerNative继承了Binder
Binder.java

private boolean execTransact(int code, long dataObj, long replyObj,
        int flags) {
    
    
    Parcel data = Parcel.obtain(dataObj);
    Parcel reply = Parcel.obtain(replyObj);
    boolean res;
    try {
    
    
	//派生类可以重新实现这个函数,以完成业务
        res = onTransact(code, data, reply, flags);

ActivityManagerNative继承Binder并重写onTransact方法

public abstract class ActivityManagerNative extends Binder implements IActivityManager
{
    
    
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
        throws RemoteException {
    
    
    switch (code) {
    
    
case START_SERVICE_TRANSACTION: {
    
    
    data.enforceInterface(IActivityManager.descriptor);
    IBinder b = data.readStrongBinder();
    IApplicationThread app = ApplicationThreadNative.asInterface(b);
    Intent service = Intent.CREATOR.createFromParcel(data);
    String resolvedType = data.readString();
    String callingPackage = data.readString();
    int userId = data.readInt();
	//再由ActivityManagerService实现具体的事务
    ComponentName cn = startService(app, service, resolvedType, callingPackage, userId);
    reply.writeNoException();
    ComponentName.writeToParcel(cn, reply);
    return true;
}

(2)理解AIDL
经过上次的分析,已经大致明白了java层Binder的架构,Bp端可以通过BinderProxy的transact()方法与Bn端发送请求,而Bn端通过继承Binder类重写onTransact()接收并处理来自Bp端的请求。实现起来颇为复杂且繁琐,于是Android提供了AIDL语言以及AIDL解释器自动生成一个服务Bn端

定义AIDL文件,IMyServer.aidl,并提供一个可以跨Binder调用的接口foo().通过aidl工具将其解析为一个实现Bn端及Bp端通过Binder进行通信的java源码

interface IMyServer {
    
    
    void foo(String str);
}

在Android studio中Build/Make Project 生成java源码,在目录app/build/generated/aidl_source_output_dir/debug/out目录下

ublic interface IMyserver extends android.os.IInterface
{
    
      //首先IMyserver被解析成一个java接口IMyserver,这个接口定义了AIDL文件中所定义的就口foo
  public static class Default implements com.example.touthdemo.AIDL.IMyserver
  {
    
    
    @Override public void foo(java.lang.String str) throws android.os.RemoteException
    {
    
    
    }
    @Override
    public android.os.IBinder asBinder() {
    
    
      return null;
    }
  }
  //AIDL工具生成一个继承自IMyserver接口的抽象类IMyserver.Stub
  //这个抽象类实现了Bn端通过onTransacet()方法用于接收来自Bp端的请求代码,foo为抽象方法
  //所以aidl工具不知道foo()方法是做什么的,它只能通过onTransact中得知Bp端希望foo方法进行调用,所以Stub是抽象的
  public static abstract class Stub extends android.os.Binder implements com.example.touthdemo.AIDL.IMyserver
  {
    
    
    private static final java.lang.String DESCRIPTOR = "com.example.touthdemo.AIDL.IMyserver";
    /** Construct the stub at attach it to the interface. */
    public Stub()
    {
    
    
      this.attachInterface(this, DESCRIPTOR);
    }
  //根据code数值选择调用IMyserver接口中的不同方法,本例中TRANSACTION_foo 以为这调用foo
    @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_foo:
        {
    
    
          data.enforceInterface(descriptor);
          java.lang.String _arg0;
	//从data中需要读取arg0
          _arg0 = data.readString();
	//Stub类的子类需要实现foo()方法
          this.foo(_arg0);
          reply.writeNoException();
          return true;
        }
        default:
        {
    
    
          return super.onTransact(code, data, reply, flags);
        }
      }
    }
  //AIDL工具生成一个继承IMyServer接口的类proxy,它是Bp端的实现,与Bn端的stub类不同,它实现的了foo()函数,因为foo函数Bp端的实现是确定的,即将参数存储到parcel中,然后执行transact()方法将请求发送到Bn端,然后从reply中读取返回值并返回给调用者。  
private static class Proxy implements com.example.touthdemo.AIDL.IMyserver
    {
    
    
      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;
      }
      @Override public void foo(java.lang.String str) 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(str);
          boolean _status = mRemote.transact(Stub.TRANSACTION_foo, _data, _reply, 0);
          if (!_status && getDefaultImpl() != null) {
    
    
            getDefaultImpl().foo(str);
            return;
          }
          _reply.readException();
        }
        finally {
    
    
          _reply.recycle();
          _data.recycle();
        }
      }
      public static com.example.touthdemo.AIDL.IMyserver sDefaultImpl;
    }
    static final int TRANSACTION_foo = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    public static boolean setDefaultImpl(com.example.touthdemo.AIDL.IMyserver impl) {
    
    
      // Only one user of this interface can use this function
      // at a time. This is a heuristic to detect if two different
      // users in the same process use this function.
      if (Stub.Proxy.sDefaultImpl != null) {
    
    
        throw new IllegalStateException("setDefaultImpl() called twice");
      }
      if (impl != null) {
    
    
        Stub.Proxy.sDefaultImpl = impl;
        return true;
      }
      return false;
    }
    public static com.example.touthdemo.AIDL.IMyserver getDefaultImpl() {
    
    
      return Stub.Proxy.sDefaultImpl;
    }
  }
  public void foo(java.lang.String str) throws android.os.RemoteException;
}

为了实现Bn端的能力,开发者需要继承IMyServer.Stub类并实现抽象方法foo

@Override
public IBinder onBind(Intent intent) {
    
    
    return new MyBinder();
}
private class MyBinder extends IMyserver.Stub {
    
    
    @Override
    public void foo(String str) throws RemoteException {
    
    
        Log.d(TAG, "foo: ");
    }

注意:
为了具有Bn端的能力,典型的做法是将MyServer类的实例通过ServiceManager,addService()添加到系统服务中, 或者在准Service的onBInd()方法中将其作为返回值使之可以被其他进程访问。

那么Bp端将如何使用IMyServer.Proxy的呢?
一旦获取了IMyServer的BinderProxy(通过ServiceManager.getService() , onServiceConnected() 或者其他方式),就可以通过如下方式获得
//binderProxy就是通过ServiceManager.getService获取到的或者在onServiceConnected()中
IMyServer remote = IMyServer.Stub.asInterface(binderProxy);
remote.foo(“”);

final class MyServiceConnection implements ServiceConnection {
    
    
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
    
    
        myServer = (IMyserver) IMyserver.Stub.asInterface(iBinder);
        try {
    
    
            myServer.foo("hahhahaha");
        } catch (RemoteException e) {
    
    
            e.printStackTrace();
        }
    }
    @Override
    public void onServiceDisconnected(ComponentName componentName) {
    
    
    }
}

那么IMserver.Stub.asInterface()实现:
就是创建一个IMServer.Stub.Proxy,其中obj就会被保存为proxy类的mRemote成员

public static com.example.touthdemo.AIDL.IMyserver asInterface(android.os.IBinder obj)
{
    
    
  if ((obj==null)) {
    
    
    return null;
  }
  android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
  if (((iin!=null)&&(iin instanceof com.example.touthdemo.AIDL.IMyserver))) {
    
    
    return ((com.example.touthdemo.AIDL.IMyserver)iin);
  }

  return new com.example.touthdemo.AIDL.IMyserver.Stub.Proxy(obj);
}

猜你喜欢

转载自blog.csdn.net/qq_42447739/article/details/125668085