首页 > 其他分享 >Android Binder 学习(一) 系统服务的Binder 是如何管理的

Android Binder 学习(一) 系统服务的Binder 是如何管理的

时间:2023-08-10 11:32:38浏览次数:34  
标签:ActivityTaskManagerService Stub name service 学习 Binder IMyAidlInterface Android 

Binder 是什么? 小编的个人理解

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

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

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

Android Binder 学习(一)  系统服务的Binder 是如何管理的_android

简单的创建了一个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;
  }
}

}

Android Binder 学习(一)  系统服务的Binder 是如何管理的_sed_02

现在思考一个问题,为什么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 ,

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

Android Binder 学习(一)  系统服务的Binder 是如何管理的_ide_03

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

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


标签:ActivityTaskManagerService,Stub,name,service,学习,Binder,IMyAidlInterface,Android,
From: https://blog.51cto.com/u_16175630/7032598

相关文章

  • Struts 学习笔记1 -Struts Framework 概览
    作者:bruce--Java研究组织Tuesday,January21200311:06AMStruts开始于2000年3月,1.0在2001年7月发布。采用Struts能开发出基于MVC(Model-View-Controller)设计模式的应用构架。MVC设计模式把一个系统分成3个相互协调的部分:Model(模型)模型用于封装系统的状态View......
  • Android仿微信图片上传,可以选择多张图片,缩放预览,拍照上传等
    仿照微信,朋友圈分享图片功能。可以进行图片的多张选择,拍照添加图片,以及进行图片的预览,预览时可以进行缩放,并且可以删除选中状态的图片。很不错的源码,大家有需要可以下载看看。微信微信微信微信下载地址: 微信上传图片源码很多网友不知道怎么获取图片路径,这里贴出......
  • awesome-android-ui
    https://github.com/wasabeef/awesome-android-ui SkiptocontentSignup Signin ThisrepositoryExploreFeaturesEnterpriseBlog   Star3,934 Fork526wasabeef/awesome-android-uiCode......
  • 点云分割学习路径
    1.传统点云分割点云分割是根据空间、几何和纹理等特征对点云进行划分,使得同一划分内的点云拥有相似的特征。点云的有效分割是许多应用的前提,例如在三维重建领域,需要对场景内的物体首先进行分类处理,然后才能进行后期的识别和重建。传统的点云分割主要依赖聚类算法和基于随机采样......
  • 【学习笔记】线段树分治
    定义线段树分治是一种解决一类有插入、删除和整体查询操作的问题的方法。它是一种离线做法,通过在线段树上记录操作的时间区间来处理修改对询问的影响。每个操作被看作一个时间区间的修改,并在线段树上进行标记。然后通过深度优先搜索(DFS)依次执行这些操作,直到根节点来回答查询,并在......
  • 萌新学习c语言过程
    今天把三子棋的代码写的差不多了,有些地方不尽人意感觉有时候还是有点迷。......
  • openGauss学习笔记-35 openGauss 高级数据管理-ALTER TABLE语句
    openGauss学习笔记-35openGauss高级数据管理-ALTERTABLE语句修改表,包括修改表的定义、重命名表、重命名表中指定的列、重命名表的约束、设置表的所属模式、添加/更新多个列、打开/关闭行访问控制开关。35.1语法格式在一张已经存在的表上添加列。ALTERTABLEtable_name......
  • 【机器学习|数学基础】Mathematics for Machine Learning系列之矩阵理论(12):相似形理论
    目录前言往期文章3.3线性变换的最简矩阵表示-相似形理论3.3.1一般数域上矩阵相似最简形定义3.9定理3.3.1前言Hello!小伙伴!非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出~ 自我介绍ଘ(੭ˊᵕˋ)੭昵称:海轰标签:程序猿|C++选手|学生简介:因C语言结识编程,随后转入计算......
  • 【机器学习|数学基础】Mathematics for Machine Learning系列之矩阵理论(13):Hamliton-Cay
    目录前言Hello!小伙伴!非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出~ 自我介绍ଘ(੭ˊᵕˋ)੭昵称:海轰标签:程序猿|C++选手|学生简介:因C语言结识编程,随后转入计算机专业,有幸拿过一些国奖、省奖…已保研。目前正在学习C++/Linux/Python学习经验:扎实基础+多做笔记+......
  • 【机器学习|数学基础】Mathematics for Machine Learning系列之矩阵理论(15):矩阵的范数
    前言Hello!小伙伴!非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出~ 自我介绍ଘ(੭ˊᵕˋ)੭昵称:海轰标签:程序猿|C++选手|学生简介:因C语言结识编程,随后转入计算机专业,有幸拿过一些国奖、省奖…已保研。目前正在学习C++/Linux/Python学习经验:扎实基础+多做笔记+多......