美文网首页
Binder机制

Binder机制

作者: patient烽 | 来源:发表于2020-01-07 16:48 被阅读0次

    Binder

    • Binder是什么?
      进程间通讯机制

      Binder 共享内存 Socket
      性能 需要拷贝一次 无需拷贝 需要拷贝两次
      特点 基于C/S 架构易用性高 控制复杂,易用性差 (同一块空间,修改了数据了之后,可能导致数据不同步,数据的同步机制可能会导致死锁等问题,开销大) 基于C/S 架构作为一款通用接口,其传输效率低,开销大
      安全性 为每个APP分配UID 依赖上层协议<br />访问接入点是开放的 依赖上层协议<br />访问接入点是开放的
    Binder传输数据.png
    • 什么时候需要用到进程间通信

      项目比较大型的时候

    • 为什么要多进程?
      虚拟机分配给各个进程的内存是有限制的,如果需要用到内存消耗大的功能的时候,主进程的容量会耗尽,容易导致OOMs

    1.png

    AIDL使用

    定义一个AIDL文件,IPersonAidl.aidl,系统会编译生成IPersonAidl.java

    interface ILeoAidl {
      void addPerson(in Person person);
    
      List<Person> getPersonList();
    }
    
    • 客户端获取AIDL的遥控器
    //获取aidl对象的方法
    private ServiceConnection connection = new ServiceConnection() {
      @Override
      public void onServiceConnected(ComponentName name, IBinder service) {
        //IPersonAidl为定义IPersonAidl.aidl文件自动生成的java文件
        iPersonAidl = IPersonAidl.Stub.asInterface(service);
      }
    
      @Override
      public void onServiceDisconnected(ComponentName name) {
        iPersonAidl = null;
      }
    };
    

    客户端:

    分析生成的IPersonAidl.java中Proxy的方法,用来发送数据给服务端

    private static class Proxy implements com.xx.leo_service.ILeoAidl {
        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 addPerson(com.xx.leo_service.Person person) throws android.os.RemoteException {
            android.os.Parcel _data = android.os.Parcel.obtain();
            android.os.Parcel _reply = android.os.Parcel.obtain();
            try {
                _data.writeInterfaceToken(DESCRIPTOR);
                if ((person != null)) {
                    _data.writeInt(1);
                    person.writeToParcel(_data, 0);
                } else {
                    _data.writeInt(0);
                }
                mRemote.transact(Stub.TRANSACTION_addPerson, _data, _reply, 0);
                _reply.readException();
            } finally {
                _reply.recycle();
                _data.recycle();
            }
        }
    
        @Override
        public java.util.List<com.xx.leo_service.Person> getPersonList() throws android.os.RemoteException {
          //发送到服务端的数据 
            android.os.Parcel _data = android.os.Parcel.obtain();
         // 服务端返回的数据
            android.os.Parcel _reply = android.os.Parcel.obtain();
            java.util.List<com.xx.leo_service.Person> _result;
            try {
              //校验是否是当前服务
                _data.writeInterfaceToken(DESCRIPTOR);
              //然后服务端就会调用onTransact()
                mRemote.transact(Stub.TRANSACTION_getPersonList, _data, _reply, 0);
                _reply.readException();
                _result = _reply.createTypedArrayList(com.xx.leo_service.Person.CREATOR);
            } finally {
                _reply.recycle();
                _data.recycle();
            }
            return _result;
        }
    }
    

    Binder#transact

    public class Binder{
      /**
     * Default implementation rewinds the parcels and calls onTransact.  On
     * the remote side, transact calls into the binder to do the IPC.
     */
        public final boolean transact(int code, Parcel data, Parcel reply,
            int flags) throws RemoteException {
        if (false) Log.v("Binder", "Transact: " + code + " to " + this);
        if (data != null) {
            data.setDataPosition(0);
        }
        //会调用onTransact()
        boolean r = onTransact(code, data, reply, flags);
        if (reply != null) {
            reply.setDataPosition(0);
        }
        return r;
        }
    }
    

    服务端:

    public class PersonService extends Service {
      public IBinder onBind(Intent intent) {
        persons = new ArrayList<>();
        Log.e("LeoPersonServiceService", "success onBind");
        return iBinder;
      }
      private IBinder iBinder = new IPersonAidl.Stub() {
        @Override
        public void addPerson(Person person) throws RemoteException {
          persons.add(person);
        }
    
        @Override
        public List<Person> getPersonList() throws RemoteException {
          return persons;
        }
      };
    }
    
    public static abstract class Stub extends android.os.Binder implements com.xx.leo_service.IPersonAidl {
        private static final java.lang.String DESCRIPTOR = "com.xx.leo_service.IPersonAidl";
    
        /**
         * 服务端Service中new Stub的时候会设置一个DESCRIPTOR
         */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }
    
        public static com.xx.leo_service.ILeoAidl asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
          //先去查询DESCRIPTOR是否设置,如果是客户端,服务端在同一个进程,DESCRIPTOR是有值的,就能直接拿到这个服务端实例,而不需要通过Proxy,也就是通过binder去中转数据
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.xx.leo_service.IPersonAidl))) {
                return ((com.xx.leo_service.IPersonAidl) iin);
            }
            return new com.xx.leo_service.IPersonAidl.Stub.Proxy(obj);
        }  
    
        @Override
        public android.os.IBinder asBinder() {
            return this;
        }
    
        @Override
        public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply,
                                  int flags) throws android.os.RemoteException {
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(DESCRIPTOR);
                    return true;
                }
                case TRANSACTION_addPerson: {
                    data.enforceInterface(DESCRIPTOR);
                    com.xx.leo_service.Person _arg0;
                    if ((0 != data.readInt())) {
                        _arg0 = com.xx.leo_service.Person.CREATOR.createFromParcel(data);
                    } else {
                        _arg0 = null;
                    }
                    this.addPerson(_arg0);
                    reply.writeNoException();
                    return true;
                }
                case TRANSACTION_getPersonList: {
                    data.enforceInterface(DESCRIPTOR);
                    java.util.List<com.xx.leo_service.Person> _result = this.getPersonList();
                    reply.writeNoException();
                    reply.writeTypedList(_result);
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }
    

    那我们的客户端是如何与服务端进行通讯的呢,首先我们需要先绑定服务端Service

    public class MainActivity extends Activity{
      private void bindService() {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.xx.leo_service", "com.xx.leo_service.AidlService"));
        bindService(intent, connection, Context.BIND_AUTO_CREATE);
      }
    }
    

    ContextImpl#bindService

    private class ContextImpl extend Context{
      public boolean bindService( Intent service, int flags, Executor executor, ServiceConnection conn) {
        warnIfCallingFromSystemProcess();
        return bindServiceCommon(service, conn, flags, null, null, executor, getUser());
      }
    
      private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, String instanceName, Handler handler, Executor executor, UserHandle user) {
        //...
        //ActivityManager.getService()返回远程服务的代理对象:IActivityManager
        int res =ActivityManager.getService().bindIsolatedService(mMainThread.getApplicationThread(), getActivityToken(), service,service.resolveTypeIfNeeded(getContentResolver()),sd, flags, instanceName, getOpPackageName(), user.getIdentifier());
      }
    }
    

    ActivityManager#getService()

    public class ActivityManager{
      private static final Singleton<IActivityManager> IActivityManagerSingleton =
        new Singleton<IActivityManager>() {
        @Override
        protected IActivityManager create() {
          // b是服务端返回的IBinder对象
          final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
          //能看出IActivityManager是一个aidl类,am就是上面例子中的aidl对象中的Proxy:客户端,
          final IActivityManager am = IActivityManager.Stub.asInterface(b);
          return am;
        }
      };
      public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
      }
    }
    

    那上面的ServiceManager.getService(Context.ACTIVITY_SERVICE)获取到的是什么对象呢?其实就是ActivityManagerService,会在ActivityManagerService#setSystemProcess方法中添加进来

    ActivityManagerService#setSystemProcess

    //继承自IActivityManager.Stub,说明ActivityManagerService是服务端的实现类
    public class ActivityManagerService extends IActivityManager.Stub{
      public void setSystemProcess() {
        //将ActivityManagerService添加到ServiceManager中
            ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /* allowIsolated= */ true,
                    DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO);
            ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
            ServiceManager.addService("meminfo", new MemBinder(this), /* allowIsolated= */ false,
                    DUMP_FLAG_PRIORITY_HIGH);
            ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
            ServiceManager.addService("dbinfo", new DbBinder(this));
            if (MONITOR_CPU_USAGE) {
                ServiceManager.addService("cpuinfo", new CpuBinder(this),
                        /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
            }
            ServiceManager.addService("permission", new PermissionController(this));
            ServiceManager.addService("processinfo", new ProcessInfoService(this));
        }
    }
    

    ActivityManager#getService()返回的类型是 IActivityManager 类型,拿到远程服务的Binder 对象,其中IActivityManager.Stub.asInterface(b)就是拿到远程服务的代理对象:IActivityManager,通过代理对象调用远程的方法,是应用进程与服务进程通信的媒介,IActivityManager#bindIsolatedService最终会调用到ActivityManagerService#bindIsolatedService

    ActivityManagerService#bindIsolatedService

    public int bindIsolatedService(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, IServiceConnection connection, int flags, String instanceName,
            String callingPackage, int userId) throws TransactionTooLargeException {
        //...省略
        synchronized(this) {
            return mServices.bindServiceLocked(caller, token, service,
                    resolvedType, connection, flags, instanceName, callingPackage, userId);
        }
    }
    

    ActivityServices#bindServiceLocked

    public class ActivityServices{
      int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
                            String resolvedType, final IServiceConnection connection, int flags,
                            String callingPackage, final int userId) {
        //...省略
        ConnectionRecord c = new ConnectionRecord(b, activity,
                                                  connection, flags, clientLabel, clientIntent,
                                                  callerApp.uid, callerApp.processName, callingPackage);
        if ((flags&Context.BIND_AUTO_CREATE) != 0) {
          s.lastActivity = SystemClock.uptimeMillis();
          //注释1:调用bringUpServiceLocked,创建服务,具体看1.1
          if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
                                   permissionsReviewRequired) != null) {
            return 0;
          }
        }
    
        if (s.app != null && b.intent.received) {
          // Service is already running, so we can immediately
          // publish the connection.
          try {
            // 具体看2.1 -- c.conn => IServiceConnection.java ,最终会调用到客户端new ServiceConnection的onServiceConnected方法,将服务端的自己创建的IBinder对象传递过去
            //b.intent.binder = 从服务端获取的binder对象
            c.conn.connected(s.name, b.intent.binder, false);
          } 
          //如果已经绑定过了,requestServiceBindingLocked最后一个参数(rebind)为true
          if (b.intent.apps.size() == 1 && b.intent.doRebind) {
            //注释3: -- 具体看3.1 调用requestServiceBindingLocked
            requestServiceBindingLocked(s, b.intent, callerFg, true);
          }
          //如果没有绑定过最后一个参数为false
        } else if (!b.intent.requested) {
          requestServiceBindingLocked(s, b.intent, callerFg, false);
        }
      }
    

    1.1ActivityServices#bringUpServiceLocked

    private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
                                        boolean whileRestarting, boolean permissionsReviewRequired) {
      //...省略
      ProcessRecord app
      if (!isolated) {
        app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);     
        //app.thread  => ApplicationThread,因为一个进程启动就会走ActivityThread的main方法,会创建ApplicationThread,如果app.thread不为空,说明已经创建了另一个进程,app服务端Service已经启动了,b进程已经启动了,直接绑定服务就行了realStartServiceLocked
        if (app != null && app.thread != null) {
          app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
          //调用realStartServiceLocked,具体看1.2
          realStartServiceLocked(r, app, execInFg);
          return null;
        } 
      }
      //1.3 如果进程B未启动,调用startProcessLocked,启动一个进程,
      if (app == null && !permissionsReviewRequired) {
        if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                                        hostingType, r.name, false, isolated, false)) == null) {
          bringDownServiceLocked(r);
          return msg;
        }
        if (isolated) {
          r.isolatedProc = app;
        }
      }
    }
    

    1.2ActivityServices#realStartServiceLocked

    private final void realStartServiceLocked(ServiceRecord r,
                                              ProcessRecord app, boolean execInFg){
      //...省略 
      //1.2.1 app.thread = ApplicationThread,调用ApplicationThread的scheduleCreateService方法,创建service
      app.thread.scheduleCreateService(r, r.serviceInfo,
                              mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                                       app.repProcState);
    }
    

    1.3ActivityManagerService#startProcessLocked

    //开启一个进程
    private boolean startProcessLocked(...){
      final String entryPoint = "android.app.ActivityThread";
      startProcess(entryPoint,...);
    }
    
    private ProcessStartResult startProcess(){
      final ProcessStartResult startResult;
      if (hostingType.equals("webview_service")) {
        startResult = startWebView(entryPoint,...);
      } else {
        //通过ZygoteProcess启动一个进程 entryPoint = "android.app.ActivityThread"
        startResult = Process.start(entryPoint,..);
      }
    }
    

    1.2.1ApplicationThread#scheduleCreateService

    public final void scheduleCreateService(IBinder token,
                                            ServiceInfo info, CompatibilityInfo compatInfo, int processState) {    
      CreateServiceData s = new CreateServiceData();
      //发送一个CREATE_SERVICE消息,会在ActivityThread.H中处理
      sendMessage(H.CREATE_SERVICE, s);
    }
    
    class H extends Handler {
      public void handleMessage(Message msg) {
        case CREATE_SERVICE:
        //接收到CREATE_SERVICE消息后,创建服务
        handleCreateService((CreateServiceData)msg.obj);
        break;
      }
      private void handleCreateService(CreateServiceData data) {
        LoadedApk packageInfo = getPackageInfoNoCheck(
          data.info.applicationInfo, data.compatInfo);
        Service service = null;
        java.lang.ClassLoader cl = packageInfo.getClassLoader();
        //反射创建service
        service = packageInfo.getAppFactory()
          .instantiateService(cl, data.info.name, data.intent);
        Application app = packageInfo.makeApplication(false, mInstrumentation);
        //调用service的attach(),onCreate()
        service.attach(context, this, data.info.name, data.token, app,
                       ActivityManager.getService());
        service.onCreate();
        mServices.put(data.token, service);      
      }
    }
    

    2.1 IServiceConnection#connected

    IServiceConnection是一个aidl的类,那么这个实现类是如何创建的呢,回到客户端中ServiceConnection通过bindService传递,会将ServiceConnection转化为IServiceConnection

    public class MainActivity extends Activity{
      public void onCreate(){
        //传递自己创建的connection到bindService()中
        bindService(intent, connection, Context.BIND_AUTO_CREATE);
      }
    }
    

    ContextImpl#bindServiceCommon

    final @NonNull LoadedApk mPackageInfo;
    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
                                      handler, UserHandle user) {
      IServiceConnection sd;   
      if (mPackageInfo != null) {
        //sd就是上面2.1步骤用到的c.conn,将自己创建的ServiceConnection通过LoadedApk#getServiceDispatcher(conn)得到,那我们看一下sd的创建过程
        sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
      } else {
        throw new RuntimeException("Not supported in system context");
      }
    }
    

    LoadedApk#getServiceDispatcher()

    public final IServiceConnection getServiceDispatcher(ServiceConnection c,
                                                         Context context, Handler handler, int flags) {
      LoadedApk.ServiceDispatcher sd = null;
      if (sd == null) {
        //创建ServiceDispatcher,将ServiceConnection当做参数传递
        sd = new ServiceDispatcher(c, context, handler, flags);
      } else {
        sd.validate(context, handler);
      }
      //返回IServiceConnection
      return sd.getIServiceConnection();
    }
    

    ServiceDispatcher的类结构,查看IServiceConnection的创建过程,ServiceDispatcherLoadApk的内部类

    static final class ServiceDispatcher{
      ServiceDispatcher(ServiceConnection conn,
                        Context context, Handler activityThread, int flags) {
        //IServiceConnection = InnerConnection
        mIServiceConnection = new InnerConnection(this);
        //mConnection = 我们自己创建的ServiceConnection
        mConnection = conn;
      }
    
      IServiceConnection getIServiceConnection() {
        //返回IServiceConnection,也就是构造方法中创建的InnerConnection,所以上边c.conn.connected,就是调用
        //LoadApk#InnerConnection.connected()
        return mIServiceConnection;
      }
    }
    

    InnerConnection#connected

    //InnerConnection继承了IServiceConnection.Stub,说明这个InnerConnection相当于服务端实现
    private static class InnerConnection extends IServiceConnection.Stub {
      public void connected(ComponentName name, IBinder service, boolean dead){
        LoadedApk.ServiceDispatcher sd = mDispatcher.get();
        if (sd != null) {
          //调用了LoadedApk.ServiceDispatcher#connected
          sd.connected(name, service, dead);
        }
      }
    }
    

    LoadedApk.ServiceDispatcher#connected

    public void connected(ComponentName name, IBinder service, boolean dead) {
      if (mActivityThread != null) {
        mActivityThread.post(new RunConnection(name, service, 0, dead));
      } else {
        doConnected(name, service, dead);
      }
    }
    
    public void doConnected(ComponentName name, IBinder service, boolean dead) {
      ServiceDispatcher.ConnectionInfo old;
      ServiceDispatcher.ConnectionInfo info;
    
      synchronized (this) {
        if (old != null) {
          old.binder.unlinkToDeath(old.deathMonitor, 0);
        }
      }
      // If there was an old service, it is now disconnected.
      if (old != null) {
        mConnection.onServiceDisconnected(name);
      }
      if (dead) {
        mConnection.onBindingDied(name);
      }
      //mConnection=>构造方法传递的ServiceConnection,所以最终会调用我们自己创建的ServiceConnection的onServiceConnected方法,并将IBinder对象传递
      if (service != null) {
        mConnection.onServiceConnected(name, service);
      } else {
        // The binding machinery worked, but the remote returned null from onBind().
        mConnection.onNullBinding(name);
      }
    }
    

    3.1ActivityServices#requestServiceBindingLocked

    private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
                                                      boolean execInFg, boolean rebind) throws TransactionTooLargeException {
      if (r.app == null || r.app.thread == null) {
        // If service is not currently running, can't yet bind.
        return false;
      }
      if ((!i.requested || rebind) && i.apps.size() > 0) {
        try {
          bumpServiceExecutingLocked(r, execInFg, "bind");
          r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
          //rebind==true,调用Application#scheduleBindService,绑定服务
          r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                                           r.app.repProcState);
          if (!rebind) {
            i.requested = true;
          }
          i.hasBound = true;
          i.doRebind = false;
        } 
      }
      return true;
    }
    

    Application#scheduleBindService

    public final void scheduleBindService(IBinder token, Intent intent,
                                          boolean rebind, int processState) { 
      BindServiceData s = new BindServiceData();
      //发送一个BIND_SERVICE消息,会在ActivityThread.H处理,会绑定服务
      sendMessage(H.BIND_SERVICE, s);
    }
    
    public class ActivityThread{
      public void handleMessage(Message msg) {
        case BIND_SERVICE:
        //接收到BIND_SERVICE消息后,绑定服务
        handleBindService((BindServiceData)msg.obj);            
        break;
      }
    
      private void handleBindService(BindServiceData data) {
        Service s = mServices.get(data.token);   
        if (s != null) {
          data.intent.setExtrasClassLoader(s.getClassLoader());
          data.intent.prepareToEnterProcess();
          if (!data.rebind) {
            //调用我们自己创建的xxxService的onBind方法,onBind中会返回我们自己创建的 IBinder iBinder = new ILeoAidl.Stub()
            IBinder binder = s.onBind(data.intent);
            //调用ActivityManagerService当中的publishService方法
            ActivityManager.getService().publishService(data.token, data.intent, binder);
          } else {
            s.onRebind(data.intent);
            ActivityManager.getService().serviceDoneExecuting(
              data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
          }
        }
      }
    

    ActivityManagerService#publishService

    public void publishService(IBinder token, Intent intent, IBinder service) {
      synchronized(this) {
        //调用ActiveServicecs的publishServiceLocked方法
        mServices.publishServiceLocked((ServiceRecord)token, intent, service);
      }
    }
    

    ActiveServicecs#publishServiceLocked

    void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
      if (r != null) {
        Intent.FilterComparison filter
          = new Intent.FilterComparison(intent);
        IntentBindRecord b = r.bindings.get(filter);
        if (b != null && !b.received) {
          for (int conni=r.connections.size()-1; conni>=0; conni--) {
            ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
            for (int i=0; i<clist.size(); i++) {
              ConnectionRecord c = clist.get(i);
              // c.conn => IServiceConnection.java ,上面分析了最终会调用到客户端new ServiceConnection的onServiceConnected方法,将服务端的自己创建的IBinder对象传递过去
              c.conn.connected(r.name, service, false);
            }
          }
        }
        serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
      }
    }
    

    最后附上一张时序图


    BindService.jpg

    相关文章

      网友评论

          本文标题:Binder机制

          本文链接:https://www.haomeiwen.com/subject/zjxdactx.html