Binder死磕到底(三):浅析AIDL

1 篇文章 1 订阅
1 篇文章 0 订阅

目录

一、AIDL基本使用

1、服务端进程

1)、创建AIDL

2)、创建接口

3)、创建服务

2、客户端应用

3、跨进程服务

二、AIDL基本原理

1、AIDL接口的默认实现

2、Stub实体对象

1)、asInterface

2)、onTransact

3、Proxy代理对象

三、应用框架层的ServiceManager

1、Java世界的ServiceManager

1)、获取native世界的BpBinder(0)

2)、ServiceManagerNative/Proxy的实体和代理

2、Java世界与servicemanager进程交互

1)、Java世界的数据封装Parcel

2)、Java世界Parcel的创建

3)、Parcel.readStrongBinder(读IBinder)

4)、Parcel.writeStrongBinder(写IBinder)

四、两个世界的转换

1、Java层的IBinder:Binder/BinderProxy

1)、Java层的实体对象Binder

2)、Java层的代理对象BinderProxy

2、JNI层的IBinder:Binder/BinderProxy

1)、JNI层的Binder

2)、JNI层的BinderProxy

3、汇总两个世界的IBinder

4、ibinderForJavaObject

1)、android.os.Binder->JavaBBinder

2)、android.os.BinderProxy->BpBinder

3)、承接android.os.Parcel.writeStringBinder

5、javaObjectForIBinder

1)、JavaBBinder->android.os.Binder

2)、BpBinder->android.os.BinderProxy

3)、承接android.os.Parcel.readStrongBinder

五、恍然一梦

1、IXXX.Stub.Proxy如何持有android.os.BinderProxy?

1)、ContxtImpl绑定服务

2)、ActivityManager绑定服务

3)、ActiveServices实现了复杂的逻辑

4)、ActivityThread实现Service的创建和绑定

2、一次完整的C/S通信流程


Binder是Android系统提供的一种IPC( 进程间通信) 机制,在Java层中如果想要利用Binder进行跨进程的通信, 也得定义一个类似ITest的接口,不过这是一个aidl文件。阿斗(aidl的谐音) 本来是扶不起的, 可是我们有了AIDL工具,就有可能将他扶起!即AIDL是Binder系统面向Java层的一种实现机制

本篇第一章讲解了AIDL的基本使用,可以通过AIDL来实现两个不同应用程序(不同进程)之间的通信,即可以通过四大组件中的远程Service的访问示例。

本篇第二章剖析了AIDL生成的中间类,即访问远程Service的基本原理,框架层的android.os.Binder/BinderProxy通过JNI调用了native世界的binder进程通信库。

本篇第三章介绍了ServiceManager.java,并梳理了ServiceManager是如何与native世界的service manager进程建立联系。

本篇第四章也分析了Java世界的android.os.Binder/BinderProxy和C++世界的BBinder和BpBinder之间的关系。

本篇第五章攻克了最后的疑问,总结了AIDL完整的一次通信流程。

参考:Android中AIDL的使用详解

参考:Binder机制学习总结之Java接口

参考:进程间通信之Binder机制浅析

一、AIDL基本使用

AIDL是Android中IPC(Inter-Process Communication)方式中的一种,AIDL是Android Interface definition language的缩写(Android内部进程通信接口的描述语言)。对于小白来说,AIDL的作用是让你可以在自己的APP里绑定一个其他APP的service,这样你的APP可以和其他APP交互。下面将手写两个应用程序,其中一个应用AIDLServer作为服务端进程(为系统提供服务),另外一个应用AIDLClient作为客户端进程。

1、服务端进程

这里我们创建一个AIDLServer的应用程序作为服务端进程,为系统提供一些列服务,该进程可以提供多个服务,即可以创建多个AIDL服务。

1)、创建AIDL

AIDL其实是Android Interface definition language的缩写,在Android框架层中,可以用一个aidl文件来描述一个AIDL接口,实际开发中我们将创建一个或多个AIDL文件,其内容符合Android Interface definition language语法(很类似java的接口),每个AIDL文件都对应一个服务service。

可以通过Android studio的菜单创建一个AIDL文件:File->New->AIDL->AIDL File

这个AIDL文件被存储的路径与java同层:项目名\app\src\main\aidl\包路径\xxx.aidl

2)、创建接口

在步骤1中我们创建了两个aidl文件,意味着我们可以为系统提供两个不同的service(服务),这些service中我们可以提供一些列的方法集合。这里的ICommonService.aidl用来实现一些基础公共服务,ISPlayerService.aidl用来实现一些媒体播放服务。因此需要分别在aidl中加上一系列函数,如下:

// ICommonService.aidl
package com.shen.aidlserver;
interface ICommonService {
    //提示AIDL文件中智能用int long boolean float double String几种基本数据类型,因为需要跨进程
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString);
    //定义接口判断是否拥有root权限
    boolean hasRootPerssion();
    //定义接口重启关闭休眠唤醒系统
    void resetSystem();
    void shutSystem();
    void sleepSystem();
    void wakeSystem();
}
// ISPlayerService.aidl
package com.shen.aidlserver;
interface ISPlayerService {
    //设置媒体播放的操作方法
    int setDataSource(int fd, long offset, long length);
    int prepareAsync();
    int start();
    int stop();
    int pause();
    int setVolume(float leftVolume, float rightVolume);
    int setLooping(int loop);
}

如上代码,我们在ICommonService服务中增加了一些操作系统的方法,在ISPlayerService服务中增加了一些媒体播放的方法,但这个时候只是定义了service的接口而已,我们并不能使用这些服务。Android studio为我们提供sycn project来一键生成这些服务。

如上图,当同步成功后就会在对应的generated目录生成对应的interface,如果该目录下有漏掉的interface那么应该去排查对应的aidl是否有语法错误导致Android studio无法解析,如下我这种情况,ICommonService没有生成,但我并没有检查出什么语法错误,去掉一些注释就好了,怀疑Android studio的bug:

3)、创建服务

同步工程之后,Android studio会自动在generated生成一些临时文件,如ICommonService.java和ISPlayerService.java。这两个文件其实是通过ICommonService.aidl和ISPlayerService.aidl转换过去的,并实现了一些关于binder库相关的一些代码,具体详情参考第二章,这里我们需要知道除了定义对应的接口类(ICommonService),还定义了ICommonService.Stub内部类。

Stub其实对应Binder框架库里面的BnXXX,因此在具体的业务中,通常只需要我们实现该类的真正业务逻辑部分功能就完成了整个Binder通信机制。这里我在Java层来创建两个服务CommonService和SPlayerService来对应上面定义的两个aidl接口文件。如下代码:

package com.shen.aidlserver;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import androidx.annotation.Nullable;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
public class CommonService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return iBinder;
    }
    private IBinder iBinder = new ICommonService.Stub() {
        @Override
        public boolean hasRootPerssion() throws RemoteException {
            PrintWriter PrintWriter = null;
            Process process = null;
            try {
                process = Runtime.getRuntime().exec("su");
                PrintWriter = new PrintWriter(process.getOutputStream());
                PrintWriter.flush();
                PrintWriter.close();
                int value = process.waitFor();
                return returnResult(value);
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
                if(process!=null) process.destroy();
            }
            return false;
        }
        @Override
        public void resetSystem() throws RemoteException {
            try {
                if (hasRootPerssion()) {
                    Process process = Runtime.getRuntime().exec("su");
                    DataOutputStream out = new DataOutputStream(process.getOutputStream());
                    out.writeBytes("reboot \n");
                    out.writeBytes("exit\n");
                    out.flush();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        @Override
        public void shutSystem() throws RemoteException {
            try {
                if (hasRootPerssion()) {
                    Process process = Runtime.getRuntime().exec("su");
                    DataOutputStream out = new DataOutputStream(process.getOutputStream());
                    out.writeBytes("reboot -p\n");
                    out.writeBytes("exit\n");
                    out.flush();
                }
            } catch(IOException e){
                e.printStackTrace();
            }
        }
        @Override
        public void sleepSystem() throws RemoteException {
            try {
                if (hasRootPerssion()) {
                    Process process = Runtime.getRuntime().exec("su");
                    DataOutputStream out = new  DataOutputStream(process.getOutputStream());
                    out.writeBytes("echo mem > /sys/power/state \n");
                    out.writeBytes("exit\n");
                    out.flush();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        @Override
        public void wakeSystem() throws RemoteException {
            try {
                if (hasRootPerssion()) {
                    Process process = Runtime.getRuntime().exec("su");
                    DataOutputStream out = new DataOutputStream(process.getOutputStream());
                    out.writeBytes("echo on > /sys/power/state \n");
                    out.writeBytes("exit\n");
                    out.flush();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    };
}

如上类CommonService代码,继承于Service表示它是一个后台服务,重写了onBind方法返回了一个ICommonService.Stub类,在该类的接口中实现了重启/关机/睡眠/唤醒系统的功能。即其他应用程序可以通过四大组件之一Service的方式来访问我,我给他们提供重启/关机/睡眠/唤醒系统的服务。

其实上面的ICommonService的实现,我觉得还是有些需要优化的,以解耦功能性的方向来看,我们完全可以把具体业务逻辑实现放在Service里面,然后IBinder只需要当成中间桥梁的作用就行了。如下SPlayerService的代码:

package com.shen.aidlserver;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class SPlayerService extends Service {
    private void prepareSPlayer(){
        //...业务逻辑具体实现
    }
    private void startSPlayer(){
        //...业务逻辑具体实现
    }
    private void stopSPlayer(){
        //...业务逻辑具体实现
    }
    private void pauseSPlayer(){
        //...业务逻辑具体实现
    }
    private void setSPlayerSource(int fd, long offset, long length){
        //...业务逻辑具体实现
    }
    private void setSPlayerLooping(int loop){
        //...业务逻辑具体实现
    }
    private void setSPlayerVolume(float leftVolume, float rightVolume){
        //...业务逻辑具体实现
    }
    @Override
    public IBinder onBind(Intent intent) {
        return new ISPlayerService.Stub() {
            @Override
            public int prepareAsync() throws RemoteException {
                prepareSPlayer();
                return 0;
            }
            @Override
            public int setDataSource(int fd, long offset, long length) throws RemoteException {
                setSPlayerSource(fd,offset,length);
                return 0;
            }
            @Override
            public int start() throws RemoteException {
                startSPlayer();
                return 0;
            }
            @Override
            public int stop() throws RemoteException {
                stopSPlayer();
                return 0;
            }
            @Override
            public int pause() throws RemoteException {
                pauseSPlayer();
                return 0;
            }
            @Override
            public int setVolume(float leftVolume, float rightVolume) throws RemoteException {
                setSPlayerVolume(leftVolume, rightVolume);
                return 0;
            }
            @Override
            public int setLooping(int loop) throws RemoteException {
                setSPlayerLooping(loop);
                return 0;
            }
        };
    }
}

2、客户端应用

第一节内容已经创建了服务端应用程序,该进程内部除了创建两个aidl文件还根据aidl接口创建了两个服务,没错这里的服务就是android四大组件之一Service。这里我们要创建一个客户端应用程序,该应用内部需要访问上面的这两个Service,在android架构中默认会为每个应用程序APP创建一个进程,因此这里就属于跨进程访问。

四大组件之Service的访问大家都应该很熟悉了,对于做应用来说,无论Service是否跨进程,访问的方式其实都是一样的。因此可以进行总结:同应用程序中的Service访问使用的代理模式;不同应用程序中需要进行Service访问,就需要使用AIDL来实现。

package com.shen.aidlclient;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.widget.Button;
import com.shen.aidlserver.ISPlayerService;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button bt = findViewById(R.id.play);
        bt.setOnClickListener(this);
    }
    @Override
    public void onClick(View view) {
        Intent intent = new Intent();
        //跨进程,无法使用Intent(this,xx.class)方法,可以使用下面的,通过包名和完整路径类名创建Intent
        intent.setClassName("com.shen.aidlserver","com.shen.aidlserver.SPlayerService");
        bindService(intent, new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
                ISPlayerService iss = ISPlayerService.Stub.asInterface(iBinder);
                try {
                    iss.prepareAsync();
                    iss.setVolume(30, 30);
                    iss.setLooping(1);
                    iss.start();
                }catch (Exception e){
                }
            }
            @Override
            public void onServiceDisconnected(ComponentName componentName) {
            }
        }, Context.BIND_AUTO_CREATE);
    }
}

如上代码访问Service的通用方式:

  • 通过bindService方法来绑定某个服务,该服务填充到Intent,因为这里访问的是其他应用程序的服务,本地中无法指定Service.class,因此必须使用包名的方式进行填充
  • 当服务连接成功之后,使用方法ISPlayerService.Stub.asInterface(iBinder)将IBinder转换成IXXX接口,这里可能编译无法通过,因此需要将对应的aidl文件拷贝过来

3、跨进程服务

目前服务端应用程序AIDLServer和客户端应用程序AIDLClient都已经准备好了,找一台手机来运行一下,看应用程序AIDLClient能够调用AIDLServer里面的服务吗?运行日志结果如下:

上面的报错日志显示SPlayerService不允许aidlclient程序访问?为什么呢?原来我们还差个步骤,需要将SPlayerService配置成远程访问允许,因此需要在SPlayerService配置的地方加上属性exported。配置如下:

二、AIDL基本原理

从上面的示例中可以看出来,AIDL文件在中间只起了桥梁的作用,即AIDL为我们提供了IBinder的接口定义。在服务端应用程序中,四大组件Service的IBinder继承了类IXXX.Stub;在客户端应用程序中,在绑定服务连接成功的时候将前面的IXXX.Stub强转成ISPlayerService.Stub.asInterface(iBinder)。

其实IXXX.Stub和IXXX.Stub.asInterface都被定义在generated目录里面对应的接口里面,Android studio在同步或编译工程的时候会自动解析aidl文件,并将其转换成对应的接口,这个过程也可以使用android sdk下面工具命令转换。ISPlayerService接口代码如下:

如上该文件中定义了接口ISPlayerService,该接口除了定义aidl文件中描述的接口之外,还有定义了一个静态内部类Default和一个抽象内部类Stub。

除此之外接口ISPlayerService继承于android.os.IInterface,其实该接口内部就定义了asBinder方法,用来将IXXX转换成接口IBinder,如下:

1、AIDL接口的默认实现

静态内部类Default其实是对aidl接口的一个默认实现,其实什么都没有,也没有什么研究的必要。如下代码:

但值得注意的是除了实现aidl文件里面描述的接口方法之外,还实现了android.os.IInterface接口里面的asBinder方法,用来将ISPlayerService接口转换成IBinder接口。

2、Stub实体对象

内部抽象类Stub继承于android.os.Binder且实现了IXXX接口,除此之外它还有一个静态内部类Proxy。其中Proxy/Stub的关系对应于Binder架构里面的C/S架构,即Stub在natvie层对应于一个BnXXX,Proxy在native层对应于一个BpXXX。如下代码:

Stub类内部还实现了几个重要的方法:

  • asBinder:将自己转换成IBinder,因为Stub实现了IBinder接口,所以这里直接返回了自己this
  • asInterface:将IBinder强转成IXXX,在使用bindService方法绑定服务成功之后,回调函数onServiceConnected的参数是最基本的IBinder类型(传递的父类),因此需要通过该方法将其强制转换成IXXX
  • onTransact:进行任务分发,类似natvie层里面的BnXXX

1)、asInterface

前文有介绍Stub对应于C/S通信架构中的服务端,也可以将其理解成Service的本地对象;而Proxy对应于C/S通信架构中的客户端,也可以理解成Service的代理对象。

当客户端应用程序使用bindService绑定Service成功之后,就会得到一个IBinder接口,我们可以通过该接口来访问被绑定的Service,因为IBinder是一个通用基类(没有任何业务相关的实现),所有需要将其强制转换成业务子类。

  • 访问本地Service:该方式通常在同一个APP中,Activity访问Service,他们同为四大组件,且都处于同一个进程,因此Activity能够获取到本地Service的实例对象强转ServiceConnection返回的IBinder为自定义业务子类,通过该业务子类访问Service或者直接获取Service的实例对象。如下示例代码:
//Service实现
public class MyService extends Service {
    //自定义Binder 该binder能返回Service实例对象
    public class MyBinder extends Binder {
        public MyService getService(){
            return MyService.this; //返回的本实例
         }
    }
    private MyBinder mBinder = new MyBinder();
    @Override
    public IBinder onBind(Intent intent) {
         return mBinder;
    }
    public String getMyName(){
        return "I am 诸神黄昏";
    }
}
//acitivity建立连接
ServiceConnection serviceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder ibinder) {
        //将ibinder强转MyBinder类型
        MyBinder  mBinder = (MyService.MyBinder)ibinder;
        //通过自定义的MyBinder拿到MyService实例对象
        MyService  mService = mBinder.getService();
        //通过实例对象来访问MyService的getMyName接口
        textView.setText(mService.getMyName());
    }
}
  • 访问远程Service:该方式通常在不同APP或不同的进程之间,Service的访问方式,因为他们不再同一个进程中,因为进程隔离的原因,上面那种方式就行不通了,你根本无法拿到MyService的实例对象。这时候就需要通过IXXX.Stub.asInterface来将IBinder转换成aidl文件定义的接口才行
//远程Service实现
public class MyService extends Service {
    private MyBinder mBinder = new IXXX.Stub();
    @Override
    public IBinder onBind(Intent intent) {
         return mBinder;
    }
    public String getMyName(){
        return "I am 诸神黄昏";
    }
}
//acitivity建立连接
ServiceConnection serviceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder ibinder) {
        //将ibinder强转MyBinder类型 
        IXXX  mBinder = IXXX.Stub.asInterface(ibinder);
        //通过实例对象来访问MyService的getMyName接口
        textView.setText(mService.getMyName());
    }
}

是不是感觉一切奥秘都在Stub的asInterface里面,该方法如下:

我们把绑定远程服务成功后返回的IBinder通过远程服务描述来判断是否在同一个进程,如果在同一进程就直接返回服务端的Stub对象本身,否则返回Stub.Proxy代理对象。因此前面访问本地服务的例子中为什么能够拿到Service的实例对象,因为这里直接返回了Stub本身。

2)、onTransact

Stub除了实现asInterface之外,还实现了onTransact方法,其主要作用就是进行任务分发,还记得Binder库里面的BnXXX吗?没错Stub作为java层的本地对象,当然类似BnXXX一样来解析分发来自客户端组件的请求,同样Stub也使用了多态的设计方式,即具体业务逻辑设计成抽象方法(BnXXX设计成虚函数)。如下代码:

3、Proxy代理对象

Proxy代理对象被定义成Stub的静态内部类,其对应于BpXXX,在跨进程通信使用过程中,客户端进程获取不到远程Service的对象实例(也可以理解成Stub),这个时候就可以通过创建代理对象Proxy,通过Proxy向Stub发起消息请求。其设计方式类似BpXXX,代码如下:

Proxy内部持有了两个比较重要的成员:sDefaultImpl和mRemote。sDefaultImpl属于Stub静态成员变量,仔细查看Stub代码会发现它在setDefaultImpl方法中设置,通常都是设置的自己,因此在非跨进程访问中Proxy可以直接通过sDefaultImpl来调用本地服务的接口。

mRemote在构造Proxy的时候被创建,通常在跨进程访问调用Stub的asInterface方法,该方法new了一个Proxy对象出来,这里传递的参数IBinder其实就是一个代理接口(类似BpBinder)。因此Proxy可以通过mRemote向远程服务发送消息。

提问onServiceConnected回调接口的IBinder这次参数是怎么来的?

三、应用框架层的ServiceManager

在讲解AIDL与native世界的关系之前,我们先看看Framwork层的ServiceManager。还记得native世界中的service manager进程吗?它被Android系统的第一个进程init启动,以c++代码编译出来的二进制文件运行在native世界,它维护了一个保存系统级服务的表,其他进程可以通过运行时binder库(当然也可以自己与binder驱动交互的方式)向service manager进程注册服务或查询服务。

那么现在问题来了,应用框架层中的Java世界的兄弟(例如应用程序)也想向系统注册服务或者查询服务该怎么办呢?我可以很负责的告诉你,Java世界并没有一个进程能够干这件事情,但是Androd系统在Framwork层实现了ServiceManager.java类,该类通过JNI方式调用native世界的C++代码,这样就可以与native世界的service manager进程进行通信。

1、Java世界的ServiceManager

ServiceManager.java被定义在framwork层,Java世界的兄弟如果想注册或获取系统服务(四大组件之一的Service),那么就可以通过它来完成。它的定义如下:

//frameworks/base/core/java/android/os/ServiceManager.java
public final class ServiceManager {
    //sServiceManager为框架层的ServiceManager的代理对象
    private static IServiceManager sServiceManager;
    //知名服务(如WM和AM)的缓存
    private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();
    private static IServiceManager getIServiceManager() {
        //ServcieManager的代理接口,单例模式
        if (sServiceManager != null) return sServiceManager;
        //ServiceManager的代理对象对应于native层的BpBinder(0)
        //ServiceManagerNative就是Java层的SM在JNI层的实现
        sServiceManager = ServiceManagerNative.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
        return sServiceManager;
    }
    public static void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority) {
        try {    //Java层的服务注册实际上调用了sServiceManager的addService接口
            getIServiceManager().addService(name, service, allowIsolated, dumpPriority);
        } catch (RemoteException e) { Log.e(TAG, "error in addService", e); }
    }
    public static IBinder checkService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {    //checkService同上
                return Binder.allowBlocking(getIServiceManager().checkService(name));
            }
        } catch (RemoteException e) {  return null; }
    }
    public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);    //从缓存中获取
            if (service != null) {
                return service;
            } else {
                return Binder.allowBlocking(rawGetService(name));
            }
        } catch (RemoteException e) { Log.e(TAG, "error in getService", e); }
        return null;
    }
}

从上面的代码不难发现,Java层的系统服务可以通过ServiceManager.addService和ServiceManager.getService向系统注册或查询,本质上实际调用的ServiceManagerNative.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()))的接口。

1)、获取native世界的BpBinder(0)

在研究ServiceManagerNative.asInterface之前,我们先看看它的参数到底是个什么东西?BinderInternal代码如下:

//frameworks/base/core/java/com/android/internal/os/BinderInternal.java
public class BinderInternal {
    //...省略
    //将当前线程加入到Binder线程池中堵塞运行
    public static final native void joinThreadPool();
    //获取当前进程的ServiceManager进程的代理
    public static final native IBinder getContextObject();
    public static final native void setMaxThreads(int numThreads);
}
//frameworks/base/core/jni/android_util_Binder.cpp
//BinderInternel的JNI函数注册
static const JNINativeMethod gBinderInternalMethods[] = {
    { "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },
    { "joinThreadPool", "()V", (void*)android_os_BinderInternal_joinThreadPool },
};
const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal";
//BinderInternal的getContextObject实现
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz) {
    //该函数参数为NULL,返回的IBinder类型其实是一个BpBinder(0)
    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
    //将BpBinder(0)转换成一个Java层的IBinder对象
    return javaObjectForIBinder(env, b);
}

如上代码可以看出BinderInternal.getContextObject()在JNI层实际上调用了ProcessState::self()->getContextObject(NULL)方法,还记得defaultServiceManager吗?native世界中的该方法其实返回的就是一个BpBinder(0),那么Java层如何使用这个对象呢?javaObjectForIBinder(env, b)就是来把它转换成一个Java世界的IBinder对象,具体流程详见后文。

2)、ServiceManagerNative/Proxy的实体和代理

Java世界除了有ServiceManager.java文件之外,同目录下还有一个ServiceManagerNative.java文件。上文可以看出Java世界的兄弟通过ServiceManager类向系统注册/查询服务,实际上是通过ServiceManagerNative.asInterface返回的对象完成,我们现在来看看这个对象到底是个什么玩意?ServiceManagerNative.java代码如下:

//frameworks/base/core/java/android/os/ServiceManagerNative.java
//ServiceManagerNative 与AIDL文件生成的Stub类一样继承于Binder,作为ServiceManager进程的本地对象
public abstract class ServiceManagerNative extends Binder implements IServiceManager {
    //descriptor在IServiceManager中定义,代表IServiceManager接口的名字
    static final String descriptor = "android.os.IServiceManager";
    static public IServiceManager asInterface(IBinder obj) {
        if (obj == null) return null;
        //传递进来的参数判断是否是IServiceManager,是就强制转换成IServiceManager
        IServiceManager in = (IServiceManager)obj.queryLocalInterface(descriptor);
        if (in != null) return in;
        //如果obj是BpBinder,那么就将其转换成ServiceManagerProxy
        return new ServiceManagerProxy(obj);
    }
    public ServiceManagerNative() {
        attachInterface(this, descriptor); //注册IServiceManager,descriptor的值在IServiceManager 中定义
    }
    //重写onTransact方法,个人认为ServiceManager根本都没有用该方法,完全是为了接口的默认实现
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags) {
        //...省略
        return false;
    }
    public IBinder asBinder() {
        return this;
    }
}
//ServiceManagerProxy 与AIDL文件生成的Stub.Proxy一样,作为ServiceManager进程的代理对象
class ServiceManagerProxy implements IServiceManager {
    //持有一个远程IBinder,这个IBinder在native对应BpBinder
    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;
    }
    public IBinder asBinder() {
        return mRemote;
    }
    public IBinder getService(String name) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        //跟native层的客户端组件BpXXX(代理对象)一样,主要干的事情就是利用远程BpBinder向Binder驱动程序发送请求,最终经过Binder驱动程序传递到服务端组件里面
        mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
        IBinder binder = reply.readStrongBinder();
        reply.recycle();
        data.recycle();
        return binder;
    }
    public void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        data.writeStrongBinder(service);
        data.writeInt(allowIsolated ? 1 : 0);
        data.writeInt(dumpPriority);
        mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
        reply.recycle();
        data.recycle();
    }
    public IBinder checkService(String name) throws RemoteException {
        //...
    }
    public String[] listServices(int dumpPriority) throws RemoteException {
        //...
    }
    public void setPermissionController(IPermissionController controller)  throws RemoteException {
        //...
    }
    private IBinder mRemote;
}

ServiceManagerNative.java的代码是不是跟AIDL文件生成的IXXX.java类似。IXXX.java文件中实现了两个类:IXXX.Stub和IXXX.Stub.Proxy;同样ServiceManagerNative.java文件中也实现了两个类:ServiceManagerNative和ServiceManagerProxy。它们分别对应于实体对象(对应于C++层的BBinder)和代理对象(对应于C++层的BpBinder)。

ServiceManagerNative.asInterface方法返回了一个IServiceManager对象,如下图该函数的参数是IBinder,在第6行判断该参数是否为IServiceManager,初始的时候obj其实是C++世界的一个BpBinder(0)转换成的IBinder对象,因此第6行判断失败,进入第9行通过obj生成一个ServiceManagerProxy对象。

ServiceManagerProxy继承于IServiceManager,内部持有了IBinder,没错这个remote就是上文讲解的与BpBinder(0)有着微妙关系的IBinder实例。如下图在实现getService这些业务接口的时候,居然通过remote发送消息来实现的。这种设计模式是不是很熟悉?典型的装饰模式,还记得native世界的BpBinder(0)与BpServiceManager的关系吗?这里等价于与C++层的BpBinder(0)有关系的IBinder与ServiceMangerProxy的关系。

ServiceManagerNative.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()))最终可以解读为new ServiceManagerProxy(BpBinder(0)有关系的IBinder)即ServiceManagerProxy内部成员mRemote本质是一个C++世界的BpBinder(0)它的getService和addService方法的实现,就是让BpBinder(0)向Binder驱动程序发送请求,Binder驱动程序最终转发到了service manager进程中并被解析处理。

2、Java世界与servicemanager进程交互

根据前面几个小节的介绍,我们就可以通过ServiceManager.java里面的几个静态方法来对service manager进程发送消息,即java层的类ServiceManager内部通过jni的方式,对native世界的service manager进程的一种封装。

无法理解吗?那我就通俗的讲解一下,service manager作为用户态的一个进程,在native世界被init进程启动,Java世界的同学也想与它进行通信,那么就需要通过jni的方式来到native世界,使用binder通信库或者自己创建BpBinder(0),然后通过BpBinder向service manager进程发起请求,这个过程是不是比较繁琐,那么ServiceManager.java就帮我们干了这件事情,我们只需要一行代码调用它的静态方法就把整个事情干完了,这样岂不是互利互赢呢。

  • 向系统注册服务,可以使用ServiceManager.addService(服务名,本地服务对象)向系统注册一个服务,(其中本地服务对象也是IBinder派生类)。例如SystemServer进程通过该方法向系统注册核心服务。如下:

  • 获取系统服务,可以使用ServiceManager.getService(服务名)得到一个系统服务的代理对象(也是IBinder的派生类)。注册一个服务。如下:

1)、Java世界的数据封装Parcel

上节中已经介绍了ServiceManager.addService/getService最终都是走的代理对象ServiceManagerProxy的代码,如下:(注意S的代码在这里有优化)

//frameworks/base/core/java/android/os/ServiceManagerNative.java
//ServiceManagerProxy 与AIDL文件生成的Stub.Proxy一样,作为ServiceManager进程的代理对象
class ServiceManagerProxy implements IServiceManager {
    //持有一个远程IBinder,这个IBinder在native对应BpBinder
    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;
    }
    public IBinder asBinder() {
        return mRemote;
    }
    public IBinder getService(String name) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
        //从reply中读取IXXX.Stub.Proxy(本质是代理对象),即service manager将查询到的服务封装在Parcel中
        IBinder binder = reply.readStrongBinder();
        reply.recycle();
        data.recycle();
        return binder;
    }
    /** 注册系统服务
     *  参数name:被注册的系统服务名称
     *  参数service:被注册的系统服务,在AIDL中通常是IXXX.Stub类型的对象实例
     *                              在框架层中通常是Binder.java的子类(java层的本地对象)
     */
    public void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        //向data中写入IXXX.Stub(本质是本地对象),即将服务封装到Parcel中,发送到service manager进程
        data.writeStrongBinder(service);
        data.writeInt(allowIsolated ? 1 : 0);
        data.writeInt(dumpPriority);
        mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
        reply.recycle();
        data.recycle();
    }
    private IBinder mRemote;
}

ServiceManagerProxy的实现我就不说了,但是值得注意的它持有的mRemote发送消息还是采用了Parcel,这里的Parcel当然是Java世界定义的,通过Parcel.obtain静态方法创建。

在addService中,调用它的writeStrongBinder方法把一个IBinder(通常是Binder.java类后文详细介绍)写入到Parcel,传递给service manager进程;在getService中,可以通过readStrongBinder方法读取一个IBinder,这个IBinder来自service manager进程的返回结果。

2)、Java世界Parcel的创建

//frameworks/base/core/java/android/os/Parcel.java
public final class Parcel {
    //在native世界删除Parcel.cpp对象
    private static native void nativeDestroy(long nativePtr);
    //在native世界创健Parcel.cpp对象
    private static native long nativeCreate();
    //字段mNativePtr很重要,保存了在c++层对应的Parcel.cpp对象首地址
    //即用来与native世界建立联系
    private long mNativePtr;
    //ServiceManagerProxy中创建的Parcel对象其实是new Parcel(0)
    public static Parcel obtain() {
        final Parcel[] pool = sOwnedPool;
        synchronized (pool) {
            Parcel p;
            for (int i=0; i<POOL_SIZE; i++) {
                p = pool[i];
                if (p != null) {
                    pool[i] = null;
                    p.mReadWriteHelper = ReadWriteHelper.DEFAULT;
                    return p;
                }
            }
        }
        //构造函数中发现该参数为0表示nativeCreate创建一个Parcel.cpp对象
        return new Parcel(0);
    }
    //构造Parcel,必须要传递nativePtr,即native的handle
    private Parcel(long nativePtr) {
        init(nativePtr);
    }
    private void init(long nativePtr) {
        if (nativePtr != 0) {
            mNativePtr = nativePtr;
            mOwnsNativeParcelObject = false;
        } else {
            //在native世界创健Parcel.cpp
            mNativePtr = nativeCreate();
            mOwnsNativeParcelObject = true;
        }
    }
    //销毁Parcel
    private void destroy() {
        if (mNativePtr != 0) {
            if (mOwnsNativeParcelObject) {
                nativeDestroy(mNativePtr);
                updateNativeSize(0);
            }
            mNativePtr = 0;
        }
        mReadWriteHelper = null;
    }
    protected void finalize() throws Throwable {
        destroy();
    }
}

如上代码Parcel有一个很重要的成员mNativePtr,该字段在构造方法中直接指定,如果传递为0就通过本地方法nativeCreate在native世界创建一个Parcel.cpp对象实例,并把它的首地址返回,这样做有什么意义呢?即在JNI的调用流程中,可以通过成员变量mNativePtr来找到C++世界中与他对应的Parcel.cpp对象。

也可以这样理解,想象一下应用开发中实例化Bitmap,除了在Java虚拟机中给他分配一个Bitmap.java对象之外,还会通过JNI在C++层分配一段内存。同理,应用层创建一个Parcel的时候,Java虚拟机会在堆中分配空间给这个Parcel.java对象,它在构造的时候通过JNI本地函数nativeCreate在C++层实例化一个Parcel.cpp对象,为了方便他们的管理,例如Java层销毁它的时候保证C++层占用的内存也需要被回收,那么同样需要在C++做一次delete操作,那么该销毁那段空间呢?还好mNativePtr保存了它在C++世界的地址,我们只需要通过JNI拿到mNativePtr这个值就行了。JNI方法如下:

//frameworks/base/core/jni/android_os_Parcel.cpp
//Parcel注册jni函数
static const JNINativeMethod gParcelMethods[] = {
    {"nativeCreate",              "()J", (void*)android_os_Parcel_create},
    {"nativeDestroy",             "(J)V", (void*)android_os_Parcel_destroy},
};
};
const char* const kParcelPathName = "android/os/Parcel";
int register_android_os_Parcel(JNIEnv* env)
{
    jclass clazz = FindClassOrDie(env, kParcelPathName);
    gParcelOffsets.clazz = MakeGlobalRefOrDie(env, clazz);
    //方便native世界得到Parcel.java的mNativePtr字段
    gParcelOffsets.mNativePtr = GetFieldIDOrDie(env, clazz, "mNativePtr", "J");
    gParcelOffsets.obtain = GetStaticMethodIDOrDie(env, clazz, "obtain", "()Landroid/os/Parcel;");
    gParcelOffsets.recycle = GetMethodIDOrDie(env, clazz, "recycle", "()V");
    return RegisterMethodsOrDie(env, kParcelPathName, gParcelMethods, NELEM(gParcelMethods));
}
//java层的nativeCreate对应的本地函数
static jlong android_os_Parcel_create(JNIEnv* env, jclass clazz)
{
    Parcel* parcel = new Parcel();
    //native世界创建了Parcel.cpp对象,并将其首地址返回给Parcel.java的mNativePtr字段
    return reinterpret_cast<jlong>(parcel);
}
//java层的nativeDestroy对应的本地函数
static void android_os_Parcel_destroy(JNIEnv* env, jclass clazz, jlong nativePtr)
{
    //native世界删除Parcel.cpp对象,java层需要把Parcel.java的mNativePtr字段传递下来
    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    delete parcel;
}

字段mNativePtr保存了对应native世界的一个Parcel.cpp对象实例首地址(指针)。这里ServiceManagerProxy通过Parcel.obtain()方法在native世界创建了Parcel.cpp对象实例,并把这个实例的首地址返回存储在了mNativePtr字段中,在以后的通信过程中两个世界都可以通过该字段作为桥梁。

3)、Parcel.readStrongBinder(读IBinder)

ServiceManagerProxy.getService方法实现了向service manager进程获取某个服务,其原理从Parcel中读取一个服务接口IBinder。但是在介绍service manager进程的时候我们知道,该进程在接收到其他进程查询某个服务的控制命令时并没有直接返回BpBinder(handle),而是直接返回了handle句柄值(不清楚的点击查看详情)。那么是如何读了一个IBinder出来呢?

//frameworks/base/core/java/android/os/Parcel.java
public final class Parcel {
    private static native IBinder nativeReadStrongBinder(long nativePtr);
    //返回一个IBinder,这个IBinder其实就是servicemanager进程收到查询服务的消息后返回的结果
    public final IBinder readStrongBinder() {
        return nativeReadStrongBinder(mNativePtr); //mNativePtr可以拿到native层的Parcel.cpp对象实例首地址
    }
}
//frameworks/base/core/jni/android_os_Parcel.cpp
static const JNINativeMethod gParcelMethods[] = {
    {"nativeReadStrongBinder",    "(J)Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder},
};
static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
{
    //找到native层的Parcel.cpp实例
    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    if (parcel != NULL) {
        //parcel->readStrongBinder():得到service manager传递过来的handle,并根据该值创建BpBinder(handle)
        //javaObjectForIBinder:将native世界的BpBinder转换成Java层的IBinder
        return javaObjectForIBinder(env, parcel->readStrongBinder());
    }
    return NULL;
}

如上代码,最终调用了JNI方法android_os_Parcel_readStrongBinder,第三个参数其实就是前文提到的很重要的mNativePtr字段,它的值是一个Parcel.cpp对象的首地址,因此可以直接把它强制转换成C++世界的Parcel指针。

因为service manager进程为native世界,因此它只能够把返回的句柄handle发送给同样为native世界的Parcel这个指针中,还记得native世界如何获取BpXXX吗?通过parcel->readStrongBinder()能够得到BpBinder(handle),不清楚的点击参考详情


//frameworks/native/libs/binder/Parcel.cpp
sp<IBinder> Parcel::readStrongBinder() const {
    sp<IBinder> val;
    readNullableStrongBinder(&val);
    return val;
}
status_t Parcel::readNullableStrongBinder(sp<IBinder>* val) const {
    return unflatten_binder(ProcessState::self(), *this, val);
}
status_t unflatten_binder(const sp<ProcessState>& proc, const Parcel& in, sp<IBinder>* out) {
    const flat_binder_object* flat = in.readObject(false);
    if (flat) {
        switch (flat->hdr.type) {
            case BINDER_TYPE_BINDER:
                *out = reinterpret_cast<IBinder*>(flat->cookie);
                return finish_unflatten_binder(NULL, *flat, in);
            case BINDER_TYPE_HANDLE:
                *out = proc->getStrongProxyForHandle(flat->handle);
                return finish_unflatten_binder(static_cast<BpBinder*>(out->get()), *flat, in);
        }
    }
    return BAD_TYPE;
}

最后通过函数javaObjectForIBinder将这个BpBinder(handle)转换成一个Java世界的IBinder对象并返回。到此,Java世界的兄弟进程通过ServiceManager.getService得到了一个与BpBinder有关系的IBinder.java实例,他们是什么关系呢?这就需要继续解读转换函数javaObjectForIBinder,后文将详细介绍。

4)、Parcel.writeStrongBinder(写IBinder)

ServiceManagerProxy.addService方法实现了向service manager进程注册某个服务,其原理向Parcel中写入了一个IBinder对象(通常是本地服务对象Binder.java的业务子类),然而位于native世界的service manager进程根本消化不了一个Java对象。代码如下:

//frameworks/base/core/java/android/os/Parcel.java
public final class Parcel {
    private static native void nativeWriteStrongBinder(long nativePtr, IBinder val);
    //此时val的本质是一个IXXX.Stub,即Binder.java的业务子类
    public final void writeStrongBinder(IBinder val) {
        nativeWriteStrongBinder(mNativePtr, val);
    }
}
//frameworks/base/core/jni/android_os_Parcel.cpp
static const JNINativeMethod gParcelMethods[] = {
    {"nativeWriteStrongBinder",   "(JLandroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder},
};
//参数nativePtr:Parcel.java中保存的native世界Parcel.cpp的对象实例
//参数object:是Java层的IBinder类,本质是一个IXXX.Stub,即Binder.java的业务子类
static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
{
    //找到native世界中的那个另一个自己
    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    if (parcel != NULL) {
        //ibinderForJavaObject(env, object):把Java层的IXXX.Stub转换成c++层的
        const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
        if (err != NO_ERROR)  signalExceptionForError(env, clazz, err);
    }
}

同样来到JNI层之后,通过mNativePtr找到对应的Parcel.cpp实例,先通过ibinderForJavaObject函数将Java世界传递下来的IBinder转换成C++层的IBinder实例,其本质是一个BBinder.cpp,转换过程详见后文。

//frameworks/native/libs/binder/Parcel.cpp
status_t Parcel::writeStrongBinder(const sp<IBinder>& val) {
    return flatten_binder(ProcessState::self(), val, this);
}
status_t flatten_binder(const sp<ProcessState>& /*proc*/, const sp<IBinder>& binder, Parcel* out) {
    //与binder驱动相关的数据结构
    flat_binder_object obj;
    if (binder != NULL) {
        IBinder *local = binder->localBinder();
        if (!local) {
            BpBinder *proxy = binder->remoteBinder();
            if (proxy == NULL)  ALOGE("null proxy");
            const int32_t handle = proxy ? proxy->handle() : 0;
            obj.hdr.type = BINDER_TYPE_HANDLE;
            obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
            obj.handle = handle;
            obj.cookie = 0;
        } else {
            //封装消息BINDER_TYPE_BINDER 表示当前数据类型为binder弱引用
            obj.hdr.type = BINDER_TYPE_BINDER;
            obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
            obj.cookie = reinterpret_cast<uintptr_t>(local);
        }
    } else {
        obj.hdr.type = BINDER_TYPE_BINDER;
        obj.binder = 0;
        obj.cookie = 0;
    }
    return finish_flatten_binder(binder, obj, out);
}

如上代码,接下来就跟native世界一样,使用Parcel.cpp的writeStrongBinder按binder驱动相关的协议封装消息,将自己的弱引用发送给binder驱动。到此,Java世界的兄弟进程通过ServiceManager.addService传递IXXX.Stub实例到JNI层,被函数ibinderForJavaObject转换成BBinder,最后将其封装成BINDER_TYPE_BINDER消息发送给binder驱动程序。

四、两个世界的转换

第一章我们使用了一个简单的AIDL示例,可以通过编写一个aidl文件来实现Service之间的访问;第二章中明白了它们之间能够进行访问,完全是因为Android编译器将aidl文件转换生成了对应的IXXX.Stub和IXXX.Stub.Proxy类;在第三章的介绍中我们已经知道了无论是Java世界还是C++世界都只有一个service manager进程,Java世界的兄弟想要向系统进行服务注册和查询服务,最终都通过ServiceManager.java封装的JNI方式来到了C++世界,与service manager进行通信。在本章将具体讲解它们在这两个世界到底是如何转的。

1、Java层的IBinder:Binder/BinderProxy

第二章提到了两个很重要的类:IXXX.Stub和IXXX.Stub.Proxy。其中Stub类继承于android.os.Binder,android.os.Binder实现了接口android.os.IBinder;Proxy内部持有了一个android.os.IBinder接口的mRemote成员。由此看来,Java世界的IBinder也至关重要。代码如下:

//frameworks/base/core/java/android/os/IBinder.java
public interface IBinder {
    int FIRST_CALL_TRANSACTION  = 0x00000001;
    int LAST_CALL_TRANSACTION   = 0x00ffffff;
    int FLAG_ONEWAY             = 0x00000001;     //异步binder
    //获取当前Binder支持的接口的规范名称
    public String getInterfaceDescriptor() throws RemoteException;
    //检测远程Binder对象是否存在
    public boolean pingBinder();
    //检测Binder所在进程是否还存在
    public boolean isBinderAlive();
    //尝试检索本地绑定对象实现的IInterface接口【可以理解成判断descriptor描述的服务是否是远程服务】
    public IInterface queryLocalInterface(String descriptor);
    public void dump(FileDescriptor fd, String[] args) throws RemoteException;
    public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException;
    //进行binder通信
    public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException;
    //定义死亡通知类
    public interface DeathRecipient {
        public void binderDied();
    }
    //注册死亡通知
    public void linkToDeath(DeathRecipient recipient, int flags) throws RemoteException;
    //注销死亡通知
    public boolean unlinkToDeath(DeathRecipient recipient, int flags);
}

1)、Java层的实体对象Binder

第二章提到IXXX.Stub其实是实体对象,为什么呢?因为它继承了android.os.Binder,它被定义在Binder.java文件中,代码如下:

//frameworks/base/core/java/android/os/Binder.java
public class Binder implements IBinder {
    // client端的进程id
    public static final native int getCallingPid();
    // client端的用户id
    public static final native int getCallingUid();    
    // 清除client端的进程id和用户id
    public static final native long clearCallingIdentity();
    // 获取c++层的实例
    private static native long getNativeBBinderHolder();
    // 指向c++层的JavaBBinderHolder对象的首地址
    // 即可以通过它找到C++世界对应的JavaBBinderHolder,它内部其实持有BBinder
    private final long mObject;
    public Binder() {
        mObject = getNativeBBinderHolder();
        NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mObject);
    }
    //Stub类构造方法中通过this关键字调用这个方法将自己与descriptor服务描述名进行绑定
    public void attachInterface(@Nullable IInterface owner, @Nullable String descriptor) {
        mOwner = owner;
        mDescriptor = descriptor;
    }
    //重写onTransact方法:初步解析来自远程客户端的命令
    //参数code:执行操作的代码,取值范围在FIRST_CALL_TRANSACTION和LAST_CALL_TRANSACTION之间(0x00000001~0x00ffffff)
    //参数data:传入的数据
    //参数reply:返回的数据
    //参数flags:额外的操作标志,取值为0或者FLAG_ONEWAY
    //注意:Stub通常重写了该方法,且判断完业务逻辑的功能码之后default里面通过super调用父类的这个方法
    protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
        //INTERFACE_TRANSACTION:获取描述符
        if (code == INTERFACE_TRANSACTION) {
            reply.writeString(getInterfaceDescriptor());
            return true;
        //DUMP_TRANSACTION:表示获取内部信息
        } else if (code == DUMP_TRANSACTION) {
            ParcelFileDescriptor fd = data.readFileDescriptor();
            String[] args = data.readStringArray();
            if (fd != null) dump(fd.getFileDescriptor(), args);
            if (reply != null)  reply.writeNoException();
            return true;
        //SHELL_COMMAND_TRANSACTION:执行一个shell命令
        } else if (code == SHELL_COMMAND_TRANSACTION) {
            ParcelFileDescriptor in = data.readFileDescriptor();
            ParcelFileDescriptor out = data.readFileDescriptor();
            ParcelFileDescriptor err = data.readFileDescriptor();
            String[] args = data.readStringArray();
            ShellCallback shellCallback = ShellCallback.CREATOR.createFromParcel(data);
            ResultReceiver resultReceiver = ResultReceiver.CREATOR.createFromParcel(data);
            try {
                if (out != null)  shellCommand(in != null ? in.getFileDescriptor() : null, out.getFileDescriptor(), err != null ? err.getFileDescriptor() : out.getFileDescriptor(), args, shellCallback, resultReceiver);
            } finally {
                IoUtils.closeQuietly(in);
                IoUtils.closeQuietly(out);
                IoUtils.closeQuietly(err);
                if (reply != null)  reply.writeNoException();
            }
            return true;
        }
        return false;
    }
    //默认的实现?
    public final boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
        if (data != null) data.setDataPosition(0);
        boolean r = onTransact(code, data, reply, flags);
        if (reply != null) reply.setDataPosition(0);
        return r;
    }
    //c++层回调方法:binder库收到来自驱动程序的消息时回调该方法将消息透传到java层,即android_util_Binder.cpp的onTrancat的切入点
    private boolean execTransact(int code, long dataObj, long replyObj, int flags) {
        BinderCallsStats binderCallsStats = BinderCallsStats.getInstance();
        BinderCallsStats.CallSession callSession = binderCallsStats.callStarted(this, code);
        Parcel data = Parcel.obtain(dataObj);
        Parcel reply = Parcel.obtain(replyObj);
        boolean res;
        final boolean tracingEnabled = Binder.isTracingEnabled();
        try {
            res = onTransact(code, data, reply, flags);
        } catch (RemoteException|RuntimeException e) {
            //...
        } finally {
            //....
        }
        checkParcel(this, code, reply, "Unreasonably large binder reply buffer");
        reply.recycle();
        data.recycle();
        StrictMode.clearGatheredViolations();
        binderCallsStats.callEnded(callSession);
        return res;
    }
}

android.os.Binder有个很重要的成员mObject,其实它跟第三章讲解的Parcel中的mNativePtr有异曲同工之意。它是一个long类型的变量,它实际上保存的是位于native世界的某个对象的首地址,那么在native世界是不是可以直接把它的值拿到将其转换成这个对象的指针呢?这种方式在Parcel都已经用烂了。

我们在看看它的构造方法,调用了本地方法getNativeBBinderHolder,并将其返回值赋值给了mObject,没错该本地方法其实就是去native世界实例化一个JavaBBinderHolder对象(c++对象),详情见后文。

android.os.Binder还有一个很重要的方法execTransact,根据注释翻译,它是一个C++的回调入口函数,它将通过JNI的方式,被C++世界的BBinder回调,即native中的BBinder接收到来自binder驱动程序的消息之后,它要么回调给native中的业务子类BnXXX,要么就通过jni的方式回调到Java世界的android.os.Binder.execTransact方法,该方法最终将任务交给onTransact初步处理,最后子类IXXX.Stub的onTransact方法进行具体业务逻辑处理。详情见后文。

2)、Java层的代理对象BinderProxy

android.os.BinderProxy也被定义在Binder.java文件中,它也继承于android.os.IBinder,其代码如下:

//frameworks/base/core/java/android/os/Binder.java
final class BinderProxy implements IBinder {
    //参数nativeData其实是native的BinderProxyNativeData首地址,其中有成员变量mObject,它将指向Java层虚拟机中的BinderProxy实例
    //参数iBinder是一个BpBinder
    private static BinderProxy getInstance(long nativeData, long iBinder) {
        BinderProxy result;
        try {
            result = sProxyMap.get(iBinder); //根据iBinder从列表sProxyMap获取对应BinderProxy
            if (result != null) return result;
            result = new BinderProxy(nativeData); //获取失败根据c++层传递的nativeData创建
        } catch (Throwable e) { /*...*/}
        //nativeData为native层的一个结构体变量,result是一个创建好的BinderProxy实例
        //该方法能够将二者绑定起来,即native层就可以通过nativeData来找到上面创健的BinderProxy实例
        NoImagePreloadHolder.sRegistry.registerNativeAllocation(result, nativeData);
        sProxyMap.set(iBinder, result);  //保存到列表中,方便下次使用
        return result;
    }
    private BinderProxy(long nativeData) {
        mNativeData = nativeData;
    }
    //指向C++层的一个BpBinder对象的首地址
    private final long mNativeData;
    //向Java层的实体对象发送消息,即向android.os.Binder发送消息
    public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        try {
            return transactNative(code, data, reply, flags);
        } finally { }
    }
    public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeFileDescriptor(fd);
        data.writeStringArray(args);
        try {
            transact(DUMP_TRANSACTION, data, reply, FLAG_ONEWAY);
        } finally {
            data.recycle();
            reply.recycle();
        }
    }
    public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver) throws RemoteException {
        //...
        try {
            transact(SHELL_COMMAND_TRANSACTION, data, reply, 0);
            reply.readException();
        } finally {
            data.recycle();
            reply.recycle();
        }
    }
}

android.os.BinderProxy有个很重要的成员mNativeData,同android.os.Binder的mObject一样,mNativeData存储的也是一个地址(指针),该地址指向C++世界的某个BpBinder,详情见后文。

android.os.BinderProxy的构造方法被私有化且必须传递参数初始化mNativeData,即该对象不允许直接被构造,因为构造它之前必须指定与他绑定的BpBinder的首地址。实际上native世界中JNI的方式回调了它的静态方法getInstance构造的BinderProxyd实例,详情见后文。

虽然android.os.BinderProxy在native世界中被构造,但它还是被分配存储在Java世界中,最终又通过transactNative回到JNI世界中的BpBinder向对应的BBinder发送消息。这个流程是不是很变态,详情见后文。

2、JNI层的IBinder:Binder/BinderProxy

第一节中介绍了android.os.Binder.java,其内部实现了两个比较重要的类Binder和BinderProxy,它们都有对应的native方法。根据Android的架构,那么其本地方法就应该实现在frameworks/base/core/jni/android_util_Binder.cpp文件中,如下代码:

//frameworks/base/core/jni/android_util_Binder.cpp
int register_android_os_Binder(JNIEnv* env) {
    //注册android.os.Binder类对应的jni方法
    if (int_register_android_os_Binder(env) < 0) return -1;
    //注册android.os.BinderInternal类的jni方法
    //第三章ServiceManager已经介绍了BinderInternal中有关于ServiceManager相关方法
    if (int_register_android_os_BinderInternal(env) < 0)  return -1;
    //注册android.os.BinderProxy类的jni方法
    if (int_register_android_os_BinderProxy(env) < 0) return -1;
    //...
    return 0;
}

1)、JNI层的Binder

//frameworks/base/core/jni/android_util_Binder.cpp
static const JNINativeMethod gBinderMethods[] = {
    //Binder.java构造方法通过该函数在C++世界创建BBinder的句柄
    { "getNativeBBinderHolder", "()J", (void*)android_os_Binder_getNativeBBinderHolder },
    //Binder.java对象实例在被虚拟机销毁将触发函数getNativeFinalizer销毁C++世界的资源
    { "getNativeFinalizer", "()J", (void*)android_os_Binder_getNativeFinalizer },
};
const char* const kBinderPathName = "android/os/Binder";
//android.os.Binder.java的注册
static int int_register_android_os_Binder(JNIEnv* env)
{
    jclass clazz = FindClassOrDie(env, kBinderPathName);
    //gBinderOffsets.mClass表示类android.os.Binder
    //后续中经常通过它来判断一个jobject是否是android.os.Binder类型
    gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
    //gBinderOffsets.mExecTransact表示android.os.Binder.java的execTransact方法
    //后续中BBinder.cpp将通过JNI方式回调Java层绑定的Binder.java对象的execTransact方法
    gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z");
    //gBinderOffsets.mObject表示android.os.Binder.java的mObject成员
    //前文已经说得很明白了它的值其实就是C++世界的BBinder的地址,可通过JNI方式拿到mObject值就找到了位于C++世界与其绑定的BBinder了
    gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J");
    //注册Java层与JNI层的方法映射
    return RegisterMethodsOrDie(env, kBinderPathName, gBinderMethods, NELEM(gBinderMethods));
}
//android.os.Binder.java在构造的时候,JNI层也new一个JavaBBinderHolder.cpp对象
static jlong android_os_Binder_getNativeBBinderHolder(JNIEnv* env, jobject clazz)
{
    JavaBBinderHolder* jbh = new JavaBBinderHolder();
    return (jlong) jbh;
}
static void Binder_destroy(void* rawJbh)
{
    JavaBBinderHolder* jbh = (JavaBBinderHolder*) rawJbh;
    delete jbh;
}
//android.os.Binder.java在销毁的时候,JNI层delete了一个JavaBBinderHolder.cpp对象
JNIEXPORT jlong JNICALL android_os_Binder_getNativeFinalizer(JNIEnv*, jclass) {
    return (jlong) Binder_destroy;
}

如上代码,需要特别记住的是gBinderOffsets结构体的几个成员含义:

  • gBinderOffsets.mClass:代表android.os.Binder类,可以通过它来判断一个Java世界的对象jobject是否是android.os.Binder的派生类
  • gBinderOffsets.mExecTransact :代表android.os.Binder类的execTransact方法,后文将介绍native世界的BBinder接收到binder驱动透传来的消息之后,通过它回调Java世界的android.os.Binder.execTransact方法来将任务消息分发到Java世界
  • gBinderOffsets.mObject:代表android.os.Binder类的mObject字段,该字段指向native世界对应的JavaBBinderHolder对象,在native世界中可以通过它的值来找到JavaBBinderHolder

除此之外介绍了两个比较重要的本地方法:getNativeBBinderHolder用来在native世界创建了JavaBBinderHolder对象,getNativeFinalizer用来销毁native世界的JavaBBinderHolder对象。我们先来看看JNI层定义的JavaBBinderHolder是个撒子玩意,如下代码:

//frameworks/base/core/jni/android_util_Binder.cpp
class JavaBBinderHolder
{
public:
    //构造方法为空,即该对象被实例化的时候什么都没有干,只有调用了其get函数才会真正的拥有一个JavaBBinder
    sp<JavaBBinder> get(JNIEnv* env, jobject obj) {
        AutoMutex _l(mLock);
        sp<JavaBBinder> b = mBinder.promote();
        if (b == NULL) {
            b = new JavaBBinder(env, obj);
            mBinder = b;
        }
        return b;
    }
    sp<JavaBBinder> getExisting() {
        AutoMutex _l(mLock);
        return mBinder.promote();
    }
private:
    Mutex           mLock;
    wp<JavaBBinder> mBinder;  //弱引用JavaBBinder,在第一次被get的时候将会被实例化
};

如上代码,JavaBBinderHolder只是一个句柄,具体事务其实交给它持有的JavaBBinder类型的mBinder,它被实例化后并没有立即创建mBinder,而是第一次被调用get函数才被创建。那我们继续深入,看看JavaBinder是个什么鬼?代码如下:

//frameworks/base/core/jni/android_util_Binder.cpp
//JavaBBinder其实就是一个BBinder,是不是跟BnXXX一样
class JavaBBinder : public BBinder
{
public:
    //构造函数很重要,第二个参数object属性JNI的同学一定知道它就是Java层进行JNI调用的对象本身,即这里就是android.os.Binder.java,直接将其初始化给mObject
    JavaBBinder(JNIEnv* env, jobject object) : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)) {
        gNumLocalRefsCreated.fetch_add(1, std::memory_order_relaxed);
        gcIfManyNewRefs(env);
    }
protected:
    //析构函数,通过JNI方式删除了与Java世界的android.os.Binder的引用
    virtual ~JavaBBinder() {
        gNumLocalRefsDeleted.fetch_add(1, memory_order_relaxed);
        JNIEnv* env = javavm_to_jnienv(mVM);
        env->DeleteGlobalRef(mObject);
    }
    //重写BBinder的onTransact函数
    //还记得吗?BBinder开启线程池轮询之后,就会轮询binder驱动程序透传的消息
    //BBinder得到这个消息之后就会进行任务分发给onTransact函数
    //子类如果想实现不同业务逻辑,那么可以重写onTransact方法
    virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) {
        JNIEnv* env = javavm_to_jnienv(mVM);
        IPCThreadState* thread_state = IPCThreadState::self();
        const int32_t strict_policy_before = thread_state->getStrictModePolicy();
        //通过JNI回调一个Java世界的函数,这个函数信息被保存在gBinderOffsets.mExecTransact
        //还记不记得它的值其实就是android.os.Binder.java的execTransact方法
        //即JavaBBinder收到来自binder驱动程序的消息之后,通过JNI方式直接回调了Java世界的android.os.Binder的execTransact方法
        jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact, code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);
        return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;
    }
private:
    JavaVM* const   mVM; //虚拟机环境,通过它才能够与虚拟机里面的Java世界建立联系
    jobject const   mObject;  // 保存了Java世界的一个对象,其实就是android.os.Binder.java对象
};

众所周知native世界的BBinder将接受到来自binder驱动的消息,它会将消息分发给业务子类BnXXX的onTransact函数进行处理(具体业务逻辑的实现),当然这里的业务子类不再是BnXXX,而是JavaBBinder,根据名字也知道这是专门针对Java层的BBinder,那么它如何重写onTransact的呢?

如上代码,通过JNI的方式,回调了mObject对象的gBinderOffsets.mExecTransact方法,其中mObject对象暂时认为是Java世界的android.os.Binder的派生类,例如IXXX.Stub,至于为什么详情见后文;其中gBinderOffsets.mExecTransact存储的方法名是execTransact。

恍然大悟了吗?IXXX.Stub继承于android.os.Binder类,在JNI层必定持有了一个JavaBBinderHolder,当它的get方法第一次被触发的时候,将实例化一个JavaBBinder出来,即可以认为每一个IXXX.Stub在native世界都对应一个JavaBBinder,因为它与BnXXX一样也是继承于BBinder,因此它也能接收来自binder驱动透传过来的消息,并触发JavaBBinder的onTransact函数,在该函数中通过JNI的方式回调了Java世界的IXXX.Stub的execTransact方法,该方法中IXXX.Stub又将任务消息分发给自己的onTransact处理,最终交给了IXXX.java定义的接口

2)、JNI层的BinderProxy

//frameworks/base/core/jni/android_util_Binder.cpp
static const JNINativeMethod gBinderProxyMethods[] = {
    //android.os.BinderProxy向android.os.Binder发送消息的本地方法
    //在jni层实现其实找到绑定的BpBinder,通过BpBinder发送消息给binder驱动程序
    {"transactNative",      "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},
    //android.os.BinderProxy在虚拟机被销毁的时候触发JNI层销毁对应的资源
    {"getNativeFinalizer",  "()J", (void*)android_os_BinderProxy_getNativeFinalizer},
};
const char* const kBinderProxyPathName = "android/os/BinderProxy";
static int int_register_android_os_BinderProxy(JNIEnv* env) {
    clazz = FindClassOrDie(env, kBinderProxyPathName);
    //gBinderProxyOffsets.mClass代表android.os.BinderProxy
    gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
    //gBinderProxyOffsets.mGetInstance代表android.os.BinderProxy的静态方法getInstance
    //后续中native世界可以通过它创建一个Java世界的BinderProxy对象
    gBinderProxyOffsets.mGetInstance = GetStaticMethodIDOrDie(env, clazz, "getInstance", "(JJ)Landroid/os/BinderProxy;");
    //gBinderProxyOffsets.mNativeData代表android.os.BinderProxy的mNativeData字段
    //该字段实际上保存了一个位于native世界的BpBinder(handle)对象的首地址
    //后续中可以通过JNI方式得到该字段值并将其转换成BpBinder向BBinder发送消息
    gBinderProxyOffsets.mNativeData = GetFieldIDOrDie(env, clazz, "mNativeData", "J");
    //android.os.BinderProxy的JNI方法注册
    return RegisterMethodsOrDie(env, kBinderProxyPathName, gBinderProxyMethods, NELEM(gBinderProxyMethods));
}
//销毁对应资源,其实销毁的是一个BpBinder(handle)
static void BinderProxy_destroy(void* rawNativeData) {
    AutoMutex _l(gProxyLock);
    BinderProxyNativeData * nativeData = (BinderProxyNativeData *) rawNativeData;
    delete nativeData;
    IPCThreadState::self()->flushCommands();
    --gNumProxies;
}
JNIEXPORT jlong JNICALL android_os_BinderProxy_getNativeFinalizer(JNIEnv*, jclass) {
    return (jlong) BinderProxy_destroy;
}

如上代码,需要特别记住的是gBinderProxyOffsets结构体的几个成员含义:

  • gBinderProxyOffsets.mClass:代表android.os.BinderProxy类,可以通过它来判断一个Java世界的对象jobject是否是android.os.BinderProxy的派生类
  • gBinderProxyOffsets.mGetInstance:代表android.os.BinderProxy类的静态方法getInstance,后文将介绍native世界的如何通过JNI的方式在Java层构造一个BindProxy类
  • gBinderProxyOffsets.mNativeData:代表android.os.BinderProxy类的mNativeData字段,该字段指向native世界对应的BpBinder(handle)对象,在native世界中可以通过它的值来找到相关联的BpBinder。后文将介绍为什么会是一个BpBinder

除此之外介绍了一个比较重要的本地方法:transactNative,当android.os.BinderProxy需要向android.os.Binder发起请求的时候,将通过该方法进入到JNI层,通过android.os.BinderProxy的mNativeData字段找到关联的BpBinder,最终由BpBinder向binder驱动程序发起请求。其中getBPNativeData(env, obj)->mObject.get()的返回值是一个BpBinder详情见后文,如下代码:

//frameworks/base/core/jni/android_util_Binder.cpp
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj, jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
    //转换请求数据:Java世界的Parcel转换成C++世界的Parcel
    Parcel* data = parcelForJavaObject(env, dataObj);
    if (data == NULL)  return JNI_FALSE;
    //转换返回数据:Java世界的Parcel转换成C++世界的Parcel
    Parcel* reply = parcelForJavaObject(env, replyObj);
    if (reply == NULL && replyObj != NULL)  return JNI_FALSE;
    //将Java世界的IBinder转换成C++世界的IBinder,转换后其实是一个BpBinder(handle)
    IBinder* target = getBPNativeData(env, obj)->mObject.get();
    if (target == NULL) { //转换失败抛出一个Java世界的异常
        jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");
        return JNI_FALSE;
    }
    //通过BpBinder向binder驱动程序发送请求
    status_t err = target->transact(code, *data, reply, flags);
    if (err == NO_ERROR) {
        return JNI_TRUE;
    } else if (err == UNKNOWN_TRANSACTION) {
        return JNI_FALSE;
    }
    return JNI_FALSE;
}

3、汇总两个世界的IBinder

根据前两节的分析,Java世界的android.os.IBinder:包括android.os.Binder和android.os.BinderProxy,其中IXXX.Stub也是android.os.Binder的子类。C++世界的sp<IBinder>其实是一个智能指针:包括本地对象BBinder和代理对象BpBinder(详情请点击我),其中处理BnXXX是BBinder的业务子类之外,JavaBBinder也是BBinder针对Java层提供的一个子类

那么一个BBinder如何转换成一个android.os.Binder的呢?一个BpBinder是如何转换成一个android.os.BinderProxy的呢?我们可以看看函数ibinderForJavaObject和函数javaObjectForIBinder。

4、ibinderForJavaObject

函数ibinderForJavaObject被定义在android_util_Binder.cpp文件中,从函数定义就可以看出返回值为一个C++世界的智能指针sp<IBinder>,函数参数为Java世界的虚拟机env和jobject,在根据函数名可以知道该函数用来将一个Java世界的IBinder转换成一个C++世界的IBinder。如下代码:

//frameworks/base/core/jni/android_util_Binder.cpp
sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
    if (obj == NULL) return NULL;
    //判断obj是否是android.os.Binder.java类型
    //gBinderOffsets.mClass存储的信息就是android.os.Binder
    if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
        //gBinderOffsets.mObject存储的信息是android.os.Binder的mmObject字段
        //该字段存储了native世界的JavaBBinderHolder的首地址
        JavaBBinderHolder* jbh = (JavaBBinderHolder*) env->GetLongField(obj, gBinderOffsets.mObject);
        //JavaBBinderHolder的get方法将返回一个C++层的IBinder,这里是返回一个JavaBBinder
        return jbh->get(env, obj);
    }
    //判断obj是否是android.os.BinderProxy.java类型
    //gBinderProxyOffsets.mClass存储的信息就是android.os.BinderProxy
    if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
        //实际返回的BpBinder
        return getBPNativeData(env, obj)->mObject;
    }
    return NULL;
}

1)、android.os.Binder->JavaBBinder

如果obj是android.os.Binder,那么通过JNI的方式拿到它被构造的时候在JNI层创建的JavaBBinderHolder对象(如何拿到呢?请详细阅读本章第一节),最终调用了该对象的get方法,如下第10行在第一次被调用的时候将实例化一个JavaBBinder并返回

2)、android.os.BinderProxy->BpBinder

如果obj是android.os.BinderProxy,那么通过getBPNativeData函数返回它在JNI层持有的资源,如下结构体包含一个sp<IBinder>,其实是一个BpBinder,至于为什么请参考后文。但是我并没有看到那个地方调用函数ibinderForJavaObject是用来转换android.os.BinderProxy的(有知道的同学请告知一下)!

3)、承接android.os.Parcel.writeStringBinder

函数ibinderForJavaObject主要有如上两部分逻辑,我们再来看看它在什么地方被调用过?如下图,还记得第三章的内容吗?当Java世界的某个进程可以通过静态方法ServiceManagerProxy.addService来注册系统服务,需要向service manager传递一个android.os.Binder,该静态方法中通过writeStrongBinder将其封装在android.os.Parcel中,如今看来Java层在封装的过程,其实调用了JNI层的ibinderForJavaObject函数将这个android.os.Binder转换成一个JavaBBinder,再按照native世界的binder进程通信库的流程进行注册。

5、javaObjectForIBinder

函数javaObjectForIBinder也被定义在android_util_Binder.cpp文件中,从函数定义就可以看出返回值类型为jobject(其实就是Java世界的android.os.IBinder),函数参数为C++世界的sp<IBinder>,即该参数可能是BBinder也可能是一个BpBinder,在根据函数名可以知道该函数用来将一个C++世界的IBinder转换成一个Java世界的IBinder。如下代码:

//frameworks/base/core/jni/android_util_Binder.cpp
struct BinderProxyNativeData {
    sp<IBinder> mObject; // The native IBinder proxied by this BinderProxy.
    sp<DeathRecipientList> mOrgue;  // Death recipients for mObject.
};
//BinderProxy持有的native世界资源是一个BinderProxyNativeData结构体,在javaObjectForIBinder中被实例化
//结构体BinderProxyNativeData存储了一个BpBinder
BinderProxyNativeData* getBPNativeData(JNIEnv* env, jobject obj) {
    return (BinderProxyNativeData *) env->GetLongField(obj, gBinderProxyOffsets.mNativeData);
}
static BinderProxyNativeData *gNativeDataCache;    //缓存上次的BinderProxyNativeData 
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
    if (val == NULL) return NULL;
    //如果参数val是一个C++世界的JavaBBinder对象
    if (val->checkSubclass(&gBinderOffsets)) {
        jobject object = static_cast<JavaBBinder*>(val.get())->object();
        return object;
    }
    //如果参数val是一个C++世界的BpBinder对象
    AutoMutex _l(gProxyLock);
    //得到上次缓存的BinderProxyNativeData结构体,否则实例化
    BinderProxyNativeData* nativeData = gNativeDataCache;
    if (nativeData == nullptr) nativeData = new BinderProxyNativeData();
    //通过JNI的方式回调Java世界的gBinderProxyOffsets.mGetInstance方法
    //其中gBinderProxyOffsets.mGetInstance存储的是android.os.BinderProxy静态方法getInstance用来创建一个android.os.BinderProxy对象
    //其中第一个参数为结构体nativeData的首地址
    //其中第二个参数val.get()返回的是一个BpBinder的首地址,为什么呢?val为智能指针,它的get函数返回智能指针持有的原始对象
    //其中object是一个android.os.BinderProxy对象
    jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get());
    if (env->ExceptionCheck()) {    //创建失败
        gNativeDataCache = nullptr;
        return NULL;
    }
    //检测上面创建的的android.os.BinderProxy的mNativeData字段是否存储与之关联的native世界的BinderProxyNativeData结构体,如果不是就重新纠正一下
    BinderProxyNativeData* actualNativeData = getBPNativeData(env, object);
    if (actualNativeData == nativeData) {
        nativeData->mOrgue = new DeathRecipientList;
        nativeData->mObject = val;
        gNativeDataCache = nullptr;
        ++gNumProxies;
        if (gNumProxies >= gProxiesWarned + PROXY_WARN_INTERVAL)  gProxiesWarned = gNumProxies;
    } else {
        gNativeDataCache = nativeData;
    }
    //最后返回上面创建的android.os.BinderProxy
    return object;
}

1)、JavaBBinder->android.os.Binder

如果参数val是一个JavaBBinder,那么就执行下图逻辑。下面的几行代码虽然简单,但是我也看了几遍才看明白到底是怎么回事。

首先第648行包含的信息就很多,val->checkSubclass从名字看就知道判断当前是否为某个类的子类,该函数在IBinder.cpp中被定义成虚函数,既然是虚函数那么就应该是子类实现,我找到了JavaBBinder的实现如下图,判断参数与gBinderOffsets的地址相同就为真,gBinderOffsets被初始化为android.os.Binder的相关信息,是不是觉得很奇怪。即如果val是一个JavaBBinder,那么这里必定被判断成一个本地对象,进入第650行的逻辑

然后第650行包含的信息也不少,可以将这行代码拆分成三部分。最先执行的是val.get(),因为参数val是一个sp<IBinder>类型,因此返回的必定是一个IBinder指针;然后执行static_cast语句强制转换成JavaBBinder类型的指针,既然已经进入第650行,那么这里的强转肯定是能够成功的;最终调用了JavaBBinder的object函数,如上图该函数返回的mObject,成员mObject就是与之关联的Java层对象(详见本章第一节)。

2)、BpBinder->android.os.BinderProxy

如果参数val不是JavaBBinder类型,就应该执行下图的逻辑,这里我们假设val是一个BpBinder,至于为什么是BpBinder详见下一个小节。

如上图最重要的为第664行,回调了一个Java的静态方法,gBinderProxyOffsets被初始化为android.os.BinderProxy,因此这里是调用android.os.BinderProxy的静态方法getInstance用来创建一个android.os.BinderProxy对象。除此之外还传递了两个参数:

  • 第一个参数nativeData为第659行的BinderProxyNativeData结构体指针(该指针要么从缓存中获取要么直接new出来了),如下图最终在Java层实例化了一个android.os.BinderProxy对象,并把这个结构体指针保存在了android.os.BinderProxy的字段mNativeData,还记得本章第一节吗,mNativeData作为Java世界访问C++世界的桥梁,从这里看他们的联系就是在创建的时候就建立好了。这里有点绕,多看几遍把。
  • 第二个参数iBinder也是一个地址,且传递了javaObjectForIBinder函数的val,姑且认为是一个BpBinder,上图第1076行把这个BpBinder的首地址放在了BinderProxy维护的的一个Map中,方便下次调用直接获取该BpBinder。

接下来的代码就不是重点了,只是防止第664行创建的android.os.BinderProxy中字段mNativeData是不是第659行创建的BinderProxyNativeData结构体的地址,如果不是就赋值,这么做完全是为了一次校验纠正的操作,因为从此以后Java世界的BinderProxy与native世界的BinderProxyNativeData结构体就绑在一起了。最后将创建的这个android.os.BinderProxy返回。

3)、承接android.os.Parcel.readStrongBinder

函数javaObjectForIBinder主要有如上两部分逻辑,我们再来看看它在什么地方被调用过?如下图,还记得第三章的内容吗?当Java世界的某个进程可以通过静态方法ServiceManagerProxy.getService来获取指定系统服务,servicemanager进程返回的并不是一个对象,而是一个handle句柄值,C++层的Parcel在读取的时候通过该handle句柄值创建了一个BpBinder(handle),最终将这个BpBinder作为参数调用了Java层的Parcel.readStrongBinder方法,在该方法中直接将这个BpBinder通过javaObjectForIBinder转换成BinderProxy。

除此之外,在第三章讲解ServiceManager的时候,获取servicemanager进程的代理BinderInternal.getContextObject(),即BpBinder(0)的时候,使用了ServiceManagerNative.asInterface方法将BpBinder(0)转换成一个BinderProxy。

五、恍然一梦

经过前面第一章的讲解,让我们对AIDL有了一个基本的认识,即可以通过AIDL接口来实现两个进程之间(两个应用程序之间)的远程Service访问。

经过第二章的讲解,让我们对AIDL的基本原理有了一个认知,原来它们能够访问远程Service,完全是因为编译的时候将AIDL文件生成了两个分别继承于android.os.Binder的IXXX.Stub类和持有android.os.BinderProxy的IXXX.Stub.Proxy类。

经过第三章的讲解,让我们对service manager进程在Java世界提供的代理ServiceManager.java有了一个了解,原来框架层并没有为我们在提供一个service manager进程,而是通过JNI的方式来到native世界,沿用了native世界的binder通信库的机制。

最终第四章的讲解,让我们看清了两个世界之间奇妙的联系,即第二章提到的android.os.Binder和android.os.BinderProxy与native世界的BBinder和BpBinder之间的关系。

上面四章用到的成员以及他们的关系可以用下图表示:

1、IXXX.Stub.Proxy如何持有android.os.BinderProxy?

难道就这样完了吗?细思极恐,在第二章的介绍中IXXX.Stub.Proxy使用了代理模式,向服务端组件发送消息的任务代理给了内部android.os.IBinder类型的成员mRemote,然而后文中我只介绍了一个android.os.BinderProxy。这个mRemote的真实面目是一个android.os.BinderProxy吗?没错,确实是,接下来我们来剖析一下。

1)、ContxtImpl绑定服务

在第一章的AIDL示例中,客户端应用程序使用了Activity的bindService方法来绑定一个Service,如下图,当链接指定Service成功之后就会回调方法onServiceConnected,并会传回一个IBinder。

如果被绑定的Service与当前Activity属于同一个应用程序(同进程),将返回Service的onBind方法返回的那个IBinder对象本身,这个对象在Java层的表现就是android.os.Binder的子类,即AIDL中是IXXX.Stub(存根对象),它在native世界持有一个JavaBBinder(它直接继承于BBinder)。这个时候客户端可以随便操作这个IXXX.Stub,因为中间不存在跨进程通信,也不需要向service manager进程发送消息,直接以操作普通对象的方式调用这个IXXX.Stub的任意public接口。

如果被绑定的Service与当前Activity不属于同一个应用程序,那么将返回这个Service中的IBinder对象的代理,该对象在Java层的表现就是android.os.BinderProxy,它是在Parcel.readStrongBinder的过程中被创建(从ServiceManager中读取IBinder的过程),应用程序可以通过IXXX.Stub.asInterface将其装饰成一个IXXX.Stub.Proxy(代理对象),除此之外,它在native世界持有一个BpBinder(handle)。这个时候客户端调用定义好的接口时,实际是通过BpBinder向binder驱动程序发送消息,并接收返回数据。最终透传到IXXX.Stub.Proxy。

这里我们先看看Activity的bindService方法,众所周知,它的具体实现是在其实现类ContextImpl中,我们先看看该方法的实现:

//frameworks/base/core/java/android/app/ContextImpl.java
class ContextImpl extends Context {
    //代表当前主线程,在ContextImpl的构造方法中被初始化
    final @NonNull ActivityThread mMainThread;
    //代表当前用户,在ContextImpl的构造方法中被初始化
    private final @NonNull UserHandle mUser;
    @Override
    public UserHandle getUser() {
        return mUser;
    }
   @Override
    public boolean bindService(Intent service, ServiceConnection conn, int flags) {
        warnIfCallingFromSystemProcess();
        return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), getUser());
    }
    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler handler, UserHandle user) {
        IServiceConnection sd;
        if (mPackageInfo != null)  sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
        validateServiceIntent(service);
        try {
            IBinder token = getActivityToken();
            if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null && mPackageInfo.getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH)  flags |= BIND_WAIVE_PRIORITY;
            service.prepareToLeaveProcess(this);
            //通过ActivityManager其实是客户端组件,对应AMS
            int res = ActivityManager.getService().bindService(mMainThread.getApplicationThread(), getActivityToken(), service,  service.resolveTypeIfNeeded(getContentResolver()), sd, flags, getOpPackageName(), user.getIdentifier());
            return res != 0;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
}

2)、ActivityManager绑定服务

如上小节带, ContextImpl最终调用了ActivityManager.getService().bindService来绑定一个服务。ActivityManager其实是一个典型的C/S架构,也沿用了binder那套机制。ActivityManager其实也沿用了AIDL接口,如下图:

其中IActivityManager.aidl定义了进程间通信的接口,其中接口bindService也在其中,如下:

我们再来看看ActivityManager.getService()的代码,返回一个IActivityManager类型,其本质是个android.os.BinderProxy,它在native世界持有了一个BpBinder(handle),最终ActivityManager.Stub.asInterface将其进行包装(IXXX.Stub.Proxy),如下:

//frameworks/base/core/java/android/app/ActivityManager.java
@SystemService(Context.ACTIVITY_SERVICE)
public class ActivityManager {
    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }
    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    //ServiceManager.getService(XXX)返回的跟XXX相关的BinderProxy对象
                    //且在native世界持有BpBinder(handle)
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    //将这个持有BpBinder(handle)的BinderProxy对象装饰成为一个IXXX.Stub.Proxy对象,当然这里是一个IAcitivityManager的业务代理子类Proxy
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };
    //...省略
}

根据第三章和第四章的内容,ActivityManager.getService()返回的是IActivityManager.Stub.Proxy代理对象,那么调用它的的接口bindService,实际上是向IActivityManager.Stub发送了消息,最终处理的地方是在其子类ActivityManagerService里面,如下:

//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public class ActivityManagerService extends IActivityManager.Stub implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    final ActiveServices mServices;
    //客户端发起绑定服务的时候将调用该方法
    public int bindService(IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, int flags, String callingPackage, int userId) throws TransactionTooLargeException {
        enforceNotIsolatedCaller("bindService");
        synchronized(this) {
            return mServices.bindServiceLocked(caller, token, service, resolvedType, connection, flags, callingPackage, userId);
        }
    }
    //客户端发起取消绑定的时候将调用该方法
    public boolean unbindService(IServiceConnection connection) {
        synchronized (this) {
            return mServices.unbindServiceLocked(connection);
        }
    }
    //客户端发起bindService之后,找到了被指定的Service,会发起该方法发布这个Service的IBinder
    public void publishService(IBinder token, Intent intent, IBinder service) {
        synchronized(this) {
            if (!(token instanceof ServiceRecord))  throw new IllegalArgumentException("Invalid service token");
            mServices.publishServiceLocked((ServiceRecord)token, intent, service);
        }
    }
    public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
        synchronized(this) {
            mServices.unbindFinishedLocked((ServiceRecord)token, intent, doRebind);
        }
    }
    public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
        synchronized(this) {
            if (!(token instanceof ServiceRecord)) {
            mServices.serviceDoneExecutingLocked((ServiceRecord)token, type, startId, res);
        }
    }
}

ActivityManagerService(简称AMS)其实干了很多有意义的事情,根据下小节的贴图,具体步骤如下:

  • AMS.bindService:绑定一个指定Intent的Service,它最后把复杂的逻辑交给了ActivityServices处理,例如检索意图Intent传递的参数,是否创建这个Service或它所在的进程,启动并请求绑定这个Service。
  • AMS.publishService:上面步骤最终会在ActivityThread中创建该Service,并拿到这个Service的IBinder对象(如果同进程则拿到该实例IXXX.Stub,如果不同进程则拿到它的代理对象IXXX.Stub.Proxy),最终将这个IBinder通过该方法发布出来,详情参考后文第四小节。该方法最终将把这个IBinder回调到onServiceConnected方法中。

3)、ActiveServices实现了复杂的逻辑

ActivityManagerService继承于IActivityManager.Stub,bindeService这几个接口,其实都交给了ActiveServices来处理。如下图,绑定流程大概有如下几个步骤:

  • ActiveServices.bindServiceLocked:绑定指定的Service(可能是不同进程),其中第三个参数service很重要,它是Intent类型,即Activity.bindService传递的这个Intent,内部封装了目标Service的过滤信息。
  • ActiveServices.retrieveServiceLocked:检索被指定的Intent并提取其中信息将其装换成ServiceRecord对象,该每一个ServiceRecord都对应于一个Service。bindServiceLocked首先调用该方法并传递了Intent service,检索这个Intent最后得到一个ServiceRecord。
  • ActiveServices.bringUpServiceLocked:提取一个Service,注意该方法的参数不再是Intent而是上面提到的ServiceRecord。bindServiceLocked首先通过retrieveServiceLocked将Intent转换成ServiceRecord,然后调用该方法并传递了ServiceRecord进来,想提取该Service。
  • ActiveServices.realStartServiceLocked:创建启动并绑定一个真实的Service。bringUpServiceLocked方法想提取一个被ServiceRecord指定的Service,但是该Service可能存在也可能被创建了,如果不存在则调用该方法来创建Service,然后通过ActivityThread的H启动它。
  • ActiveServices.requestServiceBindingLocked:请求绑定一个Service,该方法被调用的地方很多,bindServiceLocked方法创建启动ServiceRecord指定的Service之后,终于调用该方法请求绑定该Service,它的实现方式同realStartServiceLocked一样,通过ActivityThread的H去绑定它。
//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
public final class ActiveServices {
    //绑定Intent service中指定的Service
    int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service, String resolvedType, final IServiceConnection connection, int flags, String callingPackage, final int userId) throws TransactionTooLargeException {
        //...省略...
        //步骤1:检索Intent类型的service,并将其转换成ServiceRecord 
        ServiceLookupResult res = retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg, isBindExternal, allowInstant);
        if (res == null)  return 0;
        if (res.record == null)  return -1;
        ServiceRecord s = res.record;
        //...省略...
        {
                final ServiceRecord serviceRecord = s;
                final Intent serviceIntent = service;
                //步骤2:根据serviceRecord提取该Service出来
                bringUpServiceLocked(serviceRecord, serviceIntent.getFlags(), callerFg, false, false);
                //步骤3:启动开始这个Service
                final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
                intent.putExtra(Intent.EXTRA_PACKAGE_NAME, s.packageName);
                intent.putExtra(Intent.EXTRA_REMOTE_CALLBACK, callback);
                mAm.mHandler.post(new Runnable() {
                    public void run() {
                        mAm.mContext.startActivityAsUser(intent, new UserHandle(userId));
                    }
                });
        }
        //...省略...
        {
            if (s.app != null && b.intent.received) {
                try {
                    c.conn.connected(s.name, b.intent.binder, false);
                } catch (Exception e) {  }
                if (b.intent.apps.size() == 1 && b.intent.doRebind) {
                    //步骤4:请求绑定该Service
                    requestServiceBindingLocked(s, b.intent, callerFg, true);
                }
            } else if (!b.intent.requested) { //请求绑定该Service
                requestServiceBindingLocked(s, b.intent, callerFg, false);
            }
        }
    }
    //提取ServiceRecord指定的Service,如果不存在就创建出来
    private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting, boolean permissionsReviewRequired) throws TransactionTooLargeException {
    //...省略...
        final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
        final String procName = r.processName;
        String hostingType = "service";
        ProcessRecord app;
        if (!isolated) {
            //得到ServiceRecord指定Service的进程相关信息
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            if (app != null && app.thread != null) {
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
                    //创建真实的Service,第一个参数ServiceRecord
                    realStartServiceLocked(r, app, execInFg);
                    return null;
                } catch  (RemoteException e) { Slog.w(TAG, "Exception when starting service " + r.shortName, e); }
            }
        }
    //...省略...
    }
    //创建一个ServiceRecord指定的真实的Service
    private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException {
        //...省略...
        boolean created = false;
        try {
            mAm.notifyPackageUse(r.serviceInfo.packageName, PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
            app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
            //通过ActivityThread向它的H来实现Service的创建
            app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), app.repProcState);
            r.postNotification();
            created = true;
        } catch (DeadObjectException e) {
            mAm.appDiedLocked(app);
        } finally {
            if (!created) {
                // Keep the executeNesting count accurate.
                final boolean inDestroying = mDestroyingServices.contains(r);
                serviceDoneExecutingLocked(r, inDestroying, inDestroying);
                if (newService) { // Cleanup.
                    app.services.remove(r);
                    r.app = null;
                }
                if (!inDestroying) {  // Retry.
                    scheduleServiceRestartLocked(r, false);
                }
            }
        }
        //...省略...
    }
    //请求绑定一个ServiceRecord指定的真实的Service
    private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i, boolean execInFg, boolean rebind) throws TransactionTooLargeException {
        if ((!i.requested || rebind) && i.apps.size() > 0) {
            try {
                bumpServiceExecutingLocked(r, execInFg, "bind");
                r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
                //通过ActivityThread向它的H来实现Service的创建
                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,  r.app.repProcState);
                if (!rebind)  i.requested = true;
                i.hasBound = true;
                i.doRebind = false;
            } catch (RemoteException e) { /*...*/ }
        }
        return true;
    }
}

4)、ActivityThread实现Service的创建和绑定

上小节已经知道了创建/绑定服务最关键过程,ActiveServices分别调用了ActivityThread的方法scheduleCreateService和方法scheduleBindService,其中传递的第一个参数都是ServiceRecord类型,没错这个ServiceRecord是根据Intent转换过来的。如下代码:

//frameworks/base/core/java/android/app/ActivityThread.java
public final class ActivityThread extends ClientTransactionHandler {
    private class ApplicationThread extends IApplicationThread.Stub {
        public final void scheduleCreateService(IBinder token, ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
            updateProcessState(processState, false);
            CreateServiceData s = new CreateServiceData();
            s.token = token;
            s.info = info;
            s.compatInfo = compatInfo;
            sendMessage(H.CREATE_SERVICE, s);
        }
        //注意:传递过来的第一个参数token其实是一个ServiceRecord类型
        public final void scheduleBindService(IBinder token, Intent intent, boolean rebind, int processState) {
            updateProcessState(processState, false);
            BindServiceData s = new BindServiceData();
            s.token = token;
            s.intent = intent;
            s.rebind = rebind;
            sendMessage(H.BIND_SERVICE, s);
        }
    }
    class H extends Handler {
        public void handleMessage(Message msg) {
                case CREATE_SERVICE:
                    handleCreateService((CreateServiceData)msg.obj);
                    break;
                case BIND_SERVICE:
                    handleBindService((BindServiceData)msg.obj);
                    break;
        }
    }
    private void handleBindService(BindServiceData data) {
        //注意:这里的s其实是一个ServiceRecord
        Service s = mServices.get(data.token);
        if (s != null) {
            try {
                data.intent.setExtrasClassLoader(s.getClassLoader());
                data.intent.prepareToEnterProcess();
                try {
                    if (!data.rebind) {
                        //直接调用Service的onBind方法,AIDL接口中返回的是IXXX.Stub
                        //这就是为什么Service重新onBind方法如果返回null,那么服务绑定必定失败
                        IBinder binder = s.onBind(data.intent);
                        //通过AMS发布这个IBinder,即回调onServiceConnected方法
                        //注意,第三个参数binder其实是一个IXXX.Stub
                        ActivityManager.getService().publishService(data.token, data.intent, binder);
                    } else {
                        s.onRebind(data.intent);
                        ActivityManager.getService().serviceDoneExecuting(data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                    }
                    ensureJitEnabled();
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            } catch (Exception e) {
                if (!mInstrumentation.onException(s, e)) {
                    throw new RuntimeException("Unable to bind to service " + s + " with " + data.intent + ": " + e.toString(), e);
                }
            }
        }
    }
}

现在明白了吗?ActivityThread其实也没干什么,接收到指定的ServiceRecord,在H中获取出来并调用它的onBind方法,将其返回值通过AMS.publishService发布出去,值得注意的是该方法的第三个参数虽然也是IBinder,但它实际上是一个IXXX.Stub对象,并不是想象中的BinderProxy???

//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public class ActivityManagerService extends IActivityManager.Stub implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    //发布一个Service,开始回调onServiceConnected方法
    //注意:第三个参数service其实是Service.onBind返回的实例,在AIDL接口中是一个IXXX.Stub
    public void publishService(IBinder token, Intent intent, IBinder service) {
        synchronized(this) {
            if (!(token instanceof ServiceRecord))  throw new IllegalArgumentException("Invalid service token");
            mServices.publishServiceLocked((ServiceRecord)token, intent, service);
        }
    }
}
//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
public final class ActiveServices {
    void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
        final long origId = Binder.clearCallingIdentity();
        try {
            if (r != null) {
                Intent.FilterComparison filter = new Intent.FilterComparison(intent);
                IntentBindRecord b = r.bindings.get(filter);
                if (b != null && !b.received) {
                    b.binder = service;
                    b.requested = true;
                    b.received = true;
                    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);
                            if (!filter.equals(c.binding.intent.intent)) continue;
                            try {
                                //回调LoadedApk处理
                                c.conn.connected(r.name, service, false);
                            } catch (Exception e) { }
                        }
                    }
                }
                serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }
}
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

2、一次完整的C/S通信流程

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

诸神黄昏EX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值