美文网首页Android FrameWork 学习
1.Android Binder 学习(一) 系统服务的Bin

1.Android Binder 学习(一) 系统服务的Bin

作者: Tsm_2020 | 来源:发表于2023-08-08 00:36 被阅读0次

    Binder 是什么? 作者的个人理解

    1.对于系统来说,Binder 类似于血管,链接这ServiceMananger ActivityManagerService ActivityTaskManagerService,承载着他们之间的信息的传递
    2.对于kernel 底层来说,binder 是驱动,是一种虚拟的底层驱动
    3.对于Java 应用层来说,他是一个封装了一套序列化的 Clint 与 Service 信息交互类

    想要了解Binder 就不得不从AIDL 说起, AIDL 为我们封装了一套标准的 Clint 与 Service 端的交互方式,我们如何来使用它交互呢,先看一下 简单的AIDL 的编译后的类的结构

    我们来看一下为什么说AIDL是一套 Clint/Service 交互方式呢

    image.png

    简单的创建了一个AIDL 的 interface
    使用这个文件编译后的 文件目录大体是下面这个样子

    public interface IMyAidlInterface extends android.os.IInterface
    {
    /** Default implementation for IMyAidlInterface. */
    public static class Default implements com.example.myservice.IMyAidlInterface
    {
      @Override public void say() throws android.os.RemoteException
      {
      }
      @Override public java.lang.String getStringContent() throws android.os.RemoteException
      {
        return null;
      }
      @Override
      public android.os.IBinder asBinder() {
        return null;
      }
    }
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements com.example.myservice.IMyAidlInterface
    {
      public Stub()
      {
        this.attachInterface(this, DESCRIPTOR);
      }
    
      public static com.example.myservice.IMyAidlInterface asInterface(android.os.IBinder obj)
      {
        if ((obj==null)) {
          return null;
        }
        android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
        if (((iin!=null)&&(iin instanceof com.example.myservice.IMyAidlInterface))) {
          return ((com.example.myservice.IMyAidlInterface)iin);
        }
        return new com.example.myservice.IMyAidlInterface.Stub.Proxy(obj);
      }
      @Override public android.os.IBinder asBinder()
      {
        return this;
      }
      private static class Proxy implements com.example.myservice.IMyAidlInterface
      {
        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;
        }
        public static com.example.myservice.IMyAidlInterface sDefaultImpl;
      }
      public static com.example.myservice.IMyAidlInterface getDefaultImpl() {
        return Stub.Proxy.sDefaultImpl;
      }
    }
    
    }
    
    image.png

    现在思考一个问题,为什么Clint 拿道的是一个Proxy ,Service 交出的是一个Stub 呢,他们两个为什么不能拿到同一个对象吗,那样使用起来多方便,这个里面就存在一个问题,由于进程是隔离,这就让他们同时持有一个对象变得不可能,此时就有另外一个说法,能不能为两个APP 进程开辟同一个系统的内核空间呢,这样两面只要操作内核空间就可以了,其实这种方案也有一个弊端,那就是一端在写的同时,另一端来读数据,这就造成了数据混乱或者就是脏数据,最后就形成了现在的Binder 的这种使用代理的通信机制,

    通过代码来看一下他们的依赖关系是什么

    Clint 端

    我们在BinderService 的过程中都会传入一个ServiceConncetion 对象,在bind成功后会调用 AIDLInterface.Stub.asInterface 来获取 AIDL Interface.Stub.Proxy 的示例

    
      private ServiceConnection serviceConnection=new ServiceConnection() {
          @Override
          public void onServiceConnected(ComponentName name, IBinder service) {
              IMyAidlInterface binder = IMyAidlInterface.Stub.asInterface(service);
          }
          @Override
          public void onServiceDisconnected(ComponentName name) {
          }
      };
    

    在Interface.Stub 中做了一下判断,传进来是是否是IInterface,不是就创建一个Proxy

      public static com.example.myservice.IMyAidlInterface asInterface(android.os.IBinder obj)
      {
        if ((obj==null)) {
          return null;
        }
        android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
        if (((iin!=null)&&(iin instanceof com.example.myservice.IMyAidlInterface))) {
          return ((com.example.myservice.IMyAidlInterface)iin);
        }
        return new com.example.myservice.IMyAidlInterface.Stub.Proxy(obj);
      }
    

    上面就是Clint 端建立链接的过程

    Service 端

    public class MyService extends Service  {
    
      private final IMyAidlInterface.Stub binder=new IMyAidlInterface.Stub() {
          @Override
          public void say() throws RemoteException {
          }
    
          @Override
          public String getStringContent() throws RemoteException {
              return "Hellow";
          }
      };
      @Nullable
      @Override
      public IBinder onBind(Intent intent) {
          return binder;
      }
    }
    

    service 端在内部创建了一个IInterface 的Stub ,在onBind的时候将这个 stub 对外提供,来做数据通信

    整个过程看起来很简单,那么对于Android 系统来说,SystemServer 是如何来调度和管理各个 IInterface 的呢,我们就以ActivityTaskManagerService一个为例

    App 启动过程

    App启动的过程是通过zygote fork 出来的,具体的过程就是调用 ZygoteIntent.forkSystemService 方法复制出来的,具体的代码如下

         pid = Zygote.forkSystemServer(
                      parsedArgs.mUid, parsedArgs.mGid,
                      parsedArgs.mGids,
                      parsedArgs.mRuntimeFlags,
                      null,
                      parsedArgs.mPermittedCapabilities,
                      parsedArgs.mEffectiveCapabilities);
    

    fork 出app进程后,启动流程就在SystemServer中了,在SystemServer 的Run 方法内 做了3个特别重要的方法

       startBootstrapServices(t);
              startCoreServices(t);
              startOtherServices(t);
    
    

    其中 startBootstrapServices 这个方法中就初始化了 ActivityTaskManagerService,我们来看一下代码

          // Activity manager runs the show.
          t.traceBegin("StartActivityManager");
          // TODO: Might need to move after migration to WM.
          ActivityTaskManagerService atm = mSystemServiceManager.startService(
                  ActivityTaskManagerService.Lifecycle.class).getService(); //启动atms
          mActivityManagerService = ActivityManagerService.Lifecycle.startService(
                  mSystemServiceManager, atm); // 启动AMS
          mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
          mActivityManagerService.setInstaller(installer);
          mWindowManagerGlobalLock = atm.getGlobalLock();
          t.traceEnd();
    

    可以看到启动的是 mSystemServiceManager.startService(ActivityTaskManagerService.Lifecycle.class),我们继续来看SystemServiceManager 的startService

    public <T extends SystemService> T startService(Class<T> serviceClass) {
          try {
              final String name = serviceClass.getName();
              Slog.i(TAG, "Starting " + name);
              Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartService " + name);
    
              // Create the service.
              if (!SystemService.class.isAssignableFrom(serviceClass)) {
                  throw new RuntimeException("Failed to create " + name
                          + ": service must extend " + SystemService.class.getName());
              }
              final T service;
              try {
                  Constructor<T> constructor = serviceClass.getConstructor(Context.class);
                  service = constructor.newInstance(mContext);
              } catch (InstantiationException ex) {
                  throw new RuntimeException("Failed to create service " + name
                          + ": service could not be instantiated", ex);
              } catch (IllegalAccessException ex) {
                  throw new RuntimeException("Failed to create service " + name
                          + ": service must have a public constructor with a Context argument", ex);
              } catch (NoSuchMethodException ex) {
                  throw new RuntimeException("Failed to create service " + name
                          + ": service must have a public constructor with a Context argument", ex);
              } catch (InvocationTargetException ex) {
                  throw new RuntimeException("Failed to create service " + name
                          + ": service constructor threw an exception", ex);
              }
    
              startService(service);
              return service;  
          } finally {
              Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
          }
      }
    
    
    
      public void startService(@NonNull final SystemService service) {
          // Register it.
          mServices.add(service);
          // Start it.
          long time = SystemClock.elapsedRealtime();
          try {
              service.onStart();
          } catch (RuntimeException ex) {
              throw new RuntimeException("Failed to start service " + service.getClass().getName()
                      + ": onStart threw an exception", ex);
          }
          warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
      }
    

    SystemServiceManager 通过类对象使用反射创建一个实例,在将这个service实例添加到 mService 这个SystemService 的list 当中,并执行ActivityTaskManagerService.Lifecycle的onStart 方法
    ActivityTaskManagerService.Lifecycle 继承自SystemService

      public static final class Lifecycle extends SystemService {
          private final ActivityTaskManagerService mService;
    
          public Lifecycle(Context context) {
              super(context);
              mService = new ActivityTaskManagerService(context);
          }
    
          @Override
          public void onStart() {
              publishBinderService(Context.ACTIVITY_TASK_SERVICE, mService);
              mService.start();
          }
    
          @Override
          public void onUserUnlocked(@NonNull TargetUser user) {
              synchronized (mService.getGlobalLock()) {
                  mService.mTaskSupervisor.onUserUnlocked(user.getUserIdentifier());
              }
          }
    
          @Override
          public void onUserStopped(@NonNull TargetUser user) {
              synchronized (mService.getGlobalLock()) {
                  mService.mTaskSupervisor.mLaunchParamsPersister
                          .onCleanupUser(user.getUserIdentifier());
              }
          }
    
          public ActivityTaskManagerService getService() {
              return mService;
          }
      }
    

    在 ActivityTaskManagerService.Lifecycle 的onstart 方法中,将一个在ActivityTaskManagerService.Lifecycle 初始化过程中创建ActivityTaskManagerService 的mService 放入到了SystemService publishBinderService,

    我们先来看一下 ActivityTaskManagerService 这个类的继承关系

    public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    }
    

    可以看到他就是一个aidl 中的一个服务端的Stub 代理类,我们继续向下看 SystemServcie 的publishBinderService方法

      protected final void publishBinderService(@NonNull String name, @NonNull IBinder service) {
          publishBinderService(name, service, false);
      }
    
      /**
       * Publish the service so it is accessible to other services and apps.
       *
       * @param name the name of the new service
       * @param service the service object
       * @param allowIsolated set to true to allow isolated sandboxed processes
       * to access this service
       */
      protected final void publishBinderService(@NonNull String name, @NonNull IBinder service,
              boolean allowIsolated) {
          publishBinderService(name, service, allowIsolated, DUMP_FLAG_PRIORITY_DEFAULT);
      }
      protected final void publishBinderService(String name, IBinder service,
              boolean allowIsolated, int dumpPriority) {
          ServiceManager.addService(name, service, allowIsolated, dumpPriority);
      }
    

    在这个方法里面将这个 service 放入到了ServiceManager 中,继续向下看

    
      private static IServiceManager getIServiceManager() {
          if (sServiceManager != null) {
              return sServiceManager;
          }
    
          // Find the service manager
          sServiceManager = ServiceManagerNative
                  .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
          return sServiceManager;//ServiceManagerProxy
      }
    
      public static void addService(String name, IBinder service, boolean allowIsolated,
              int dumpPriority) {
          try {
              getIServiceManager().addService(name, service, allowIsolated, dumpPriority);
          } catch (RemoteException e) {
              Log.e(TAG, "error in addService", e);
          }
      }
    

    这个里面就是获取到了一个 IServiceManager 的 IInterface Stub 的实例,继续往下看就是c++相关的文件了,这里我贴一下IServiceManager 当中定义 serviceManager 的相关代码
    这段代码在IServiceManager.cpp 文件中

    using AidlServiceManager = android::os::IServiceManager;
    

    上面所有的代码流程其实就是想说明一下,在activity 当中通过getSystemService 获取的 各类manager 都是 Binder 机制中的 Stub,我们可以通过Stub 进行跨进程通信 ,再来梳理一遍 IInterface 注册Stub 的整个过程

    1.ZygoteInit fork app 进程 , 启动SystemServer.main()方法,在SystemServer main 方法中创建了一个 SystemServer,并执行SystemServer 的run 方法

    2.SystemServer run方法中执行了3个比较重要的方法,其中startBootstrapServices 中 通过 SystemServiceManager 使用反射启动了 ActivityTaskManagerService.Lifecycle ,启动后将他放入到mservice 这个list 中,并执行service.onstart方法

    3.ActivityTaskManagerService.Lifecycle 的onstart 方法中将 ActivityTaskManagerService.Lifecycle 初始化过程中创建的 ActivityTaskManagerService 放入publishBinderService 方法中, ActivityTaskManagerService 就是一个IInterface.Stub 的实例

    4.SystemService 将 这个 Stub 放入到 ServiceManager 中

    5.由ServiceManager 做了Native 的桥梁管理这些 IInterface.Stub ,

    整个过程就是下面这种图这样的


    image.png

    本来这篇想写一下ActivityManagerService 的启动过程的,但是发现 ActivityManagerService 没有将这个IInterface.Stub 的实例放入到ServiceManager 当中,看来应该是没有对外调度的方法,或者不想让开发者参与进来,
    根据ServiceManager 这个管理者我们可以理解为,ServiceManager 是通过binder 来进行跨进程的任务调度,他管理这所有进程的一些服务,

    了解了Binder 的 基本通信逻辑,接下来我们继续分析一下bindService 这个过程中到底使用了几次跨进程通信

    相关文章

      网友评论

        本文标题:1.Android Binder 学习(一) 系统服务的Bin

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