【面试】【binder】

java编写binder服务实例

https://www.cnblogs.com/winfu/p/7521372.html

1.编写AIDL 文件

IHelloService.aidl:

/** {@hide} */
interface IHelloService
{
    void sayhello();
    int sayhello_to(String name);
}

   1.把 IHelloService.aidl 放入 frameworks/base/core/java/android/os

   2.修改 frameworks/base/Android.mk 添加一行

core/java/android/os/IVibratorService.aidl \
+ core/java/android/os/IHelloService.aidl \

   3. 编译/framework/base

   4.系统自动生成IHelloService.java

public interface IHelloService extends android.os.IInterface
{
    public static abstract class Stub extends android.os.Binder implements IHelloService{
      private static final java.lang.String DESCRIPTOR = "IHelloService";
      
      public Stub()
      {
          this.attachInterface(this, DESCRIPTOR);
      }

      public static IHelloService asInterface(android.os.IBinder obj)
      { ... ...
          return new IHelloService.Stub.Proxy(obj);
      }

      @Override public android.os.IBinder asBinder()

      @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) ... 
      {
          switch (code)
          {
              case INTERFACE_TRANSACTION:
              case TRANSACTION_sayhello:
              case TRANSACTION_sayhello_to:
          }
      }

      private static class Proxy implements IHelloService

      static final int TRANSACTION_sayhello = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);

      static final int TRANSACTION_sayhello_to = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
  }

   public void sayhello() throws android.os.RemoteException;
    public int sayhello_to(java.lang.String name) throws android.os.RemoteException;
}

IHelloService.java 的结构为:

1.名字为IHelloService 的interface:

 2.IHelloService 这个interface 中有一个继承Binder 的抽象类stub

    IHelloService.aidl 中已经定义好的service 中的几个函数的虚函数

public interface IHelloService extends android.os.IInterface
{
    public static abstract class Stub extends android.os.Binder implements IHelloService ...
   
    public void sayhello() throws android.os.RemoteException; 

    public int sayhello_to(java.lang.String name) throws android.os.RemoteException;

}

    2.HelloService.java

import android.util.Slog;

public class HelloService extends IHelloService.Stub {
    private static final String TAG = "HelloService";
    ... ...
    public void sayhello() throws android.os.RemoteException {
    ... ...
    }
    
    public int sayhello_to(java.lang.String name) throws android.os.RemoteException {
     ... ...
    }
}

  1. HelloService.java 继承 IHelloService.Stub  这个内部类;

  2.  HelloService.java 中复写 之前在IHelloService.aidl 中定义好的函数

 

3.Client端代码

import android.util.Slog;
import android.os.ServiceManager;
import android.os.IBinder;

public class TestClient {
    public static void main(String args[])
    {

        if (args[0].equals("hello"))
        {
            /* 1. getService */
            IBinder binder = ServiceManager.getService("hello");

            IHelloService svr = IHelloService.Stub.asInterface(binder);

            svr.sayhello();

            int cnt = svr.sayhello_to(args[1]);

        }
    }
}

总结:

1.自己先写一个IHelloService.aidl ,系统编译后生成IHelloService.java

2.IHelloService.java是一个接口,其中定义了一个继承了binder 的抽象的 内部类stub,stub中实现了在IHelloService.aidl中定义方法的实现:将需要传输的数据打包为Parcel 类型,调用super.onTransact传输出去。

3.内部类stub中定义了一个实现了IHelloService接口的内部类proxy,proxy中实现了之前定义方法在client端的实现:初始化Parcel,调用mRemote.transact 发送出去。

4.内部类stub 中定义了一个返回  stub中内部类proxy类 的函数asInterface()

5.HelloService 继承IHelloService.stub

6.client端通过ServiceManager.getService("hello")得到IBinder 对象,传入到IHelloService.stub.asInterface() 这个静态方法中获取IHelloService对象,就可以直接调用函数了。

 

 

 

=========================================================================================

https://www.jianshu.com/p/adaa1a39a274

* Parcel

Parcel是一个容器,主要就是用来进行IPC通信的。

  1.Parcel的获取 :

Parcel parcle = Parcel.Obtain();

或者

new Parcel();

  2.Parcel 传入数据

parcel.writeInt(int val); // 传入Int 型数据

parcel.writeString(String val); //传入String 型 数据

  3.Parcel 获取数据


private PrintJobInfo(@NonNull Parcel parcel) {
   .. .. ..
        mLabel = parcel.readString();
        mState = parcel.readInt();
   .. .. ..

 

 

 

1. 如何确定目标binder 实体,唤醒进程/线程

 binder_proc 结构体

struct binder_proc {
    struct hlist_node proc_node;
    struct rb_root threads;
    struct rb_root nodes;
    struct rb_root refs_by_desc;
    struct rb_root refs_by_node;
... ...
    struct list_head todo;
    wait_queue_head_t wait;
... ...
};

nodes : Binder实体在内核中对应的数据结构

binder_node : 记录进程相关的binder_proc

1.SM.addService(XXXservice) ,将XXXservice 对应的binder_ref 放入SM 的binder_ref

2.SM.getService(XXXservice),查询SM 的binder_ref,将XXXservice 对应的binder_ref返回给client

3.client将binder_transaction事物插入到XXXservice 的binder_proc待处理队列

 

2.Binder传输数据的大小限制

ProcessState类中,限制每次传输大小不超过4M

 

3.系统服务与bindService服务的区别

    1.系统服务:通过SM.addService 添加的service,由ServiceManager 进行管理

    2.BinderService:通过Activity的startService启动,Service 只是一个封装,主要是Binder服务实类,不是ServiceManager管理,是AMS 在管理;Activity.binderService添加的service 无法被SM.getService 获取到;

    3.BinderService是去ActivityManagerService中去查找相应的Service组件,最终会将Service内部Binder的句柄传给Client。

     

4.Binder请求的同步与异步

 

5.Binder协议中BC_TRANSACTION与BR_TRANSACTION

  BC与BR主要是标志数据及Transaction流向;

  BC_TRANSACTION从用户空间流向内核

  BR_TRANSACTION从内核流线用户空间

 

6.Binder 传输数据的封装

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章