Android Binder框架实现之bindService详解



Android Binder框架实现目录:

Android Binder框架实现之Binder的设计思想Android Binder框架实现之何为匿名/实名BinderAndroid Binder框架实现之Binder中的数据结构Android Binder框架实现之Binder相关的接口和类Android Binder框架实现之Parcel详解之基本数据的读写Android Binder框架实现之Parcel read/writeStrongBinder实现Android Binder框架实现之servicemanager守护进程Android Binder框架实现之defaultServiceManager()的实现Android Binder框架实现之Native层addService详解之请求的发送Android Binder框架实现之Native层addService详解之请求的处理Android Binder框架实现之Native层addService详解之请求的反馈Android Binder框架实现之Binder服务的消息循环Android Binder框架实现之Native层getService详解之请求的发送Android Binder框架实现之Native层getService详解之请求的处理Android Binder框架实现之Native层getService详解之请求的反馈Android Binder框架实现之Binder Native Service的Java调用流程Android Binder框架实现之Java层Binder整体框架设计Android Binder框架实现之Framework层Binder服务注册过程源码分析Android Binder框架实现之Java层Binder服务跨进程调用源码分析Android Binder框架实现之Java层获取Binder服务源码分析Android Binder框架实现之bindService详解


本篇博客编写思路总结和关键点说明:

Android bindService校验 安卓bindservice_Binder


为了更加方便的读者阅读博客,通过导读思维图的形式将本博客的关键点列举出来,从而方便读者取舍和阅读!



引言

  小伙们还记得前面博客Android Binder框架实现之何为匿名/实名Binder中我们分析匿名/实名Binder的时候重点以bindService为例说明了匿名Binder在该调用过程中的运用(上篇的重点主要是匿名Binder在传输中如何在驱动中完成匿名Binder的实体节点的生成和引用的创建),那么在今天的博客中我们重点以bindService为例来分析匿名Binder的实际运用过程。 当然小伙们也可以抛开上面的匿名/实名Binder等相关知识点,单纯当成是bindService的源码分析也不为过,这个就看小伙们的出发点了,是分析匿名Binder的应用还是bindService的流程就看小伙们各取所需了。


  • 注意:本篇的介绍是基于Android 7.xx平台为基础的,其中涉及的代码路径如下:
frameworks/base/services/core/java/com/android/server/am/
  --- ActivityManagerService.java
  --- ActiveServices.java
  --- ServiceRecord.java
  --- ProcessRecord.java

frameworks/base/core/java/android/app/
  --- IActivityManager.java
  --- ActivityManagerNative.java (内部包含AMP)
  --- ActivityManager.java
  
  --- IApplicationThread.java
  --- ApplicationThreadNative.java (内部包含ATP)
  --- ActivityThread.java (内含ApplicationThread)
  
  --- ContextImpl.java

frameworks/base/core/java/android/app/LoadedApk.java  
frameworks/base/core/java/android/app/IServiceConnection.aidl
frameworks/base/core/java/android/content/ServiceConnection.java
frameworks/base/core/java/android/util/Singleton.java
  • 并且在后续的源码分析过程中为了简述方便,会将做如下简述:
    ApplicationThreadProxy简称为ATP
    ActivityManagerProxy简称为AMP
    ActivityManagerService简称为AMS
    ActivityManagerNative简称AMN
    ApplicationThreadNative简称ATN
    PackageManagerService简称为PKMS
    ApplicationThread简称为AT
    ActivityServices简称为AS



一. bindService开篇

在bindService的源码中将要涉及到三个主要的进程,分别是bindService发起端进程,system_server进程和目的端Service进程, 我们将会以这三个进程角度出来阐述bindService是怎么在这三个进程之间辗转腾挪达到远程绑定服务或者说是Binder传递功能的。对于绝大部分小伙们来说遇到一个新的知识点,一定是先从实例入手先使用,然后再深入原理及其实现,我们这里也不例外,先让我们看看bindService的实例怎么使用!

1.1 bindService使用实例

  bindService的实例涉及到目的端Service进程和client端发起端进程,让我们来开写,好久没有写过实例了让我们入手一番!

定义aidl文件

  bindService能实现的一个前提就是Android为我们提供了一套AIDL(Android Interface Definition Language)即Android接口定义语言,来帮助我们实现远程Binder的通信(当然我们也可以不使用AIDL语言,直接硬编码实现也行可以参见博客Android Binder实战开发指南之不借助AIDL创建Java层Binder服务)。好了前面说了这么多了,直接不如正题,编码一个aidl文件如下:

interface IAidlFun {
    void doAction();
}

此时编译器会对aidl文件自动编译生成,IAidlFun.java文件,我们看看其神秘面纱,我想如何小伙们对Binder有过一定的基础,对其中的代码就不会陌生了,这就是Android为了我们快速能使用Binder而做的一个模板啊,即生成通信层代码模板,而用户完全只用关心业务层的逻辑,降低开发难度。

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: E:\\workspace\\PaxForAll\\src\\com\\example\\api\\aidl\\IAidlFun.aidl
 */
package com.example.api.aidl;

public interface IAidlFun extends android.os.IInterface {
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements
            com.example.api.aidl.IAidlFun {
        private static final java.lang.String DESCRIPTOR = "com.example.api.aidl.IAidlFun";

        /** Construct the stub at attach it to the interface. */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an com.example.api.aidl.IAidlFun
         * interface, generating a proxy if needed.
         */
        public static com.example.api.aidl.IAidlFun asInterface(
                android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.example.api.aidl.IAidlFun))) {
                return ((com.example.api.aidl.IAidlFun) iin);
            }
            return new com.example.api.aidl.IAidlFun.Stub.Proxy(obj);
        }

        @Override
        public android.os.IBinder asBinder() {
            return this;
        }

        @Override
        public boolean onTransact(int code, android.os.Parcel data,
                android.os.Parcel reply, int flags)
                throws android.os.RemoteException {
            switch (code) {
            case INTERFACE_TRANSACTION: {
                reply.writeString(DESCRIPTOR);
                return true;
            }
            case TRANSACTION_doAction: {
                data.enforceInterface(DESCRIPTOR);
                this.doAction();
                reply.writeNoException();
                return true;
            }
            }
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements com.example.api.aidl.IAidlFun {
            private android.os.IBinder mRemote;

            Proxy(android.os.IBinder remote) {
                mRemote = remote;
            }

            @Override
            public android.os.IBinder asBinder() {
                return mRemote;
            }

            public java.lang.String getInterfaceDescriptor() {
                return DESCRIPTOR;
            }

            @Override
            public void doAction() throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_doAction, _data, _reply,
                            0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
        }

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

    public void doAction() throws android.os.RemoteException;
}
目的端(Service进程)
...
public class AidlService extends Service {
    private BindService mBindService = null;
    private static final String TAG = AidlService.class.getSimpleName();

    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG,"onBind");
        return mBindService;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e(TAG,"onCreate");
        mBindService = new BindService();
    }
    
    //此处的IAidlFun.Stub是由编译器自动实现生成的,帮我们快速实现Binder的开发
    public class BindService extends IAidlFun.Stub {
        @Override
        public void doAction() throws RemoteException {
        }
    }
...
}
发起端进程
private IAidlFun mRemoteServiceProxy;
    private void bindService() {
        // 发起端进程绑定远程服务端进程
        bindService(new Intent("com.example.aidl.aidlService"), mConnection,
                Context.BIND_AUTO_CREATE);
    }

    ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceDisconnected(ComponentName name) {
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "onServiceConnected");
            // 获取远程服务端Service代理端Proxy
            mRemoteServiceProxy = IAidlFun.Stub.asInterface(service);

            try {
                // RPC远程服务端方法,实现跨进程交互
                mRemoteServiceProxy.doAction();
            } catch (RemoteException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };

bindService感觉用起来好爽,好简单啊!可是其中涉及的过程调用和源码逻辑各位小伙们都清楚吗,不清楚也没有关系,让我们来一起搞清楚!


1.2 bindService源码分析前期知识储备

  还是老套路,在正式开始分析之前我们还是磨刀不误砍柴工,我们还是对即将要分析的源码先来梳理梳理要准备的知识点,这样后续分析起来也会简单顺手一些。

1.2.1 进程创建流程

  bindService调用过程中会牵涉到目的端进程的创建(即目的端服务进程没有创建的前提下),这个虽然不是本文的重点,但是还是大概看下其示意图,后面也会大概过下:

Android bindService校验 安卓bindservice_Android_02

1.2.2 binderService时序图

  为了不耽误小伙们的时间,如果看了下面的时序图觉得有信心跟下去深入的可以接着往下分析,如果觉得没有毅力深入的可以就此打住了(因为分析源码真的是一件枯燥乏味的事情)!

Android bindService校验 安卓bindservice_1024程序员节_03




二. 发起端进程发送bindService请求

  在正式开始bindService的分析之前,将要涉及到涉及到Context的继承关系类图,从下面的类图中可以看出,Context是一个接口(提供了很多的接口方法),ContextImp和ContextWrapper都是其实现类,我们常用的Activity、Service、Application都直接或间接继承自ContextWrapper。

Android bindService校验 安卓bindservice_Android_04

2.1 ContextWrapper.bindService

Android bindService校验 安卓bindservice_framework_05


  这里我们可以看到bindService会调用到ContextWrapper类的bindService中,源码如下:

@Override
    //ContextWrapper.java
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        return mBase.bindService(service, conn, flags);//这里的mBase指向ContextImpl(怎么来的这里就不分析了,给出结论),其方法bindService见章节2.2
    }

这里我们有如下几点需要注意:

  • bindService方法第二个入参ServiceConnection为一个接口类型对象
  • ServiceConnection内部方法onServiceConnected的一个入参参数为IBinder数据类型,它就是我们最终获取的远程Binder实体的服务代理端(同时它也是一个匿名Binder)。通过我们前面的博客知道IBinder类型是可以跨进程传递的,而这里也运用了IBinder的这个特性从而实现了bindService。
public interface ServiceConnection {
	//这里的入参service就是我们最终要获取的远程Binder Service的远程代理端
    public void onServiceConnected(ComponentName name, IBinder service);
    public void onServiceDisconnected(ComponentName name);
}


2.2 ContextImpl.bindService

//ServiceConnection.java
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        warnIfCallingFromSystemProcess();//权限检测
        //这里的入参conn是一个interface类型的接口类,供回调使用
        return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
                Process.myUserHandle());
    }

无需多言,直接调用方法bindServiceCommon进行下一步的处理。


2.3 ContextImpl.bindServiceCommon

//ContextImpl.java
	final LoadedApk mPackageInfo;
    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
            handler, UserHandle user) {
        IServiceConnection sd;//这是一个aidl生成的Binder接口类
		...
        if (mPackageInfo != null) {
			//获取的是内部静态类InnerConnection
            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);//详见章节2.3.1
        } else {
            ...
        }
        validateServiceIntent(service);//判断参数service的有效性
        try {
			...
			//通过Binder远程调用AMS的bindService方法,详见2.4
            int res = ActivityManagerNative.getDefault().bindService(
                mMainThread.getApplicationThread(), getActivityToken(), service,
                service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, getOpPackageName(), user.getIdentifier());
			...
            return res != 0;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

  这里的IServiceConnection是一个aidl生成的Binder通讯工具类文件,其定义如下所示(可以看到它被定义为oneway类型的,即是一个非阻塞的Binder调用):

//IServiceConnection.aidl
oneway interface IServiceConnection {
	//注意这里的入参IBinder service和ServiceConnection的方法中入参IBinder service,都是相同的入参那么有啥关联,这里先预留一个疑点,到了后续小伙伴们应该就清楚了
    void connected(in ComponentName name, IBinder service);
}

我们回过头来看看bindServiceCommon的主要功能,然后对其逐个出击,一一攻破:

  • 创建对象内部静态类LoadedApk.ServiceDispatcher.InnerConnection的对象
  • 调用AMS的代理端AMP,向AMS服务发起bindService请求

其中bindService的入参mMainThread.getApplicationThread()方法返回的是ApplicationThread对象, 该对象继承于ApplicationThreadNative(Binder服务端),这个ApplicationThread对象很重要,因为正是通过它串联其了AMS对发起端进程的ActivityThread的交互(如果把ApplicationThread当作服务端,那么此时AMS相关于ApplicationThread而言就是客户端)。其两者之间的关系建立详见下述的示意图,即AMS持有ApplicationThread的代理端,而应用端进程持有AMS的代理端AMP,二者相互持有各自Binder服务端的代理端进而完成了二者之间的RPC调用。

Android bindService校验 安卓bindservice_Android_06

2.3.1 getServiceDispatcher

  在正式开始介绍getServiceDispatcher获取内部静态类LoadedApk.ServiceDispatcher.InnerConnection的对象之前,我们先看看LoadedApk的类图关系,如下(先熟悉熟悉,这样后续分析源码不会迷失):

Android bindService校验 安卓bindservice_bindService_07

//LoadedApk.java
    private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices
       = new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
    public final IServiceConnection getServiceDispatcher(ServiceConnection c,
            Context context, Handler handler, int flags) {
        synchronized (mServices) {
            LoadedApk.ServiceDispatcher sd = null;//ServiceDispatcher内部类
            ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);//查找mService中是否存在context的key
            if (map != null) {//如果存在这样的map,则继续查找map中是否存在ServiceConnection类型的实例c的key
                sd = map.get(c);//
            }
            if (sd == null) {//没有则创建
				//创建服务分发对象,注意这里的参数c是ServiceConnection对象,详见2.3.2
                sd = new ServiceDispatcher(c, context, handler, flags);
                if (map == null) {
                    map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
                    mServices.put(context, map);
                }
				//以ServiceConnection为key,ServiceDispatcher为value保存到map中
                map.put(c, sd);
            } else {
                sd.validate(context, handler);
            }
			//返回内部类对象InnerConnection实例
            return sd.getIServiceConnection();
        }
    }

在正式开始上述的源码分析前,我们先介绍介绍其中涉及的一个重要的数据结构对象mServices:

  • 可以看到它是一个Hashmap类型的数据,其key为Context类型对象
  • 然后mServices的value也是一个Hasmap,存放着Context对象所对应的ServiceConnection以及所对应的LoadedApk.ServiceDispatcher对象,即一个Context对象可以对应很多个ServiceConnection,但是同一个只会被创建一次

路障扫清了,让我们接着分析该方法,可以该方法返回LoadedApk.ServiceDispatcher.InnerConnection类型对象,该对象继承于IServiceConnection.Stub, 该类是由IServiceConnection.aidl类型文件由编译器怎懂自动生成的作为Binder服务端的实体端类。其中IServiceConnection.aidl在2.2章节已经有给出过了,就不放上了。

2.3.1 ServiceDispatcher
//LoadedApk.java
    static final class ServiceDispatcher {
		//内部类
        private final ServiceDispatcher.InnerConnection mIServiceConnection;
		//用户传递的参数
        private final ServiceConnection mConnection;
        private final Context mContext;
        private final Handler mActivityThread;
        private final ServiceConnectionLeaked mLocation;
		//保存第三方进程bindService传递过来的参数
        private final int mFlags;

        private RuntimeException mUnbindLocation;

        private boolean mForgotten;

        private static class InnerConnection extends IServiceConnection.Stub {
            final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;

            InnerConnection(LoadedApk.ServiceDispatcher sd) {
                mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
            }
			//注意这里的入参IBinder实例对象service
            public void connected(ComponentName name, IBinder service) throws RemoteException {
                LoadedApk.ServiceDispatcher sd = mDispatcher.get();
                if (sd != null) {
                    sd.connected(name, service);
                }
            }
        }

        ServiceDispatcher(ServiceConnection conn,
                Context context, Handler activityThread, int flags) {
            //创建InnerConnection对象
            mIServiceConnection = new InnerConnection(this);
			//用户定义的ServiceConnection
            mConnection = conn;
            mContext = context;
            mActivityThread = activityThread;
            mLocation = new ServiceConnectionLeaked(null);
            mLocation.fillInStackTrace();
			//保存用户传递的参数,通常为Context.BIND_AUTO_CREATE
            mFlags = flags;
        }		
}


		//返回内部类对象InnerConnection实例
        IServiceConnection getIServiceConnection() {
            return mIServiceConnection;
        }

  通过源码我们发现ServiceDispatcher是LoadedApk的内部类。InnerConnection是ServiceDispatcher的静态内部类,是不是有点拗口啊,这就是为什么我在前面先其奉上了LoadedApk的类图的原因。其中ServiceDispatcher有一个重要的方法getIServiceConnection(),通过该方法返回的便是在其构造方法中创建的InnerConnection对象。而这个InnerConnection也是bindService中的关键类,为啥这么说呢,往后分析小伙们就知道了!


2.4 AMN.getDefault()

  继续回到章节2.3在获取到InnerConnection实例对象sd之后,调AMN.getDefault().bindService,这里牵涉到一个重要的方法AMN.getDefault(),其实它在我们的博客中Android Binder框架实现之Java层获取Binder服务源码分析已经有详细的介绍和分析了,但是为了博客的连贯性还是简单过下(主要是为了不太熟悉的小伙伴们)。

//ActivityManagerNative.java
    static public IActivityManager getDefault() {
        return gDefault.get();
    }

这里的gDefault是Singleton对象实例,而Singleton我们可以看到是一个模板类对象,并且提供了一个单例方法,其定义如下:

//Singleton.java
public abstract class Singleton<T> {
    private T mInstance;

    protected abstract T create();

    public final T get() {
        synchronized (this) {
            if (mInstance == null) {//采用单例模式
                mInstance = create();
            }
            return mInstance;
        }
    }
}

我们将IActivityManager带入Singleton,得到如下的create方法过程:

//ActivityManagerNative.java
    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
        	//此处等价于IBinder b = new BinderProxy(new BpBinder(handle));
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
			//此处等价于IActivityManager am = new ActivityManagerProxy(new BinderProxy(new BpBinder(handle)))
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

	//注意此处我们的入参是BinderProxy类型,所以会走代理端
    static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }
		//即会走到此处
        return new ActivityManagerProxy(obj);
    }

这里即最终经过层层转换得到了AMS服务的代理端ActivityManagerProxy,进而借助它完成对AMS服务的RPC请求。

2.4.1 AMN.getDefault()小结

  AMN.getDefault()的调用流程基本分析结束了,我们对其小结一下:

  • AMN.getDefault()最终获取了AMS的远程Binder代理端AMP
  • AMS的Binder通信过程中提供了一个IActivityManager服务业务层接口,AMP类与AMS类都实现了IActivityManager接口方法,区别不同给的是AMS端显示了真正的具体服务,而AMP端是封装了相关的通信传输逻辑。AMP作为Binder通信的服务代理端,而AMS作为Binder通信的服务端实体,根据Android Binder框架实现之Java层Binder服务跨进程调用源码分析,AMP.bindService()最终调用AMS.bindService(),整个流程图如下:

Android bindService校验 安卓bindservice_Android_08


2.5 AMP.bindService()

//ActivityManagerNative.java
    public int bindService(IApplicationThread caller, IBinder token,
            Intent service, String resolvedType, IServiceConnection connection,
            int flags,  String callingPackage, int userId) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
		//写入AMS Binder服务描述信息即android.app.IActivityManager
        data.writeInterfaceToken(IActivityManager.descriptor);
		//写入IApplicationThread 匿名Binder服务实体(这个在attachApplication时写入过)
		data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeStrongBinder(token);
        service.writeToParcel(data, 0);
        data.writeString(resolvedType);
		//此处写入IServiceConnection 匿名Binder服务实体
        data.writeStrongBinder(connection.asBinder());
        data.writeInt(flags);
        data.writeString(callingPackage);
        data.writeInt(userId);
		//mRemote指向BinderProxy,而BinderProxy持有C++端的BpBinder,进而借助Binder驱动和AMS通信
        mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);
        reply.readException();
        int res = reply.readInt();
        data.recycle();
        reply.recycle();
        return res;
    }

  这里如果对Binder框架熟悉的小伙们应该对上述的调用过程是见怪不怪了,但是有几个点我们需要注意:

  • bindService中调用了三次Parcel类的方法writeStrongBinder(),这里我们需要注意writeStrongBinder()这三次写入的是Binder实体代理端还是代理端,是实名Binder还是匿名Binder。
  • 这里的mRemote指向BinderProxy,而BinderProxy持有C++端的BpBinder,而BpBinder作为远程Binder实体的通信代理端,最后借助Binder驱动和AMS通信,最后调用到ActivityManagerNative的onTransact()方法中



三. system_server进程处理bindService请求

  通过上面的层层冲关,打怪我们跳出了发起端进程,来到了system_server进程,让我们接着分析看看system_server是怎么处理bindService的RPC请求的。

3.1 AMN.onTransact

//ActivityManagerNative.java
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        switch (code) {
        	...
        	case BIND_SERVICE_TRANSACTION: {
	            data.enforceInterface(IActivityManager.descriptor);
	            IBinder b = data.readStrongBinder();
				//此处b为ApplicationThread的代理端,转换后生成即ApplicationThreadProxy对象
	            IApplicationThread app = ApplicationThreadNative.asInterface(b);
	            IBinder token = data.readStrongBinder();
	            Intent service = Intent.CREATOR.createFromParcel(data);
	            String resolvedType = data.readString();
	            b = data.readStrongBinder();//注意这里的b被重新赋值了
	            int fl = data.readInt();
	            String callingPackage = data.readString();
	            int userId = data.readInt();
				//生成IServiceConnection的代理对象IServiceConnection.Stub.Proxy
	            IServiceConnection conn = IServiceConnection.Stub.asInterface(b);
	            int res = bindService(app, token, service, resolvedType, conn, fl,
	                    callingPackage, userId);//详见3.2
	            reply.writeNoException();
	            reply.writeInt(res);
	            return true;
        	}
        	...
        }
   }

在正式开始上述的源码分析前,我们先来阐述一个重要的知识点,即在这个调用过程中涉及到两个进程,不妨令bindService的发起进程记为进程Process_A,AMS Service所属进程记为进程Process_B;那么进程Process_A通过Binder机制(采用IActivityManager接口)向进程Process_B发起请求服务,进程Process_B则通过Binder机制(采用IApplicationThread接口)向进程Process_A发起请求服务。也就是说进程Process_A与进程Process_B能相互间主动发起请求,进而完成进程通信,但是这里有一点需要注意IApplicationThread的Binder实体端并没有注册到servicemanager进程中,它是一个依赖于实名Binder的匿名Binder。

这里涉及IApplicationThread很重要,它串联起了AMS对App进程的生命周期及其其它的控制,那么下面直接把其相关的类图展示如下:

Android bindService校验 安卓bindservice_Binder_09

这里的IApplicationThread与IActivityManager的Binder通信原理一样,ATP作为Binder通信的客户端,ATN作为Binder通信的服务端,其中ApplicationThread继承ATN类,覆写其中的部分方法。

接着继续分析onTransact方法,其根据AMP传递过来的code值进入BIND_SERVICE_TRANSACTION分支,然后解读取通过Binder驱动传递过来的数据,解析完成之后调用AMN的方法bindService继续未完成之工作(这里的bindService在AMS服务中具体实现),这里从驱动中获取到数据然后解析这里就不重点关注了,我们这里重点关注一下AMN.bindService的几个入参:

  • 参数app: 发起端进程通过Binder IPC传递过来的ApplicationThread对象(匿名Binder服务端实体端)的Binder通信层代理端BinderProxy(BinderProxy(BpBinder())), 然后借助ATN.asInterface()方法生成新的代理对象ApplicationThreadProxy类型对象app(这个地方有点拗口,如果实在转不过来就算了,我们只需要知道此处获取了ApplicationThread的远程代理端ATP)
  • 参数conn: 根据发起端进程传递过来的InnerConnectiond对象(Binder服务端),同样通过转换后,生成IServiceConnection.Stub.Proxy类型对象conn
  • 参数service: 数据类型为Intent, 是指本次要启动的service的意图
  • 参数callingPackage: 发起方所属的包名
  • 参数fl: 是指flags, 此时等于Context.BIND_AUTO_CREATE, 即值为1


3.2 AMS.bindService

//ActivityManagerService.java
	//final ActiveServices mServices;
    public int bindService(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, IServiceConnection connection, int flags, String callingPackage,
            int userId) throws TransactionTooLargeException {
		...
        synchronized(this) {
            return mServices.bindServiceLocked(caller, token, service,
                    resolvedType, connection, flags, callingPackage, userId);
        }
    }

  AMS的担子很大,代码很多,为了的代码的条理性和代码的易阅读性AMS将事务委托给ActiveServices类实例对象进行处理。


3.3 ActiveServices.bindServiceLocked

  前方高能预警,小伙们可以趁着现在上个厕所,喝个水啥的,实在不行休息一下也行!因为后续的代码很长,很长,而且中途还不好休息最好是憋着一口气整完,不然又得找自己究竟在那里了!

//ActiveServices.java
    int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, final IServiceConnection connection, int flags,
            String callingPackage, final int userId) throws TransactionTooLargeException {
		...
		//查询发起端对应的进程记录结构
		final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
		...
        ActivityRecord activity = null;
		//token不为空,代表着发起方具有activiy上下文
        if (token != null) {
            activity = ActivityRecord.isInStackLocked(token);
            if (activity == null) {
                Slog.w(TAG, "Binding with unknown activity: " + token);
                return 0;//存在token, 却找不到activity为空,则直接返回
            }
        }

        int clientLabel = 0;
        PendingIntent clientIntent = null;
        final boolean isCallerSystem = callerApp.info.uid == Process.SYSTEM_UID;

        if (isCallerSystem) {//调用者是否是system_uid用户
			...
        }
		...
		//根据发送端所在进程的SchedGroup来决定是否为前台service.
        final boolean callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
        final boolean isBindExternal = (flags & Context.BIND_EXTERNAL_SERVICE) != 0;

		//根据第三方进程传递进来的Intent信息来检索相对应的服务,这个retriev单词很契合
		ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),
                    Binder.getCallingUid(), userId, true, callerFg, isBindExternal);//详见章节3.3.1
		...
		//查询到相应的Service
        ServiceRecord s = res.record;
        if (mAm.mPermissionReviewRequired || Build.PERMISSIONS_REVIEW_REQUIRED) {//权限检测
			...
        }

        try {
			//取消服务的重启调度
			if (unscheduleServiceRestartLocked(s, callerApp.info.uid, false)) {
                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "BIND SERVICE WHILE RESTART PENDING: "
                        + s);
            }

            if ((flags&Context.BIND_AUTO_CREATE) != 0) {//根据前面的分析可知,此处传递过来的flags的值就是Context.BIND_AUTO_CREATE
				//更新当前service活动时间
				s.lastActivity = SystemClock.uptimeMillis();
                if (!s.hasAutoCreateConnections()) {
                    // This is the first binding, let the tracker know.
                    ServiceState stracker = s.getTracker();
                    if (stracker != null) {
                        stracker.setBound(true, mAm.mProcessStats.getMemFactorLocked(),
                                s.lastActivity);
                    }
                }
            }

            mAm.startAssociationLocked(callerApp.uid, callerApp.processName, callerApp.curProcState,
                    s.appInfo.uid, s.name, s.processName);

            AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);//详见章节3.3.2
			//创建对象ConnectionRecord,此处connection来自发起方
            ConnectionRecord c = new ConnectionRecord(b, activity,
                    connection, flags, clientLabel, clientIntent);

            IBinder binder = connection.asBinder();//这里表示IServiceConnection服务的远程代理端,看来Binder真的是很重要阿
            ArrayList<ConnectionRecord> clist = s.connections.get(binder);
            if (clist == null) {
                clist = new ArrayList<ConnectionRecord>();
                s.connections.put(binder, clist);
            }
            clist.add(c);// clist是ServiceRecord.connections的成员变量
            b.connections.add(c);//b是指AppBindRecord
            if (activity != null) {
                if (activity.connections == null) {
                    activity.connections = new HashSet<ConnectionRecord>();
                }
                activity.connections.add(c);
            }
            b.client.connections.add(c);
            if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
                b.client.hasAboveClient = true;
            }
            if ((c.flags&Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) {
                s.whitelistManager = true;
            }
            if (s.app != null) {
                updateServiceClientActivitiesLocked(s.app, c, true);
            }
            clist = mServiceConnections.get(binder);
            if (clist == null) {
                clist = new ArrayList<ConnectionRecord>();
                mServiceConnections.put(binder, clist);
            }
            clist.add(c);

            if ((flags&Context.BIND_AUTO_CREATE) != 0) {
                s.lastActivity = SystemClock.uptimeMillis();
				//启动service,这个过程和startService过程一致
                if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
                        permissionsReviewRequired) != null) {//详见章节3.4
                    return 0;
                }
            }

            if (s.app != null) {//此时表示service所属进程已经启动
                if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
                    s.app.treatLikeActivity = true;
                }
                if (s.whitelistManager) {
                    s.app.whitelistManager = true;
                }
                // This could have made the service more important.
                //更新service所在进程优先级
                mAm.updateLruProcessLocked(s.app, s.app.hasClientActivities
                        || s.app.treatLikeActivity, b.client);
                mAm.updateOomAdjLocked(s.app);
            }
				...
            if (s.app != null && b.intent.received) {
                // Service is already running, so we can immediately
                // publish the connection.
                try {
                	//Service已经正在运行,则调用InnerConnection的代理对象
                    c.conn.connected(s.name, b.intent.binder);
                } catch (Exception e) {
                    Slog.w(TAG, "Failure sending service " + s.shortName
                            + " to connection " + c.conn.asBinder()
                            + " (in " + c.binding.client.processName + ")", e);
                }
				...
                //当第一个app连接到该binding, 且之前已被bind过, 则回调onRebind()方法
                if (b.intent.apps.size() == 1 && b.intent.doRebind) {
                    requestServiceBindingLocked(s, b.intent, callerFg, true);
                }
            } else if (!b.intent.requested) {
				//最终回调onBind()方法
				requestServiceBindingLocked(s, b.intent, callerFg, false);
            }

            getServiceMap(s.userId).ensureNotStartingBackground(s);

        } finally {
            Binder.restoreCallingIdentity(origId);
        }

        return 1;
    }

是不是感觉有点懵,这一坨代码的,不要慌!我们理一理这一坨代码的主要功能有哪些:

  • 通常第三方进程调用system_server进程中的Java层Binder服务时候会做一些安全和功能的检测,这里也不例外,会判断发起端进程是否存在,是否存在activity上下文等信息
  • 调用retrieveServiceLocked查找根据第三方进程传递进来的Intent所对应的服务,即系统中是否存在符合intent携带消息的Service
  • 通过retrieveAppBindingLocked()方法创建AppBindRecord对象,该对象记录着当前ServiceRecord, intent以及发起方的进程ProcessRecord信息
  • 一切准备就绪之后,调用bringUpServiceLocked拉起目标服务(如果此时目标进程还没有创建的话,得先创建目标进程)

另外可以看到在AMS服务中会将发起端传递过来的connection存储起来,即将发起端进程传递过来的LoadedApk.ServiceDispatcher.InnerConnection的代理对象IServiceConnection.Stub.Proxy类型对象实例connection,保存到新创建的ConnectionRecord对象的成员变量. 再通过clist.add( c ), 将该ConnectionRecord对象添加到clist队列. 后面便可以通过clist来 查询发起方的信息。

3.3.1 ActiveServices.retrieveServiceLocked
//ActiveServices.java
	final SparseArray<ServiceMap> mServiceMap = new SparseArray<>();
    private ServiceLookupResult retrieveServiceLocked(Intent service,
            String resolvedType, String callingPackage, int callingPid, int callingUid, int userId,
            boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal) {
        ServiceRecord r = null;
		...

        userId = mAm.mUserController.handleIncomingUser(callingPid, callingUid, userId, false,
                ActivityManagerService.ALLOW_NON_FULL_IN_PROFILE, "service", null);

        ServiceMap smap = getServiceMap(userId);
        final ComponentName comp = service.getComponent();
        if (comp != null) {
			//根据服务名查找对应的ServiceRecord
            r = smap.mServicesByName.get(comp);
        }
        if (r == null && !isBindExternal) {
            Intent.FilterComparison filter = new Intent.FilterComparison(service);
			//根据Intent查找相应的相应的ServiceRecord
            r = smap.mServicesByIntent.get(filter);
        }
        if (r != null && (r.serviceInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) != 0
                && !callingPackage.equals(r.packageName)) {
			...
            r = null;
        }
        if (r == null) {//在smap中没有查找到对应的服务
            try {
            	...
				//通过PKMS来查询相应的service
				ResolveInfo rInfo = AppGlobals.getPackageManager().resolveService(service,
                        resolvedType, ActivityManagerService.STOCK_PM_FLAGS
                                | PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
                        userId);
                ServiceInfo sInfo =
                    rInfo != null ? rInfo.serviceInfo : null;
                if (sInfo == null) {
					...
                }

				//组装组件名
                ComponentName name = new ComponentName(
                        sInfo.applicationInfo.packageName, sInfo.name);
                if ((sInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) != 0) {//声明externalService为true就是让该Service可以绑定并运行在调用方的App中,而不是在声明这个Service的App中
                    if (isBindExternal) {
                        if (!sInfo.exported) {
                            throw new SecurityException("BIND_EXTERNAL_SERVICE failed, " + name +
                                    " is not exported");
                        }
                        if ((sInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) == 0) {
                            throw new SecurityException("BIND_EXTERNAL_SERVICE failed, " + name +
                                    " is not an isolatedProcess");
                        }
                        // Run the service under the calling package's application.
                        ApplicationInfo aInfo = AppGlobals.getPackageManager().getApplicationInfo(
                                callingPackage, ActivityManagerService.STOCK_PM_FLAGS, userId);
                        if (aInfo == null) {
                            throw new SecurityException("BIND_EXTERNAL_SERVICE failed, " +
                                    "could not resolve client package " + callingPackage);
                        }
                        //其实就是重新设置了一遍ServiceInfo,让此Service改名换姓
                        sInfo = new ServiceInfo(sInfo);
                        sInfo.applicationInfo = new ApplicationInfo(sInfo.applicationInfo);
                        sInfo.applicationInfo.packageName = aInfo.packageName;
                        sInfo.applicationInfo.uid = aInfo.uid;
                        name = new ComponentName(aInfo.packageName, name.getClassName());
                        service.setComponent(name);
                    } else {
                        throw new SecurityException("BIND_EXTERNAL_SERVICE required for " +
                                name);
                    }
                } else if (isBindExternal) {
                    throw new SecurityException("BIND_EXTERNAL_SERVICE failed, " + name +
                            " is not an externalService");
                }
                if (userId > 0) {
					//服务是否属于单例模式
                    if (mAm.isSingleton(sInfo.processName, sInfo.applicationInfo,
                            sInfo.name, sInfo.flags)
                            && mAm.isValidSingletonCall(callingUid, sInfo.applicationInfo.uid)) {
                        userId = 0;
                        smap = getServiceMap(0);
                    }
                    sInfo = new ServiceInfo(sInfo);
                    sInfo.applicationInfo = mAm.getAppInfoForUser(sInfo.applicationInfo, userId);
                }
                r = smap.mServicesByName.get(name);
                if (r == null && createIfNeeded) {
                    Intent.FilterComparison filter
                            = new Intent.FilterComparison(service.cloneFilter());
                    ServiceRestarter res = new ServiceRestarter();
                    BatteryStatsImpl.Uid.Pkg.Serv ss = null;
                    BatteryStatsImpl stats = mAm.mBatteryStatsService.getActiveStatistics();
                    synchronized (stats) {
                        ss = stats.getServiceStatsLocked(
                                sInfo.applicationInfo.uid, sInfo.packageName,
                                sInfo.name);
                    }
					//创建ServiceRecord
                    r = new ServiceRecord(mAm, ss, name, filter, sInfo, callingFromFg, res);
                    res.setService(r);
					//将创建的ServiceRecord信息放入smap列表中,因为之前该service并没有创建过,所以会加入smap哈希列表
                    smap.mServicesByName.put(name, r);
                    smap.mServicesByIntent.put(filter, r);

                    for (int i=mPendingServices.size()-1; i>=0; i--) {
                        ServiceRecord pr = mPendingServices.get(i);
                        if (pr.serviceInfo.applicationInfo.uid == sInfo.applicationInfo.uid
                                && pr.name.equals(name)) {
                            mPendingServices.remove(i);
                        }
                    }
                }
            } catch (RemoteException ex) {
            }
        }
        if (r != null) {
			//各种权限检查
            if (mAm.checkComponentPermission(r.permission,
                    callingPid, callingUid, r.appInfo.uid, r.exported)
                    != PackageManager.PERMISSION_GRANTED) {
                //当exported=false则不允许启动
                if (!r.exported) {
                    Slog.w(TAG, "Permission Denial: Accessing service " + r.name
                            + " from pid=" + callingPid
                            + ", uid=" + callingUid
                            + " that is not exported from uid " + r.appInfo.uid);
                    return new ServiceLookupResult(null, "not exported from uid "
                            + r.appInfo.uid);
                }
                Slog.w(TAG, "Permission Denial: Accessing service " + r.name
                        + " from pid=" + callingPid
                        + ", uid=" + callingUid
                        + " requires " + r.permission);
                return new ServiceLookupResult(null, r.permission);
            } else if (r.permission != null && callingPackage != null) {
                final int opCode = AppOpsManager.permissionToOpCode(r.permission);
                if (opCode != AppOpsManager.OP_NONE && mAm.mAppOpsService.noteOperation(
                        opCode, callingUid, callingPackage) != AppOpsManager.MODE_ALLOWED) {
                    Slog.w(TAG, "Appop Denial: Accessing service " + r.name
                            + " from pid=" + callingPid
                            + ", uid=" + callingUid
                            + " requires appop " + AppOpsManager.opToName(opCode));
                    return null;
                }
            }

            if (!mAm.mIntentFirewall.checkService(r.name, service, callingUid, callingPid,
                    resolvedType, r.appInfo)) {
                return null;
            }
			//创建Service查询结果,并返回
            return new ServiceLookupResult(r, null);
        }
        return null;
    }

  前方的代码又是大一坨,主要是牵扯到各种数据结构的转换和关联,得数据结构这得天下啊,看来学好数据结构真的很重要啊,好像跑题了啊!前面我们知道retrieveServiceLocked主要是查询我们的目的端服务ServiceLookupResult结构是否存在(如果前面没有调用过,当然不存在得创建),其查询按照如下步骤依次执行(这里不详细展开了,不然那真是没完没了的了,估计你要疯,我也要疯):

  • 通过userId查询mServiceMap中是否存在对应的ServiceMap实例,如果没有则创建一个并返回赋给ServiceMap实例smap
  • 根据服务名从实例对象smap.mServicesByName中查找相应的ServiceRecord,如果没有找到,则往下执行;
  • 根据Intent从实例对象smap.mServicesByIntent中查找相应的ServiceRecord,如果还是没有找到,则往下执行;
  • 通过PKMS来查询相应的ServiceInfo,如果仍然没有找到相关信息,则不再往下执行,如若找到则继续执行填充ServiceRecord数据结构

这里还有一个知识点,就是ServiceInfo.FLAG_EXTERNAL_SERVICE这个标志,是干啥的呢,说实话我也没有用过,我多方翻阅发现这是service在AndroidManifest.xml中新增加的属性android:externalService,当它置为true的时候可以让该Service可以绑定并运行在调用方的App中,而不是在声明这个Service的App中,意不意外惊不惊喜,详细的分析可以参见这个博客android:externalService的功能和原理,这个不是我们的重点不过多分析,我们接着继续往下分析!

接着调用AMS.isSingleton判断我们要查询的目的端Service是否是单例模式,其中符合单例模式需要满足下述三个条件之一:

  • 目的端组件uid>10000,且同时具有ServiceInfo.FLAG_SINGLE_USER flags和INTERACT_ACROSS_USERS权限,说实话这个地方我有个疑问就是目的端进程都没有创建uid怎么就分配了,特殊的进程除外啊
  • 目的端组件运行在system进程的情况
  • 目的端具有ServiceInfo.FLAG_SINGLE_USER flags,且uid=Process.PHONE_UID或者persistent app的情况

如果经过如上一顿猛如虎般的操作之后,依然没有找到合适的ServiceRecord对象,那么则会创建ServiceRecord实例,然后将前面解析,组装出来的相关参数填入ServiceRecord实例对象,然后分别以目的端服务的name和filter为key,存入到smap的mServicesByName和smap的mServicesByIntent。娘的这数据结构,左一坨右一坨的,难受!

3.3.2 ServiceRecord.retrieveAppBindingLocked
//ServiceRecord.java
    final ArrayMap<Intent.FilterComparison, IntentBindRecord> bindings
            = new ArrayMap<Intent.FilterComparison, IntentBindRecord>();
	//创建AppBindRecord对象记录着当前ServiceRecord, intent以及发起方的进程信息。
	public AppBindRecord retrieveAppBindingLocked(Intent intent,
            ProcessRecord app) {
        Intent.FilterComparison filter = new Intent.FilterComparison(intent);
        IntentBindRecord i = bindings.get(filter);
        if (i == null) {
			//创建连接ServiceRecord和fliter的记录
            i = new IntentBindRecord(this, filter);
            bindings.put(filter, i);
        }
		//此处app是指调用方所在进程
        AppBindRecord a = i.apps.get(app);
        if (a != null) {
            return a;
        }
		//创建ServiceRecord跟进程绑定的记录信息
        a = new AppBindRecord(this, i, app);
        i.apps.put(app, a);
        return a;
    }

  说实话看着这一大坨的数据结构对象,真的感觉干不动了。不详细分析了,这里我们需要知道AppBindRecord对象记录着当前ServiceRecord,intent以及发起方的进程信息,并且该记录会存在在ArrayMap对象bindings中存起来,供后续查询!


3.4 bringUpServiceLocked

  我们回到章节3.3继续未完成实名之bringUpServiceLocked,这也可以说是本篇的高潮部分了,因为该方法将会拉起服务端Service,倘若服务端进程还没有创建则会先创建进程进而再拉起服务。所以bringUpServiceLocked会分为两种情况处理!

private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {

		//此种情况前提是要启动的Service所属进程已经创建
		if (r.app != null && r.app.thread != null) {
			//兜兜转转最终调用到目的端Service.onStartCommand()过程,这个过程就不分析了,最后通过ApplicationThreadProxy调用到目的端ActivityThread进而控制目的端Service生命周期执行
            sendServiceArgsLocked(r, execInFg, false);
            return null;
        }
		
	    if (!whileRestarting && r.restartDelay > 0) {
            return null;//等待延迟重启的过程,则直接返回
        }

	  // 启动service前,把service从重启服务队列中移除
	   if (mRestartingServices.remove(r)) {
	       r.resetRestartCounter();
	       clearRestartingIfNeededLocked(r);
	   }
	   //service正在启动,将delayed设置为false
	   if (r.delayed) {
	       getServiceMap(r.userId).mDelayedStartList.remove(r);
	       r.delayed = false;
	   }
	
	   //确保拥有该服务的user已经启动,否则停止,即多用户情况下
	   if (mAm.mStartedUsers.get(r.userId) == null) {
	       String msg = "";
	       bringDownServiceLocked(r);
	       return msg;
	   }
        try {
        	//服务正在启动,设置package停止状态为false
            AppGlobals.getPackageManager().setPackageStoppedState(
                    r.packageName, false, r.userId);
        } catch (RemoteException e) {
        } catch (IllegalArgumentException e) {
			...
        }

		//isolated为true表示Service独立运行到一个特定进程中
        final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
        final String procName = r.processName;
        ProcessRecord app;

        if (!isolated) {
        	//根据进程名和uid,查询ProcessRecord
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            if (app != null && app.thread != null) {//此时
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
					//启动服务
					realStartServiceLocked(r, app, execInFg);
                    return null;
                } catch (TransactionTooLargeException e) {
                    throw e;
                } catch (RemoteException e) {
                    ...
                }
            }
        } else {
            app = r.isolatedProc;
        }

        //对于进程没有启动的情况下,先启动进程
        if (app == null && !permissionsReviewRequired) {
			//启动service所要运行的进程,这就牵涉到Android应用进程创建的流程了
            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    "service", r.name, false, isolated, false)) == null) {//详见章节3.4.1
                bringDownServiceLocked(r);//进程启动失败处理逻辑
                return msg;
            }
            if (isolated) {
                r.isolatedProc = app;
            }
        }

        if (!mPendingServices.contains(r)) {
            mPendingServices.add(r);//注意此处,将ServiceRecord添加到mPendingServices中,后续会遍历此list
        }

        if (r.delayedStop) {
            r.delayedStop = false;
            if (r.startRequested) {
                stopServiceLocked(r);//停止服务
            }
        }

        return null;
    }

前面说过bringUpServiceLocked的启动分为两种情况:

  • 当目标进程已存在,则直接执行realStartServiceLocked();
  • 这个逻辑我想也是小伙们最关心的, 我们后续从这个地方开撸
3.4.1 AMS.startProcessLocked

  startProcessLocked的路漫漫其修远兮吾将上下而求索,这个涉及的代码信息量太大,具体流程小伙们可以参见博客Android应用进程创建流程大揭秘,及最终会调用到目的端进程的ActivityThread.main方法里面,其中的过程大概可以使用如下的流程图表示:

Android bindService校验 安卓bindservice_bindService_10

我们就这ActivityThread.main接着分析(在这里我们只挑和我们这里相关的,其它的暂且不予关注),代码如下:

//ActivityThread.java
    public static void main(String[] args) {
		...
        ActivityThread thread = new ActivityThread();
        thread.attach(false);//参数false是重点
		...
    }
    final ApplicationThread mAppThread = new ApplicationThread();
    private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
        	final IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                mgr.attachApplication(mAppThread);//老套路了啊,远程调用AMS的attachApplication方法,注意这里的参数是IApplicationThread的Binder实体端,该调用流程详见3.4.2
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        } else {//不要问我谁会走此分支,我不会告诉你system_server的创建会走此分支的
			...
        }
    }
3.4.2 AMS.attachApplication

  到这里了我们就不详细分析目的端进程怎么通过Binder框架调用到AMS服务来了,大概的调用流程如下:

AMP.attachApplication() ---> 
BinderProxy.transact() --->
BpBinder.transact()--->
binder驱动传输--->
JavaBBinder.onTransact()--->
AMN.onTransact()--->
AMS.scheduleCreateService()

这个前面章节有具体分析过了,举一反三即可。我们直捣黄龙直接分析AMS的attachApplication方法。

//ActivityMangerService.java
    @Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
			...
            attachApplicationLocked(thread, callingPid);
            ...
        }
    }

    private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
           ...
           if (!badApp) {
	            try {
					//寻找所有需要在该进程中运行的服务
	                didSomething |= mServices.attachApplicationLocked(app, processName);//详见3.4.3
	                checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");
	            } catch (Exception e) {
	                Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
	                badApp = true;
	            }
        }
        ...         
   	}

好吗又调用到了ActiveServices对象实例中去了,我们接着分析其attachApplicationLocked方法。

3.4.2 ActiveServices.attachApplicationLocked
//ActiveServices.java
    boolean attachApplicationLocked(ProcessRecord proc, String processName)
            throws RemoteException {
        boolean didSomething = false;
        //遍历所有在mPendingServices列表中,等待在该进程中启动的service,此处mPendingServices的添加在3.4章节bringUpServiceLocked的最后,即mPendingServices.add阶段
        if (mPendingServices.size() > 0) {
            ServiceRecord sr = null;
            try {
                for (int i=0; i<mPendingServices.size(); i++) {
                    sr = mPendingServices.get(i);
                    if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
                            || !processName.equals(sr.processName))) {
                        continue;
                    }

                    mPendingServices.remove(i);
                    i--;
					//将当前服务的包信息加入到proc
                    proc.addPackage(sr.appInfo.packageName, sr.appInfo.versionCode,
                            mAm.mProcessStats);
					//正常启动service,并开始其的生命周期
                    realStartServiceLocked(sr, proc, sr.createdFromFg);
                    didSomething = true;
                    if (!isServiceNeeded(sr, false, false)) {
                        bringDownServiceLocked(sr);
                    }
                }
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception in new application when starting service "
                        + sr.shortName, e);
                throw e;
            }
        }

		//对于正在等待重启并需要运行在该进程的服务,现在是启动它们的大好时机
		if (mRestartingServices.size() > 0) {
            ServiceRecord sr;
            for (int i=0; i<mRestartingServices.size(); i++) {
                sr = mRestartingServices.get(i);
                if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
                        || !processName.equals(sr.processName))) {
                    continue;
                }
                mAm.mHandler.removeCallbacks(sr.restarter);
                mAm.mHandler.post(sr.restarter);
            }
        }
        return didSomething;
    }

  兜兜转转,又来到了realStartServiceLocked方法,这个和前面章节总结的前后照应了:

  • 即当需要创建新的进程时候,会调用AMS.startProcessLocked启动进程,然后经过千辛万苦的各种辗转最后调用到attachApplicationLocked方法,进而调用realStartServiceLocked方法
  • 若不用创建进程,则直接调用realStartServiceLocked方法,进行剩余工作


3.5 ActiveServices.realStartServiceLocked

//ActiveServices.java
    private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        if (app.thread == null) {
            throw new RemoteException();
        }

        r.app = app;
        r.restartTime = r.lastActivity = SystemClock.uptimeMillis();

        final boolean newService = app.services.add(r);
		//发送delay消息,ANR预埋雷
        bumpServiceExecutingLocked(r, execInFg, "create");//详见3.5.1
        mAm.updateLruProcessLocked(app, false, null);
        mAm.updateOomAdjLocked();

        boolean created = false;
        try {
			...
            mAm.notifyPackageUse(r.serviceInfo.packageName,
                                 PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
            app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
			//这里的app.thread是IApplicationThread服务的远程代理客户端,服务进入onCreate
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);//调用到远程服务端onCreate方法,详见章节3.6
            r.postNotification();
            created = true;
        } catch (DeadObjectException e) {//应用死亡通知
            Slog.w(TAG, "Application dead when creating service " + r);
            mAm.appDiedLocked(app);
            throw e;
        } finally {
            if (!created) {
                // Keep the executeNesting count accurate.
                final boolean inDestroying = mDestroyingServices.contains(r);
                serviceDoneExecutingLocked(r, inDestroying, inDestroying);

                if (newService) {
                    app.services.remove(r);
                    r.app = null;
                    if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) {
                    Slog.w(TAG, " Failed to create Service !!!! ."
                           +"This will introduce huge delay...  "
                           +r.shortName + " in " + r.restartDelay + "ms");
                    }
                }

                // Retry.
                //尝试重新启动服务
                if (!inDestroying) {
                    scheduleServiceRestartLocked(r, false);
                }
            }
        }

        if (r.whitelistManager) {
            app.whitelistManager = true;
        }

		//通过bindService方式启动service
        requestServiceBindingsLocked(r, execInFg);//详见章节5.1

        updateServiceClientActivitiesLocked(app, null, true);


        if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
            r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                    null, null));
        }

		//开启service的生命周期onStartCommand()
        sendServiceArgsLocked(r, execInFg, true);

        if (r.delayed) {
            getServiceMap(r.userId).mDelayedStartList.remove(r);
            r.delayed = false;
        }

        if (r.delayedStop) {
            r.delayedStop = false;
            if (r.startRequested) {
                stopServiceLocked(r);
            }
        }
    }

  记得我们经常说的Android四大组件中不能执行耗时操作吗,小伙们有想过为什么吗?这是因为有Android ANR的预埋雷机制,关于ANR的机制和原理可以详细参见博客理解Android ANR的触发原理,在bumpServiceExecutingLocked会发送一个延迟处理的消息SERVICE_TIMEOUT_MSG。在方法scheduleCreateService执行完成,也就是onCreate回调执行完成之后,便会remove掉该消息。但是如果没能在延时时间之内remove该消息,则会进入执行service timeout流程触发ANR,这就是为啥Android 四大组件不能执行耗时操作的原因。

3.5.1 ActiveServices.bumpServiceExecutingLocked
//ActiveServices.java
    private final void bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why) {

        long now = SystemClock.uptimeMillis();
        if (r.executeNesting == 0) {
            r.executeFg = fg;
            ServiceState stracker = r.getTracker();
            if (stracker != null) {
                stracker.setExecuting(true, mAm.mProcessStats.getMemFactorLocked(), now);
            }
            if (r.app != null) {
                r.app.executingServices.add(r);
                r.app.execServicesFg |= fg;
                if (r.app.executingServices.size() == 1) {
                    scheduleServiceTimeoutLocked(r.app);
                }
            }
        } else if (r.app != null && fg && !r.app.execServicesFg) {
            r.app.execServicesFg = true;
            scheduleServiceTimeoutLocked(r.app);//走入该分支,不要问我为啥,调试打印的结果
        }
        r.executeFg |= fg;
        r.executeNesting++;
        r.executingStart = now;
    }

  不管选择那个分支,最终都会走入scheduleServiceTimeoutLocked方法!

3.5.2 ActiveServices.scheduleServiceTimeoutLocked
//ActiveServices.java
	//前台服务timeout时间为20
    static final int SERVICE_TIMEOUT = 20*1000;
    // 后台服务timeout时间为200s
    static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10;
    void scheduleServiceTimeoutLocked(ProcessRecord proc) {
        if (proc.executingServices.size() == 0 || proc.thread == null) {
            return;
        }
        long now = SystemClock.uptimeMillis();
        Message msg = mAm.mHandler.obtainMessage(
                ActivityManagerService.SERVICE_TIMEOUT_MSG);
        msg.obj = proc;
		//在超时允许的时间内依然没有remove该SERVICE_TIMEOUT_MSG,则会执行SERVICE_TIMEOUT_MSG流程
        mAm.mHandler.sendMessageAtTime(msg,
                proc.execServicesFg ? (now+SERVICE_TIMEOUT) : (now+ SERVICE_BACKGROUND_TIMEOUT));
    }

  还记得我们老说的Service的ANR超时时间吗,什么前台服务是多少,后台服务是多少,一切的源头都在于此,这里会延时发送消息SERVICE_TIMEOUT_MSG,而这个延时的时间可以看到分为两种情况:

  • 对于前台服务,则超时时间为SERVICE_TIMEOUT,即timeout=20s
  • 对于后台服务,则超时间为SERVICE_BACKGROUND_TIMEOUT,即timeout=200s

注意这里的mAm.mHandler是在AMS中进行处理的,其处理逻辑如下所示:

//AMS.java
final class MainHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            	...
	            case SERVICE_TIMEOUT_MSG: {
	                if (mDidDexOpt) {
	                    mDidDexOpt = false;
	                    Message nmsg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
	                    nmsg.obj = msg.obj;
	                    mHandler.sendMessageDelayed(nmsg, ActiveServices.SERVICE_TIMEOUT);
	                    return;
	                }
	                mServices.serviceTimeout((ProcessRecord)msg.obj);//又调用到ActiveServices中去了,老子不跟了
	            } break;   
	            ...         
        	}
        }
}


3.6 ATP.scheduleCreateService

//ApplicationThreadNative.java
    public final void scheduleCreateService(IBinder token, ServiceInfo info,
            CompatibilityInfo compatInfo, int processState) throws RemoteException {
        Parcel data = Parcel.obtain();
        data.writeInterfaceToken(IApplicationThread.descriptor);
        data.writeStrongBinder(token);
        info.writeToParcel(data, 0);
        compatInfo.writeToParcel(data, 0);
        data.writeInt(processState);
        try {
            mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null,
                    IBinder.FLAG_ONEWAY);
        } catch (TransactionTooLargeException e) {
            Log.e("CREATE_SERVICE", "Binder failure starting service; service=" + info);
            throw e;
        }
        data.recycle();
    }

  历史和其的相似,看来在Android源码的学习过程中Binder是一个必须攻克的堡垒啊。这里的ATP是IApplicationThread服务的代理端,然后借助BInder框架会调用到其服务端,而该匿名Binder服务端注册在目的端进程中,其调用过程大概如下:

ATP.scheduleCreateService()---> 
BinderProxy.transact() --->
BpBinder.transact()--->
binder驱动传输--->
JavaBBinder.onTransact()--->
ATN.onTransact()--->
ATN.attachApplication()



四. 目的端进程处理bindService请求

  通过ATP的努力和我们的Binder框架的协助,我们跨越万水千山,完成了system_server所在进程到Service所在目的端进程调用过程,让我们接着分析看看目的端进程是怎么处理bindService的RPC请求的。我好难啊!

4.1 ATN.onTransact

@Override
    //ApplicationThreadNative.java
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        switch (code) {
        ..
        case SCHEDULE_CREATE_SERVICE_TRANSACTION: {
            data.enforceInterface(IApplicationThread.descriptor);//常规操作,读取从binder驱动传递过来的业务数据
            IBinder token = data.readStrongBinder();
            ServiceInfo info = ServiceInfo.CREATOR.createFromParcel(data);
            CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data);
            int processState = data.readInt();
            scheduleCreateService(token, info, compatInfo, processState);//由其子类ApplicationThread实现,详见章节4.2
            return true;
        }
        ...
      }
	}

无需多言,直接进入下一关,打怪升级!


4.2 AT.scheduleCreateService

public final void scheduleCreateService(IBinder token,
                ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
            updateProcessState(processState, false);
            CreateServiceData s = new CreateServiceData();//创建CreateServiceData实例对象,为Service的创建准备数据
            s.token = token;
            s.info = info;
            s.compatInfo = compatInfo;

            sendMessage(H.CREATE_SERVICE, s);
        }

  巧用ActivityThread的主线程的Handler发送消息,这里我们可以总结一下规律,通常AMS通过ATP发送过来的消息,遵循如下的处理逻辑,如下:

scheduleXXX() ---> handleXXX()


4.3 H.handleMessage

//ActivityThread.java
private class H extends Handler {
	public void handleMessage(Message msg) {
	    switch (msg.what) {
	        ...
	        case CREATE_SERVICE:
	            handleCreateService((CreateServiceData)msg.obj); //详见4.4
	            break;
	        case BIND_SERVICE:
	            handleBindService((BindServiceData)msg.obj);//onBind
	            break;
	        case UNBIND_SERVICE:
	            handleUnbindService((BindServiceData)msg.obj);
	            break;
	        case SERVICE_ARGS:
	            handleServiceArgs((ServiceArgsData)msg.obj);  // serviceStart
	            break;
	        case STOP_SERVICE:
	            handleStopService((IBinder)msg.obj);
	            maybeSnapshot();
	            break;
	        ...
	    }
	}
}

无需多言,直接进入下一关,打怪升级!


4.4 AT.handleCreateService创建目的端Service并执行onCreate()方法

//AT.java
    private void handleCreateService(CreateServiceData data) {
        //如果应用处于后台即将进行GC,此时我们将其调回到活动状态,并且跳过本次GC
        unscheduleGcIdler();

        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
			//通过反射创建目标服务对象
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = (Service) cl.loadClass(data.info.name).newInstance();
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to instantiate service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }
        try {
            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);

			//创建ContextImpl对象
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);
			//创建Application对象
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManagerNative.getDefault());
			//调用service服务的onCreate()方法
			service.onCreate();//详见4.4.1
            mServices.put(data.token, service);
            try {
				//调用服务创建完成,将ANR预埋雷除去,看来和AMS的互动很频繁啊
                ActivityManagerNative.getDefault().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);//详见章节4.5
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to create service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }
    }

该段代码,主要执行两个业务逻辑:

  • 执行目的端Service的onCreate方法
  • 调用AMS的serviceDoneExecuting方法,解除在前面3.5.2章节预埋的ANR雷,不然真的会爆炸的
4.4.1 Services.onCreate
//Services.java
    public void onCreate() {
    }

  我曾跨过山河大海也穿过人山人海,终于来到了目标进程Service的生命周期onCreate方法中,通常Service的子类会重写该方法!不容易啊,终于看到了胜利曙光,但是还没有结束,依然还需要战斗!


4.5 AMS.serviceDoneExecuting

不要问我为啥来到此处,这都是套路,慢慢的套路!

//AMS.java
    public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
        synchronized(this) {
            if (!(token instanceof ServiceRecord)) {
                Slog.e(TAG, "serviceDoneExecuting: Invalid service token=" + token);
                throw new IllegalArgumentException("Invalid service token");
            }
            //AMS很闲啊,啥也不干全部扔给了ActivityServices处理了,详见4.5.1
            mServices.serviceDoneExecutingLocked((ServiceRecord)token, type, startId, res);
        }
    }

无需多言,直接进入下一关,打怪升级!

4.5.1 ActivityServices.serviceDoneExecutingLocked
//ActivityServices.java
    void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {
    	if (r != null) {
    		...
    		final long origId = Binder.clearCallingIdentity();
            serviceDoneExecutingLocked(r, inDestroying, inDestroying);//详见4.5.2
            Binder.restoreCallingIdentity(origId);
            ...
    	}
    	...
    }

我感觉Android的开发工程师也很难受,一个方法里面代码太多了吗,小伙们说这个裹脚布,搞方法太多了吗,跳转的难受!

4.5.2 ActivityServices.serviceDoneExecutingLocked
private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying, boolean finishing) {
    r.executeNesting--;
    if (r.executeNesting <= 0) {
        if (r.app != null) {
            r.app.execServicesFg = false;
            r.app.executingServices.remove(r);
            if (r.app.executingServices.size() == 0) {
                //移除服务启动超时的消息,将ANR的雷排除
                mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
            } else if (r.executeFg) {
                ...
            }
            if (inDestroying) {
                mDestroyingServices.remove(r);
                r.bindings.clear();
            }
            mAm.updateOomAdjLocked(r.app);
        }
        r.executeFg = false;
        ...
        if (finishing) {
            if (r.app != null && !r.app.persistent) {
                r.app.services.remove(r);
            }
            r.app = null;
        }
    }
}

  在此处终于将执行removeMessages将3.5.2章节预埋的ANR雷移除,即将消息息SERVICE_TIMEOUT_MSG从Handler的消息队列中移除。分析至此,小伙们应该了解了Service启动过程出现ANR,”executing service [发送超时serviceRecord信息]”,这往往是service的onCreate()回调方法执行时间过长的原因了。




五. 重返system_server进程

  此时的我在那里,该何处何从。此时让我们穿越时空重新回到system_server进程,继续章节3.5之未完成实名,革命仍未成功还需努力啊。

5.1 AS.requestServiceBindingsLocked

//ActivityServices.java
    private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)
            throws TransactionTooLargeException {
        for (int i=r.bindings.size()-1; i>=0; i--) {//遍历有多少需要bindings的Service
            IntentBindRecord ibr = r.bindings.valueAt(i);
            if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {//调用另外一个重载的requestServiceBindingLocked方法
                break;
            }
        }
    }

    private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
            boolean execInFg, boolean rebind) throws TransactionTooLargeException {
        if (r.app == null || r.app.thread == null) {
            return false;
        }
        if ((!i.requested || rebind) && i.apps.size() > 0) {
            try {
				//发送bind开始的消息,又开始埋雷了
                bumpServiceExecutingLocked(r, execInFg, "bind");
                r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
				//服务进入onBind()
				r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                        r.app.repProcState);
                if (!rebind) {
                    i.requested = true;
                }
                i.hasBound = true;
                i.doRebind = false;
            } catch (TransactionTooLargeException e) {
                final boolean inDestroying = mDestroyingServices.contains(r);
                serviceDoneExecutingLocked(r, inDestroying, inDestroying);
                throw e;
            } catch (RemoteException e) {
                final boolean inDestroying = mDestroyingServices.contains(r);
                serviceDoneExecutingLocked(r, inDestroying, inDestroying);
                return false;
            }
        }
        return true;
    }

  通过bindService方式启动的服务, 那么该serviceRecord的bindings则一定不会空,不然后续的工作咋开展呢!而这里的入参ServiceRecord实例对象的创建可以回到章节3.5温故温故。接着继续调用重载的requestServiceBindingLocked方法继续处理,而在该重载的方法中主要执行了两项操作:

  • 调用bumpServiceExecutingLocked方法继续埋雷,倘若目标Service的onBind方法没有在指定的时间内执行完毕,则会触发ANR,这个已经在前面有过详细分析了
  • 接着调用目标服务端进程的AT代理端ATP的方法scheduleBindService,向AT发送Binder请求

5.2 ATP.scheduleBindService

//ApplicationThreadNative.java
    public final void scheduleBindService(IBinder token, Intent intent, boolean rebind,
            int processState) throws RemoteException {
        Parcel data = Parcel.obtain();
        data.writeInterfaceToken(IApplicationThread.descriptor);
        data.writeStrongBinder(token);
        intent.writeToParcel(data, 0);
        data.writeInt(rebind ? 1 : 0);
        data.writeInt(processState);
        mRemote.transact(SCHEDULE_BIND_SERVICE_TRANSACTION, data, null,
                IBinder.FLAG_ONEWAY);
        data.recycle();
    }

  AMS和AT之间的交互很频繁啊,目的端进程和system_server进程之间通过IApplicationThread和IActivityManager来回的折腾着。这里的ATP是IApplicationThread服务的代理端,然后借助BInder框架会调用到其服务端,而该匿名Binder服务端注册在目的端进程中,其调用过程大概如下:

ATP.scheduleBindService()---> 
BinderProxy.transact() --->
BpBinder.transact()--->
binder驱动传输--->
JavaBBinder.onTransact()--->
ATN.onTransact()--->
ATN.scheduleBindService()



六. 重返目的端服务进程

  这么来回的跳转,折腾着感觉心好累啊!但是木有办法,要想深入只能是操起锤子接着干了。

6.1 ATN.onTransact

@Override
    //ApplicationThreadNative.java
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        switch (code) {
        ..
        case SCHEDULE_BIND_SERVICE_TRANSACTION: {
            data.enforceInterface(IApplicationThread.descriptor);
            IBinder token = data.readStrongBinder();
            Intent intent = Intent.CREATOR.createFromParcel(data);
            boolean rebind = data.readInt() != 0;
            int processState = data.readInt();
            scheduleBindService(token, intent, rebind, processState);//在其子类AT中实现该方法
            return true;
        }
        ...
      }
	}

无需多言,直接进入下一关,打怪升级!


6.2 AT.scheduleBindService

public final void scheduleBindService(IBinder token, Intent intent,
                boolean rebind, int processState) {
            updateProcessState(processState, false);
            BindServiceData s = new BindServiceData();//创建BindServiceData实例对象,接收AMS传递过来的Service信息
            s.token = token;
            s.intent = intent;
            s.rebind = rebind;

            sendMessage(H.BIND_SERVICE, s);
        }

  巧用ActivityThread的主线程的Handler发送消息,这里我们可以总结一下规律,通常AMS通过ATP发送过来的消息,遵循如下的处理逻辑,如下:

scheduleXXX() ---> handleXXX()


6.3 H.handleMessage

//ActivityThread.java
private class H extends Handler {
	public void handleMessage(Message msg) {
	    switch (msg.what) {
	        ...
	        case CREATE_SERVICE:
	            handleCreateService((CreateServiceData)msg.obj); //onCreate
	            break;
	        case BIND_SERVICE:
	            handleBindService((BindServiceData)msg.obj);//onBind,详见6.4
	            break;
	        case UNBIND_SERVICE:
	            handleUnbindService((BindServiceData)msg.obj);
	            break;
	        case SERVICE_ARGS:
	            handleServiceArgs((ServiceArgsData)msg.obj);  // serviceStart
	            break;
	        case STOP_SERVICE:
	            handleStopService((IBinder)msg.obj);
	            maybeSnapshot();
	            break;
	        ...
	    }
	}
}

无需多言,直接进入下一关,打怪升级!


6.4 AT.handleBindService

//AT.java
    private void handleBindService(BindServiceData data) {
        Service s = mServices.get(data.token);
        if (DEBUG_SERVICE)
            Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
        if (s != null) {
            try {
                data.intent.setExtrasClassLoader(s.getClassLoader());
                data.intent.prepareToEnterProcess();
                try {
                    if (!data.rebind) {
						//执行Service.onBind()回调方法,此时在远程服务进程的主线程中
                        IBinder binder = s.onBind(data.intent);
						//将onBinde返回值传递回去,注意这里的binder还是Binder服务端,只有经过Binder传输以后才变成了代理端
						//这里的ActivityManagerNative.getDefault()获取的是AMS的代理端AMP
                        ActivityManagerNative.getDefault().publishService(
                                data.token, data.intent, binder);
                    } else {
                        s.onRebind(data.intent);
                        ActivityManagerNative.getDefault().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);
                }
            }
        }
    }

该段代码,主要执行两个业务逻辑:

  • 执行目的端Service的onBind方法
  • 调用AMS的publishService方法,即将获取到Service中的匿名Binder实体通过Binder传递到AMS中
6.4.1 Services.onBind
//Services.java
    @Nullable
    public abstract IBinder onBind(Intent intent);

  我曾跨过山河大海也穿过人山人海,终于来到了目标进程Service的生命周期onBind方法中,Service的onBind()是抽象方法, 所以大家创建Service子类时必须要覆写该方法, 返回IBinder对象, 也可以直接返回NULL.


6.5 AMP.publishService

//ActivityManagerNative.java
    public void publishService(IBinder token,
            Intent intent, IBinder service) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(token);
        intent.writeToParcel(data, 0);
		//将service.onbind的返回值传递给远端进程,这里写入的是bind目的服务端的Binder实体对象,经过Binder传输以后会转变成Binder代理端,并在AMS的内核进程中创建一个binder_ref引用	
        data.writeStrongBinder(service);
        mRemote.transact(PUBLISH_SERVICE_TRANSACTION, data, reply, 0);
        reply.readException();
        data.recycle();
        reply.recycle();
    }

  AMS和AT之间的交互很频繁啊,目的端进程和system_server进程之间通过IApplicationThread和IActivityManager来回的折腾着。这里的AMP是IActivityManager服务的代理端,然后借助BInder框架会调用到其服务端AMS,其调用过程大概如下:

AMP.publishService()---> 
BinderProxy.transact() --->
BpBinder.transact()--->
binder驱动传输--->
JavaBBinder.onTransact()--->
AMN.onTransact()--->
AMN.publishService()



七. 三进system_server进程

是时候展现真正的实力了,怎么从AMP到AMS的过程我们就不细说了,因为本篇博客里面已经有很多次这种操作了。我们直奔主题进入AMS。

7.1 AMS.publishService

//AMS.java
    public void publishService(IBinder token, Intent intent, IBinder service) {
        if (intent != null && intent.hasFileDescriptors() == true) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }

        synchronized(this) {
            if (!(token instanceof ServiceRecord)) {
                throw new IllegalArgumentException("Invalid service token");
            }
            //这里需要关注的是入参service为目的端IBinder的代理端
            mServices.publishServiceLocked((ServiceRecord)token, intent, service);
        }
    }

  远程服务的onBind()在目的服务端进程的返回值的IBinder类型是(Bn端), 在AMP.publishService()过程中经过data.writeStrongBinder(service)传递到底层驱动在system_server内核的binder_proc中创建上述IBinder实体的binder_ref引用, 再回到system_server进程中AMN.onTransact()中经过data.readStrongBinder()方法会获取该service所相对应的代理对象(Bp端).总而言之,此处的IBinder类型的service就是远程服务进程中的Bp端对象,并且此处的IBinder类型的service就是一个典型的匿名Binder,它并没有向servicemanager进程注册。


7.2 AS.publishServiceLocked

//AS.java
	//注意此处的入参service为我们要启动服务端的代理端即(Bp)
    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;
                            }
                            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Publishing to: " + c);
                            try {
								//c.conn是指通往发起端进程的IServiceConnection.Stub.Proxy代理对象
                                c.conn.connected(r.name, service);//
                            } catch (Exception e) {
								...
                            }
                        }
                    }
                }
                //解除章节5.1预先埋雷
                serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }

  此处是关键,让我们先缓一缓。这里先取出ServiceRecord 中的ConnectionRecord列表,然后匹配对应的intent消息,如果匹配到则取出ConnectionRecord中的IServiceConnection实例对象conn,先换缓缓,这个ServiceRecord和ConnectionRecord又是啥时候创建的呢,这个就要回到章节3.3和章节3.3.1其中涉及到了ServiceRecord和ConnectionRecord创建。

还有一个核心就是这里的c.conn指代什么呢,关于此处就得回到2.3章节细品了,这里我们给出结论c.conn是指通往发起端进程的IServiceConnection.Stub.Proxy代理对象,其是经由Binder调用从发起端进程传递过来的,而我们此时通过该代理端通过Binder IPC调用到进入发起方进程的IServiceConnection.Stub实体中。关于该匿名Binder的传递路线如下所示:

发起端进程(IServiceConnection.Stub) ---> Binder驱动 ---->system_server进程(IServiceConnection.Stub.Proxy)

并且根据前面的分析可知,由于LoadedApk.ServiceDispatcher.InnerConnection 继承于IServiceConnection.Stub. 所以,接下来便由回到发起方进程中的InnerConnection对象,关于其调用过程这里简单阐述一下:

IServiceConnection.Stub.Proxy.connected()---> 
BinderProxy.transact() --->
BpBinder.transact()--->
binder驱动传输--->
JavaBBinder.onTransact()--->
IServiceConnection.Stub.onTransact()--->
InnerConnection.connected()



八. 重返发起端进程

  来返往复,曲折之路告一段落,我们终于返回了发起端进程。让我们接着来到发起端进程的LoadedApk.ServiceDispatcher.InnerConnection分析之,关于LoadedApk可以回过头到2.3.1章节看看其类图,再巩固巩固!

8.1 InnerConnection.connected

//LoadedApk.java[InnerConnection]
        private static class InnerConnection extends IServiceConnection.Stub {
            final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;

            InnerConnection(LoadedApk.ServiceDispatcher sd) {
                mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
            }

            public void connected(ComponentName name, IBinder service) throws RemoteException {
                LoadedApk.ServiceDispatcher sd = mDispatcher.get();
                if (sd != null) {//注意此处的sd为LoadedApk.ServiceDispatcher实例
                    sd.connected(name, service);//详见章节8.2
                }
            }
        }

无需多言,直接进入下一关,打怪升级!


8.2 ServiceDispatcher.connected

//LoadedApk.java[ServiceDispatcher]
        public void connected(ComponentName name, IBinder service) {
            if (mActivityThread != null) {//走此分支,mActivityThread不为null,并且这里的mActivityThread是一个Handler不是ActivtyThread,可以从章节2.2看到这个Handler是发起端主线程的Handler,接下来详见8.3
                mActivityThread.post(new RunConnection(name, service, 0));
            } else {
                doConnected(name, service);
            }
        }

无需多言,直接进入下一关,打怪升级!


8.3 RunConnection.run

//LoadedApk.java[RunConnection]
        private final class RunConnection implements Runnable {
            RunConnection(ComponentName name, IBinder service, int command) {
                mName = name;
                mService = service;
                mCommand = command;
            }

            public void run() {
                if (mCommand == 0) {
                    doConnected(mName, mService);
                } else if (mCommand == 1) {
                    doDeath(mName, mService);
                }
            }

            final ComponentName mName;
            final IBinder mService;
            final int mCommand;
        }

  关于Handerl.post用法就不用多讲了,最后会触发RunConnection 的run方法执行,这里我们要注意doConnected方法的两个入参:

  • mName指代我们bind的目的端远程Service的组件名对象ComponentName 实例
  • mService指代我们bind的目的端远程端服务onBind()返回的返回的Binder实体的代理端对象


8.3 ServiceDispatcher.doConnected

//LoadedApk.java[ServiceDispatcher]
        public void doConnected(ComponentName name, IBinder service) {
            ServiceDispatcher.ConnectionInfo old;
            ServiceDispatcher.ConnectionInfo info;

            synchronized (this) {
                if (mForgotten) {
                    return;
                }
                old = mActiveConnections.get(name);
                if (old != null && old.binder == service) {
                    return;
                }

                if (service != null) {
                    info = new ConnectionInfo();
                    info.binder = service;
					//创建死亡监听对象
                    info.deathMonitor = new DeathMonitor(name, service);
                    try {
						//建立死亡通知,绑定到目的端Service IBinder实体,详见8.4
                        service.linkToDeath(info.deathMonitor, 0);
                        mActiveConnections.put(name, info);
                    } catch (RemoteException e) {
                        mActiveConnections.remove(name);
                        return;
                    }

                } else {
                    mActiveConnections.remove(name);
                }

                if (old != null) {
                    old.binder.unlinkToDeath(old.deathMonitor, 0);
                }
            }

            if (old != null) {
                mConnection.onServiceDisconnected(name);
            }
            if (service != null) {
				//回调用户的onServiceConnected方法
                mConnection.onServiceConnected(name, service);
            }
        }

  到此处分析起来也比较简单了,主要执行了如下两个逻辑:

  • 先行创建死亡监听对象,也是内部类:LoadedApk.ServiceDispatcher.DeathMonitor,监听目的端服务Binder的情况
  • 调用用户传递过来的回调类ServiceConnection的onServiceConnected方法


8.5 DeathMonitor

LoadedApk.java[DeathMonitor ]
        private final class DeathMonitor implements IBinder.DeathRecipient
        {
            DeathMonitor(ComponentName name, IBinder service) {
                mName = name;
                mService = service;
            }

            public void binderDied() {
                death(mName, mService);
            }

            final ComponentName mName;
            final IBinder mService;
        }

        public void doDeath(ComponentName name, IBinder service) {
            synchronized (this) {
                ConnectionInfo old = mActiveConnections.get(name);
                if (old == null || old.binder != service) {
                    // Death for someone different than who we last
                    // reported...  just ignore it.
                    return;
                }
                mActiveConnections.remove(name);
                old.binder.unlinkToDeath(old.deathMonitor, 0);
            }

            mConnection.onServiceDisconnected(name);
        }

此处不在本文的分析的重点之内,总之这里会监听目的服务端的情况,如果其发生了异常则会通知到其bind的发起端!关于DeathMonitor强烈推荐参见博客Binder死亡通知机制之linkToDeath




总结

  至此,bindService已经基本分析完毕了,是时候重新拿去时序图来重新总结一把了,时序图如下:

Android bindService校验 安卓bindservice_Android_11

  • 小伙伴门有没有发现在bindService中牵涉到了大量的Binder IPC,在Android的源码分析里真的是学好Android Binder很重要啊,并且在交互过程中牵涉到了好几处的匿名Binder,小伙们能找出来吗
  • 并且关于上述时序图中,红色代表Binder通信,绿色类代表发起端进程持有,黄色类代表system_server进程持有,蓝色代类代表目的端进程持有
从进程交互角度出发
  • 发起端进程: 首先通过bindService携带接口回调类ServiceConnection传递到LoadedApk中,接着在该类中通过getServiceDispatcher获取发起端进程的匿名Binder服务端(此为第一处匿名Binder),即LoadedApk.ServiceDispatcher.InnerConnection,该对象继承于IServiceConnection.Stub;再通过bindService调用到system_server进程
  • system_server进程: 依次通过scheduleCreateService和scheduleBindService方法, 远程调用到目的端进程进程(这里的前提是目的端进程已经创建,如果服务端进程还没有创建,则还牵涉到目的服务端进程的创建)
  • 目的端进程: 依次执行目的端Service的onCreate()和onBind()方法;,然后将onBind()方法的返回值IBinder(作为目的端进程匿名的Binder服务端,此处为第二处匿名Binder服务端),接着通过publishService将该匿名Binder服务端的代理端传递到system_server进程
  • system_server进程: 经过上述的一系列处理以后,利用IServiceConnection代理对象向发起端进程发起connected()调用, 并把target进程的onBind返回Binder对象的代理端传递到发起端进程
  • 发起端: 回调到onServiceConnection()方法, 该方法的第二个参数便是目的端进程的Binder代理端. 到此便成功地拿到了目的端进程的代理, 可以畅通无阻地进行RPC交互了


从匿名Binder传递角度出发

还记得我们一开篇就说的匿名/实名Binder吗,综管全篇不知小伙们发现没有其实bindService的实质就是匿名Binder跨进程的传递,当然也不全是毕竟还是目的端进程创建的一些操作呢!那么我们站在匿名Binder传递的角度来看看bindService的流程,其最最核心的一点就是目的端Service IBinder匿名BInder服务端怎么传递到发起端,其传递过程大概如下:

目的端Service(IBinder实体) ---->
Binder驱动传递 --->
system_server进程(IBinder实体对应的代理端) --->
发起端进程(IBinder实体对应的代理端)