Android进程间通讯(二)AIDL、Binder、bindService源码分析

Android进程间通讯(一)Binder介绍及AIDL的具体使用
Android进程间通讯(二)AIDL、Binder源码分析

AIDL没使用过的,可以先看前一篇文章Android进程间通讯(一)AIDL的具体使用
我们在上一篇文章中提到了三个问题
1、客户端是怎么获取这个遥控器的呢?
2、这个遥控器又是怎么调用到服务端代码的呢?
3、就算把服务端app杀死了,客户端为什么还能调用到服务端的代码?

我们从客户端获取iLeoAidl对象作为入口具体到源码分析

 private void bindService() {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.xx.leo_service", "com.xx.leo_service.LeoAidlService"));
        bindService(intent, connection, Context.BIND_AUTO_CREATE);
    }
 private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.e(TAG, "onServiceConnected: success");
            iLeoAidl = ILeoAidl.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.e(TAG, "onServiceDisconnected: success");
            iLeoAidl = null;
        }
    };

客户端先通过bindService方法进行绑定服务,然后在onServiceConnected连接成功的监听函数里,然后将IBinder的对象service,传入到ILeoAidl.Stub.asInterface方法里获取到 iLeoAidl对象。
所以我们有两处源码要分析

  • 1、 bindService(intent, connection, Context.BIND_AUTO_CREATE);是怎么进行绑定的?
  • 2、ILeoAidl.Stub.asInterface(service);是怎么获取到AIDL对象的?
    我们先看看客户端是怎么获取到AIDL对象的。我们点进去进入源码
public interface ILeoAidl extends android.os.IInterface {
    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements com.xx.leo_service.ILeoAidl {
        private static final java.lang.String DESCRIPTOR = "com.xx.leo_service.ILeoAidl";

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

        /**
         * Cast an IBinder object into an com.xx.leo_service.ILeoAidl interface,
         * generating a proxy if needed.
         */
        public static com.xx.leo_service.ILeoAidl asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.xx.leo_service.ILeoAidl))) {
                return ((com.xx.leo_service.ILeoAidl) iin);
            }
            return new com.xx.leo_service.ILeoAidl.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_addPerson: {
                    data.enforceInterface(DESCRIPTOR);
                    com.xx.leo_service.Person _arg0;
                    if ((0 != data.readInt())) {
                        _arg0 = com.xx.leo_service.Person.CREATOR.createFromParcel(data);
                    } else {
                        _arg0 = null;
                    }
                    this.addPerson(_arg0);
                    reply.writeNoException();
                    return true;
                }
                case TRANSACTION_getPersonList: {
                    data.enforceInterface(DESCRIPTOR);
                    java.util.List<com.xx.leo_service.Person> _result = this.getPersonList();
                    reply.writeNoException();
                    reply.writeTypedList(_result);
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements com.xx.leo_service.ILeoAidl {
            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 addPerson(com.xx.leo_service.Person person) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    if ((person != null)) {
                        _data.writeInt(1);
                        person.writeToParcel(_data, 0);
                    } else {
                        _data.writeInt(0);
                    }
                    mRemote.transact(Stub.TRANSACTION_addPerson, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            @Override
            public java.util.List<com.xx.leo_service.Person> getPersonList() throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                java.util.List<com.xx.leo_service.Person> _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_getPersonList, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.createTypedArrayList(com.xx.leo_service.Person.CREATOR);
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }

        static final int TRANSACTION_addPerson = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_getPersonList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    }

    public void addPerson(com.xx.leo_service.Person person) throws android.os.RemoteException;

    public java.util.List<com.xx.leo_service.Person> getPersonList() throws android.os.RemoteException;
}

其实ILeoAidl这个接口是系统通过我们写的aidl文件帮我们生成的模板(所以客户端和服务端的app都会有这个类)。我们先大致看下这个接口的结构


image.png

我们发现public interface ILeoAidl extends android.os.IInterface
ILeoAidl是继承自IInterface的,里面有两个内部类:Stub和Proxy。

  • Stub:用来接收数据、抽象类、继承Binder并实现ILeoAidl
  • Proxy:用来发送数据的、实体类、实现ILeoAidl

看到上面的结构图,我们知道:Stub是接口ILeoAidl的内部类,Proxy又是Stub的内部类,我们直接进入Stub的asInterface方法,看看客户端是怎么获取AIDL对象。

        public static abstract class Stub extends android.os.Binder implements com.xx.leo_service.ILeoAidl {
        private static final java.lang.String DESCRIPTOR = "com.xx.leo_service.ILeoAidl";

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

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

首先会判断,传进来的service是不是空,是空就直接返回了,然后走到obj.queryLocalInterface(DESCRIPTOR),我们看到DESCRIPTOR是"com.xx.leo_service.ILeoAidl"是aidl的全类名。我们再进入queryLocalInterface方法的具体实现,是在Binder的queryLocalInterface方法里

 public IInterface queryLocalInterface(String descriptor) {
        if (mDescriptor.equals(descriptor)) {
            return mOwner;
        }
        return null;
    }

它是比较传进来的和mDescriptor是否相等,相等的话就返回IInterface类型的 mOwner成员变量;
我们再看到stub的构造函数

 public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

  public void attachInterface(IInterface owner, String descriptor) {
        mOwner = owner;
        mDescriptor = descriptor;
    }

也就是一开始会把DESCRIPTOR赋值给mDescriptor,把this赋值给owner,那是不是一开始进来就相等了呢?其实不是相等的,因为asInterface是静态方法,是不会走构造方法的,所以通过 ILeoAidl.Stub.asInterface(service);这条路进来的,mDescriptor是空的,是没有赋值的。现在我们看我们服务端的app的代码,
image.png

是通过new Stub的,所以通过服务端进来的Binder类的成员变量mDescriptor是有值的,就是等于aidl的全类名。
所以如果我们服务端和客户端是在一个进程的话,mDescriptor是有值的,如果不是在同一进程的话是没有值的,所以这个判断obj.queryLocalInterface(DESCRIPTOR);就是来判断客户端和服务端是否在一个进程的,如果在一个进程就直接返回全类名下的ILeoAidl,如果不是同一进程,就返回Stub里的Proxy。因为我们的例子是在不同进程的,所以通过iLeoAidl = ILeoAidl.Stub.asInterface(service);我们就拿到了Proxy对象了。所以我们就能调用Proxy对象里的方法了,那么我们客户端是在什么时候调用Proxy里的方法的呢?就是上一篇文章里讲的在点击按钮的时候

 btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    iLeoAidl.addPerson(new Person("小三爷", 3));
                    List<Person> persons = iLeoAidl.getPersonList();
                    Log.e(TAG,persons.size()+persons.toString());
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });

这时候 iLeoAidl.addPerson就调用了Proxy里的addPerson了所以,我们先看看
Proxy里的addPerson方法

 @Override
            public void addPerson(com.xx.leo_service.Person person) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    if ((person != null)) {
                        _data.writeInt(1);
                        person.writeToParcel(_data, 0);
                    } else {
                        _data.writeInt(0);
                    }
                    mRemote.transact(Stub.TRANSACTION_addPerson, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

_data 是用来存储发送到服务端的数据的;_reply是存储服务端返回的数据的,
_data.writeInterfaceToken(DESCRIPTOR)是来校验的,因为可能一个进程可能会调用多个服务(App里调用多个服务,就要生成多个AIDL,每个服务都要有一个AIDL与之对应),所以要校验下,具体是native方法,我们就不进去看了,
然后往_data 里写入数据,最后调用mRemote.transact(Stub.TRANSACTION_addPerson, _data, _reply, 0);运行到这里的时候,客户端的线程会挂起,直到服务端返回数据,客户端线程才会继续运行。Stub.TRANSACTION_addPerson就是标志方法的位置的整形数值,因为我们客户端和服务端都是知道.aidl里所有方法的全类名的,这里只要标志下哪个方法在哪个位置就行了。我们点击transact方法看下

   public final boolean transact(int code, Parcel data, Parcel reply,
            int flags) throws RemoteException {
        if (false) Log.v("Binder", "Transact: " + code + " to " + this);
        if (data != null) {
            data.setDataPosition(0);
        }
        boolean r = onTransact(code, data, reply, flags);
        if (reply != null) {
            reply.setDataPosition(0);
        }
        return r;
    }
    

我们就来到了Binder类的transact方法,我们现在可以先理解为:调用mRemote.transact就调用Binder的transact方法,然后Binder经过一系列处理
调用到服务端aidl里的Stub的onTransact接收数据,所以我们先看服务端的onTransact方法

 @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_addPerson: {
                    data.enforceInterface(DESCRIPTOR);
                    com.xx.leo_service.Person _arg0;
                    if ((0 != data.readInt())) {
                        _arg0 = com.xx.leo_service.Person.CREATOR.createFromParcel(data);
                    } else {
                        _arg0 = null;
                    }
                    this.addPerson(_arg0);
                    reply.writeNoException();
                    return true;
                }
                case TRANSACTION_getPersonList: {
                    data.enforceInterface(DESCRIPTOR);
                    java.util.List<com.xx.leo_service.Person> _result = this.getPersonList();
                    reply.writeNoException();
                    reply.writeTypedList(_result);
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }

我们看到TRANSACTION_addPerson,这个就是添加person的方法,一开始也是校验了下,然后取出data赋值给this.addPerson(_arg0);,我们知道Stub里并没有实现addPerson的地方,其实这个this.addPerson方法调用的就是服务端自己写的LeoAidlService里的addPerson方法。


image.png

那么现在,我们就完成了完整的分析了客户端到服务端的调用。

image.png

image.png

现在我们再通过上面的流程图分析下整个流程

1、客户端调用iLeoAidl.addPerson就会跑到Proxy里面
2、Proxy就会调用mRemote.transact调用到Binder里来
3、Binder调用onTransact就会跑到服务端的Stub里
4、服务端的Stub的onTransact里调用this.addPerson就会跑到服务端自己的LeoAidlService里

分析完客户端和服务端的通信,现在进入下一个问题:bindService(intent, connection, Context.BIND_AUTO_CREATE);客户端和服务端是怎么进行绑定的?

在分析这个问题之前,我们来讲下android系统里的一些服务相关的理解,比如闹钟服务和通话服务,其实我们app去访问这些服务也是跨进程的,那么系统那么多服务,Android系统是怎么管理的呢?就是ServiceManager,用来管理系统中的service的,而ServiceManager自身也是一个服务,所以我们调用闹钟这些服务的时候,会通过proxy先去调用ServiceManager,然后ServiceManager去中找到闹钟这些服务,和我们绑定,然后我们才能调用闹钟服务里的一些方法。所以我们去找ServiceManager也是通过AIDL的,所以分析下面的源码的时候要结合前面的AIDL流程一起分析。

现在我们正式进入绑定流程的分析我们点进bindService方法

 @Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        return mBase.bindService(service, conn, flags);
    }

来到ContextWrapper的bindService方法,方法里实际是调用了Context的bindService,我们知道Context是个abstract类,我们都知道实现是在ContextImpl里。所以我们看到ContextImpl这里的bindService方法


 @Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        warnIfCallingFromSystemProcess();
        return bindServiceCommon(service, conn, flags, Process.myUserHandle());
    }

我们看到是跑到bindServiceCommon里

  private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
            UserHandle user) {
        IServiceConnection sd;
        if (conn == null) {
            throw new IllegalArgumentException("connection is null");
        }
        if (mPackageInfo != null) {
            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
                    mMainThread.getHandler(), flags);
        } else {
            throw new RuntimeException("Not supported in system context");
        }
        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();
            int res = ActivityManagerNative.getDefault().bindService(
                mMainThread.getApplicationThread(), getActivityToken(), service,
                service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, getOpPackageName(), user.getIdentifier());
            if (res < 0) {
                throw new SecurityException(
                        "Not allowed to bind to service " + service);
            }
            return res != 0;
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
    }

我们看到这样一段代码 int res =ActivityManagerNative.getDefault().bindService
我看进到getDefault方法,

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

我们看到是返回一个IActivityManager,我们点进IActivityManager,看到ActivityManager是继承自IInterface的。之前分析流程的时候android系统给我们生成的aidl文件ILeoAidl也是继承自IInterface的。所以我们得出。通过aidl去找ServiceManager的时候

IActivityManager类比ILeoAidl

我们知道ILeoAidl接口里是有stub和proxy内部类的,这里我们并没有看到啊,所以我们还是回到getDefault里,我们看看getDefault


  private static final Singleton<IActivityManager> getDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

我们是不是看到一段熟悉的代码啊IActivityManager am = asInterface(b);我们之前是不是通过ILeoAidl.Stub.asInterface(service);获取到Proxy对象的,所以这里的IActivityManager am 我们可以类比成Proxy实例对象,getDefault最终就是返会am的,而且asInterface是Stub里的方法,所以我们再点进去看看

public abstract class ActivityManagerNative extends Binder implements IActivityManager
{
    /**
     * Cast a Binder object into an activity manager interface, generating
     * a proxy if needed.
     */
    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);
    }

我们看ActivityManagerNative是不是很像Stub,继承自Binder,实现AIDL接口

ActivityManagerNative类比Stub

我们看到最后一句, return new ActivityManagerProxy(obj);
所以我们看到ActivityManagerNative的结构图


image.png

class ActivityManagerProxy implements IActivityManager
{
    public ActivityManagerProxy(IBinder remote)
    {
        mRemote = remote;
    }

ActivityManagerProxy实现了IActivityManager,也就是实现了aidl接口

ActivityManagerProxy类比Proxy

所以我们再回到int res = ActivityManagerNative.getDefault().bindService这段代码,因为ActivityManagerNative.getDefault().是返回Proxy的实例对象的,所以我们找找ActivityManagerProxy里的bindService方法

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();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeStrongBinder(token);
        service.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeStrongBinder(connection.asBinder());
        data.writeInt(flags);
        data.writeString(callingPackage);
        data.writeInt(userId);
        mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);
        reply.readException();
        int res = reply.readInt();
        data.recycle();
        reply.recycle();
        return res;
    }

这个bindService方法是不是和我们之前的addPerson方法很像啊?
开始先获取data和reply,然后往data里塞数据,再校验descriptor,然后调用 mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);
方法,就跑到服务端Stub里的onTransact方法里去了,所以我们找到ActivityManagerNative的onTransact方法的BIND_SERVICE_TRANSACTION的case条件

 case BIND_SERVICE_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            IBinder b = data.readStrongBinder();
            IApplicationThread app = ApplicationThreadNative.asInterface(b);
            IBinder token = data.readStrongBinder();
            Intent service = Intent.CREATOR.createFromParcel(data);
            String resolvedType = data.readString();
            b = data.readStrongBinder();
            int fl = data.readInt();
            String callingPackage = data.readString();
            int userId = data.readInt();
            IServiceConnection conn = IServiceConnection.Stub.asInterface(b);
            int res = bindService(app, token, service, resolvedType, conn, fl,
                    callingPackage, userId);
            reply.writeNoException();
            reply.writeInt(res);
            return true;
        }

这里我们看到 int res = bindService(app, token, service, resolvedType, conn, fl,callingPackage, userId);这一段,我们之前知道在stub的onTransact调用的是就是真正的service,就像我们之前调用LeoAidlService里真正的addPerson方法一样,而Android系统的核心服务就是AMS(ActivityManagerService),所以这里的bindService方法实际就是调用AMS里的bindService,源码分析到这里,就相当于前面说的,我们通过ServiceManager,帮助我们找到了闹钟服务,而我们实际例子里是LeoAidlService,所以我们要找的服务找到了,接下来就是要分析怎么和这个服务通信了。

所以接下来我们要分四种状态去分析这个服务:
  • 1、app(进程)没启动
  • 2、app(进程)启动了,服务没创建
  • 3、app(进程)启动了,服务创建了,服务没绑定
  • 3、app(进程)启动了,服务创建了,服务已经被绑定了

ActivityManagerService类比LeoAidlService

因为真正的服务是在AMS里,所以我们看到AMS里的bindService

public int bindService(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, IServiceConnection connection, int flags, String callingPackage,
            int userId) throws TransactionTooLargeException {
        enforceNotIsolatedCaller("bindService");

        // Refuse possible leaked file descriptors
        if (service != null && service.hasFileDescriptors() == true) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }

        if (callingPackage == null) {
            throw new IllegalArgumentException("callingPackage cannot be null");
        }

        synchronized(this) {
            return mServices.bindServiceLocked(caller, token, service,
                    resolvedType, connection, flags, callingPackage, userId);
        }
    }

我们再进入ActiveServices#bindServiceLocked

  int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, IServiceConnection connection, int flags,
            String callingPackage, int userId) throws TransactionTooLargeException {
          .......
         bringUpServiceLocked(s, service.getFlags(), callerFg, false) 
          .....
         requestServiceBindingLocked(s, b.intent, callerFg, false);
          ......

}

因为bindServiceLocked方法里面的内容太多了,我们直接抽出其中最核心的两个方法bringUpServiceLocked和requestServiceBindingLocked来讲,
我们先看bringUpServiceLocked方法

  private final String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting) throws TransactionTooLargeException {
        ......
      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) {
                    Slog.w(TAG, "Exception when starting service " + r.shortName, e);
                }

                // If a dead object exception was thrown -- fall through to
                // restart the application.
         }
        ......
  if (app == null) {
            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    "service", r.name, false, isolated, false)) == null) {
                String msg = "Unable to launch app "
                        + r.appInfo.packageName + "/"
                        + r.appInfo.uid + " for service "
                        + r.intent.getIntent() + ": process is bad";
                Slog.w(TAG, msg);
                bringDownServiceLocked(r);
                return msg;
            }
            if (isolated) {
                r.isolatedProc = app;
            }
        }
......
}

我们看到这里有两种情况:1、一种是app==null:app没启动。2、一种是 if (app != null && app.thread != null) {这个判断的意思就是app已经启动了。

ActiveServices#bringUpServiceLocked(app启动与否)

1、app已经启动的情况,

然后会调用ActiveServices#realStartServiceLocked方法。

 private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
      ......
      app.thread.scheduleCreateService(r, r.serviceInfo,
                         mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);

      .....
}

我们只看主要方法 app.thread.scheduleCreateService,那么app.thread是什么呢?我们看入参 ProcessRecord app,我们知道我们启动一个app就会创建一个进程,那么这个创建的进程就保存在ProcessRecord里。而app.thread就是IApplicationThread thread;


image.png

其实就是ApplicationThread,所以我们直接进入ActivityThread#ApplicationThread中去找scheduleCreateService方法,

    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);
        }

我们看到 sendMessage(H.CREATE_SERVICE, s);所以我们直接根据CREATE_SERVICE去找handle处理消息的地方handleMessage

           case CREATE_SERVICE:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");
                    handleCreateService((CreateServiceData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;

再进入handleCreateService方法

 private void handleCreateService(CreateServiceData data) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        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 context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);

            Application app = packageInfo.makeApplication(false, mInstrumentation);
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManagerNative.getDefault());
            service.onCreate();
            mServices.put(data.token, service);
            try {
                ActivityManagerNative.getDefault().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
            } catch (RemoteException e) {
                // nothing to do.
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to create service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }
    }

这里就是创建真正服务的地方,也就是创建我们LeoAidlService的地方,
看到这两行代码java.lang.ClassLoader cl = packageInfo.getClassLoader(); service = (Service) cl.loadClass(data.info.name).newInstance();所以其实真正就是通过获取应用的一些信息,然后通过反射和类加载器去创建的,然后调用service.onCreate()启动这个service,最后把这个服务放进mServices数组里。这个service其实就是我们之前说的LeoAidlService,因为是通过反射创建的服务,所以就算把服务端app杀死了,客户端还是能调用到服务端的代码。
分析完app已经启动的情况,现在继续分析

2、app还没启动的情况

我们进入ActiveServices#startProcessLocked方法

    private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {



        if (entryPoint == null) entryPoint = "android.app.ActivityThread";
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                    app.processName);
            checkTime(startTime, "startProcess: asking zygote to start proc");
            Process.ProcessStartResult startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                    app.info.dataDir, entryPointArgs);
      }

我们直接看主要代码,它把"android.app.ActivityThread"传进去通过Process.start直接创建了进程。也就是app没启动,他会给你创建这app的进程。到这里app也启动了,LeoAidlService服务也创建了,接下来就是分析LeoAidlService怎么和客户端绑定了。

所以我们再看到requestServiceBindingLocked方法

ActiveServices#requestServiceBindingLocked(情况2,3)

    private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
            boolean execInFg, boolean rebind) throws TransactionTooLargeException {
        if (r.app == null || r.app.thread == null) {
            // If service is not currently running, can't yet bind.
            return false;
        }
        if ((!i.requested || rebind) && i.apps.size() > 0) {
            try {
                bumpServiceExecutingLocked(r, execInFg, "bind");
                r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_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 (TransactionTooLargeException e) {
                // Keep the executeNesting count accurate.
                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r, e);
                final boolean inDestroying = mDestroyingServices.contains(r);
                serviceDoneExecutingLocked(r, inDestroying, inDestroying);
                throw e;
            } catch (RemoteException e) {
                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r);
                // Keep the executeNesting count accurate.
                final boolean inDestroying = mDestroyingServices.contains(r);
                serviceDoneExecutingLocked(r, inDestroying, inDestroying);
                return false;
            }
        }
        return true;
    }

我们看到r.app.thread.scheduleBindService,前面分析app启动与否是调用
scheduleCreateService,我们这里绑定服务是调用scheduleBindService,所以我们也是进入ActivityThread找scheduleBindService方法,中间流程和创建服务时是一样的,我们直接到处理消息的地方,

 case BIND_SERVICE:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
                    handleBindService((BindServiceData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;

再进入handleBindService方法

    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) {
                        IBinder binder = s.onBind(data.intent);
                        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) {
                }
            } catch (Exception e) {
                if (!mInstrumentation.onException(s, e)) {
                    throw new RuntimeException(
                            "Unable to bind to service " + s
                            + " with " + data.intent + ": " + e.toString(), e);
                }
            }
        }
    }

这里就是真正绑定服务的地方,一开始我们就从之前创建服务存的mServices数组里去拿我们的服务,我们再看 IBinder binder = s.onBind(data.intent);
这一句代码返回一个IBinder对象,其实就是LeoAidlService的onBind方法。


image.png

我们再看到这一句ActivityManagerNative.getDefault().publishService(data.token, data.intent, binder);这里就把刚刚创建的IBinder对象传进来了,前面我们分析过了ActivityManagerNative.getDefault()就是类比于Proxy,所以我们去ActivityManagerProxy里找publishService方法,这个流程和我们之前找bindService方法是一个道理,也就是调用AMS里的publishService

   public void publishService(IBinder token, Intent intent, IBinder service) {
        // Refuse possible leaked file descriptors
        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");
            }
            mServices.publishServiceLocked((ServiceRecord)token, intent, service);
        }
    }

然后进入publishServiceLocked就到了ActiveServices#publishServiceLocked方法


    void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
        final long origId = Binder.clearCallingIdentity();
        try {
            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "PUBLISHING " + r
                    + " " + intent + ": " + service);
            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)) {
                                if (DEBUG_SERVICE) Slog.v(
                                        TAG_SERVICE, "Not publishing to: " + c);
                                if (DEBUG_SERVICE) Slog.v(
                                        TAG_SERVICE, "Bound intent: " + c.binding.intent.intent);
                                if (DEBUG_SERVICE) Slog.v(
                                        TAG_SERVICE, "Published intent: " + intent);
                                continue;
                            }
                            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Publishing to: " + c);
                            try {
                                c.conn.connected(r.name, service);
                            } catch (Exception e) {
                                Slog.w(TAG, "Failure sending service " + r.name +
                                      " to connection " + c.conn.asBinder() +
                                      " (in " + c.binding.client.processName + ")", e);
                            }
                        }
                    }
                }

                serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }

里面这样一段代码 c.conn.connected(r.name, service);这句话最终会调用到客户端的onServiceConnected(或者onServiceDisconnected)这个代码,并把IBinder对象返回到客户端。


image.png

传递的参数也是IBinder和name,到这里在客户端的onServiceConnected里就拿到了服务端传递过来的IBinder对象了,完成了LeoAidlService和客户端的绑定。

那 c.conn.connected到底是怎么调用到客户端的onServiceConnected方法的呢?我们继续分析,我们发现conn是IServiceConnection 类型的,c是ConnectionRecord类型,在这里,我们通过conn变量我们找不到connected方法到底在哪里实现的,那怎么办呢?我们看到客户端的bindService流程
image.png
,客户端的bindService不就传递了connection对象么?所以我们通过客户端去查看c.conn.connected(r.name, service);的具体实现,所以我们进入ContextImpl的bindServiceCommon(流程和前面我们分析绑定流程一样,具体不再讲了)
image.png

我们看到了前面 IServiceConnection sd;和ServiceConnection conn,所以这个sd是不是就是前面我们要找的IServiceConnection conn,所以我们是不是就要看sd到底是怎么获得的?,就能找到c.conn.connected
的具体实现了,我们看到 sd = getServiceDispatcher(conn, getOuterContext(), mMainThread.getHandler(), flags);这句是不是就是把conn和sd关联起来了,我们进入 sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), mMainThread.getHandler(), flags);看看到底怎么关联的

 public final IServiceConnection getServiceDispatcher(ServiceConnection c,
            Context context, Handler handler, int flags) {
        synchronized (mServices) {
            LoadedApk.ServiceDispatcher sd = null;
            ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
            if (map != null) {
                sd = map.get(c);
            }
            if (sd == null) {
                sd = new ServiceDispatcher(c, context, handler, flags);
                if (map == null) {
                    map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
                    mServices.put(context, map);
                }
                map.put(c, sd);
            } else {
                sd.validate(context, handler);
            }
            return sd.getIServiceConnection();
        }
    }

看到最后一句 return sd.getIServiceConnection();,我们再进入getIServiceConnection方法看看,

        IServiceConnection getIServiceConnection() {
            return mIServiceConnection;
        }

我们发现getIServiceConnection方法返回mIServiceConnection对象,我们看看mIServiceConnection对象到底是什么?


    static final class ServiceDispatcher {
        private final ServiceDispatcher.InnerConnection mIServiceConnection;

再进入ServiceDispatcher.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.connected(name, service);
                }
            }
        }

我们是不是发现了 sd.connected(name, service);是不是就是前面的c.conn.connected了。因为绑定服务的流程是在客户端的,c.conn.connected就通过这一句代码调到了客户端的 sd.connected(name, service);,我们再进入connected看看,最终在doConnected方法里

public void doConnected(ComponentName name, IBinder service) {

 // If there was an old service, it is not disconnected.
            if (old != null) {
                mConnection.onServiceDisconnected(name);
            }
            // If there is a new service, it is now connected.
            if (service != null) {
                mConnection.onServiceConnected(name, service);
            }
}
image.png

所以在服务端调用c.conn.connected这句代码的时候,会调用到客户端的onServiceConnected(成功)和onServiceDisconnected(失败),我们现在整个流程是不是都通了。

到这里我们把android系统的AIDL整个机制就分析完整了。最后,给出我们从我们自己的例子,分析到系统的aidl的类比图,你们你们看到这些系统类,就要想到AIDL的流程,这样看起源码来就很容易懂了。

image.png

文末分析一篇比较好理解的文章,看完可以巩固理解

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,928评论 6 509
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,748评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,282评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,065评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,101评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,855评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,521评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,414评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,931评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,053评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,191评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,873评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,529评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,074评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,188评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,491评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,173评论 2 357

推荐阅读更多精彩内容