Binder机制(1)-从framework分析AIDL生成文件

主目录见:Android高级进阶知识(这是总目录索引)
 为什么要突然讲这一章呢?因为后面要开始讲Framework的代码,有太多应用到AIDL机制了。所以想在这里给大家介绍清楚这个,但是我不能保证我讲的很清楚,不过希望大家自己能学懂,为后面的打下基础,下面可能有块硬骨头要啃,我们上图休息一下:

Binder机制(1)-从framework分析AIDL生成文件_第1张图片
Relax

一.目标

今天讲这个的原因前面已经讲了,我们今天的目标就是搞懂AIDL的生成文件,然后明白调用过程,所以目标如下:
1.清楚AIDL生成文件的代码结构;
2.从bindService的过程来了解调用过程。

二.AIDL生成文件分析

 为了分析AIDL生成文件,我们首先得来看看AIDL要怎么应用,就是怎么个写法,我们这里还是以[LRouter]项目中的跨进程部分来讲。首先我们来看看我们是怎么写的:
1.首先要编写aidl文件用于自动生成代码

package com.lenovohit.lrouter_api;
import com.lenovohit.lrouter_api.core.LRouterRequest;

interface IRemoteRouterAIDL {
    boolean stopRouter(String processName);
    boolean checkIfLocalRouterAsync(String processName,in LRouterRequest routerRequset);
    String navigation(String processName,in LRouterRequest routerRequest);
}

2.接着我们要编写一个服务,然后把Stub绑定到这个服务上

public final class RemoteRouterService extends Service {
    private static final String TAG = "RemoteRouterService";
    public static final String PROCESS_NAME = "process_name";

    @Override
    public void onCreate() {
        super.onCreate();
        if (!(getApplication() instanceof LRouterAppcation)) {
            throw new LRException("请检查你的AndroidManifest.xml和applicaiton是LRouterApplicaiton");
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_NOT_STICKY;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
.....
          return mStub;
    }

    IRemoteRouterAIDL.Stub mStub = new IRemoteRouterAIDL.Stub() {
//省略实现的方法
......
    };
}

3.编写ServiceConnection在onServiceConnected得到远程服务代理对象

 private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mRemoteRouterAIDL = IRemoteRouterAIDL.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mRemoteRouterAIDL = null;
        }
    };

4.最后绑定服务

        Intent bindRemoteRouterServiceIntent = new Intent(mLRouterAppcation,RemoteRouterService.class);
        bindRemoteRouterServiceIntent.putExtra(RemoteRouterService.PROCESS_NAME,processName);
        mLRouterAppcation.bindService(bindRemoteRouterServiceIntent,mServiceConnection, BIND_AUTO_CREATE);

到这里我们的使用就已经完成了,当然有些小细节没有说,不过没关系,这篇不是为了讲具体的使用方法的,大家应该要已经知道怎么使用了。

1.bindService

要想把这一整套流程都讲清楚就得从绑定服务开始,这里不像系统服务的启动和注册需要ServiceManager管理。这里我们应用的服务直接从bindService开始讲就可以。我们看到前面绑定服务的时候是Application里面的bindService()方法,但是查找的时候会发现这里面没有这个方法,而且在基类ContextWrapper中:

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

这里的mBase是个ContextImpl对象,于是调用ContextImpl的bindService方法:

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

我们看到这里调用了bindServiceCommon()方法:

    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
            handler, UserHandle user) {
        IServiceConnection sd;
        if (conn == null) {
            throw new IllegalArgumentException("connection is null");
        }
        if (mPackageInfo != null) {
            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
        } else {
            throw new RuntimeException("Not supported in system context");
        }
        validateServiceIntent(service);
        try {
       ....
            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();
        }
    }

前面的mMainThread是一个ActivityThread对象,通过他的getHandler()方法得到一个Handler对象,有了这个Handler对象,就可以把消息发送到ActivityThread所在线程的消息队列中了。然后我们看到最终会把这个handler放进ServiceDispatcher中去。这里的mPackageInfo就是我们的LoadedApk对象,所以我们看到LoadedApk的getServiceDispatcher()方法:

    public final IServiceConnection getServiceDispatcher(ServiceConnection c,
            Context context, Handler handler, int flags) {
        synchronized (mServices) {
            LoadedApk.ServiceDispatcher sd = null;
            ArrayMap 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();
                    mServices.put(context, map);
                }
                map.put(c, sd);
            } else {
                sd.validate(context, handler);
            }
            return sd.getIServiceConnection();
        }
    }

我们看到这里主要就是将ServiceConnection的对象,handler等传给ServiceDispatcher对象,我们看下ServiceDispatcher类是长啥样的:

 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;
        private final int mFlags;

        private RuntimeException mUnbindLocation;

        private boolean mForgotten;

        private static class ConnectionInfo {
            IBinder binder;
            IBinder.DeathRecipient deathMonitor;
        }

        private static class InnerConnection extends IServiceConnection.Stub {
            final WeakReference mDispatcher;

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

            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) {
            mIServiceConnection = new InnerConnection(this);
            mConnection = conn;
            mContext = context;
            mActivityThread = activityThread;
            mLocation = new ServiceConnectionLeaked(null);
            mLocation.fillInStackTrace();
            mFlags = flags;
        }
.......
}

 我们看到ServiceDispatcher内部还创建了一个InnerConnection对象,这是一个Binder对象,一会是要传递给ActivityManagerService的,ActivityManagerServic后续就是要通过这个Binder对象和ServiceConnection通信的。
 函数getServiceDispatcher最后就是返回了一个InnerConnection对象给ContextImpl.bindService函数。回到ContextImpl.bindService函数中,它接着就要调用ActivityManagerService的远程接口来进一步处理了。接着我们程序会调用 ActivityManagerNative.getDefault().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;
    }

这个函数通过Binder驱动程序就进入到ActivityManagerService的bindService函数去了。我们紧接着看ActivityManagerService.bindService方法:

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

我们看到这个方法最后直接调用了mServices.bindServiceLocked()方法,这个mServices就是ActiveServices类:

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;
        if (token != null) {
            activity = ActivityRecord.isInStackLocked(token);
.......
        }

        int clientLabel = 0;
        PendingIntent clientIntent = null;
        final boolean isCallerSystem = callerApp.info.uid == Process.SYSTEM_UID;
.....
        ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),
                    Binder.getCallingUid(), userId, true, callerFg, isBindExternal);
 .....

            AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
            ConnectionRecord c = new ConnectionRecord(b, activity,
                    connection, flags, clientLabel, clientIntent);

            IBinder binder = connection.asBinder();
            ArrayList clist = s.connections.get(binder);
            if (clist == null) {
                clist = new ArrayList();
                s.connections.put(binder, clist);
            }
            clist.add(c);
            b.connections.add(c);
            if (activity != null) {
                if (activity.connections == null) {
                    activity.connections = new HashSet();
                }
                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();
                mServiceConnections.put(binder, clist);
            }
            clist.add(c);

            if ((flags&Context.BIND_AUTO_CREATE) != 0) {
                s.lastActivity = SystemClock.uptimeMillis();
                if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
                        permissionsReviewRequired) != null) {
                    return 0;
                }
            }
.........
        return 1;
    }

 首先传进来的token就是Application在AcitivityManagerService中的令牌,通过token就可以将对应的ActivityRecord取回。
 接着通过retrieveServiceLocked函数,得到一个ServiceRecord,这个ServiceReocrd描述的是一个Service对象,这个service这里就是说的我们的RemoteRouterService对象。这是根据传进来的参数service的内容获得的。我们前面说的绑定服务那里可以看出:

        Intent bindRemoteRouterServiceIntent = new Intent(mLRouterAppcation,RemoteRouterService.class);
        bindRemoteRouterServiceIntent.putExtra(RemoteRouterService.PROCESS_NAME,processName);
        mLRouterAppcation.bindService(bindRemoteRouterServiceIntent,mServiceConnection, BIND_AUTO_CREATE);

 这里的参数service,就是上面的bindIntent了,它里面设置了RemoteRouterService类的信息(RemoteRouterService.class),因此,这里可以通过它来把RemoteRouterService的信息取出来,并且保存在ServiceRecord对象s中。
 接下来,就是把传进来的参数connection封装成一个ConnectionRecord对象。注意,这里的参数connection是一个Binder对象,它的类型是LoadedApk.ServiceDispatcher.InnerConnection,后续ActivityManagerService就是要通过它来告诉Application,RemoteRouterService已经启动起来了,因此,这里要把这个ConnectionRecord变量c保存下来,它保在在好几个地方,都是为了后面要用时方便地取回来的,这里就不仔细去研究了,只要知道ActivityManagerService要使用它时就可以方便地把它取出来就可以了,具体后面我们再分析。
 最后,传进来的参数flags的位Context.BIND_AUTO_CREATE为1。最后程序会调用ActiveServices类的bringUpServiceLocked继续处理:

  private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
.......
        final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
        final String procName = r.processName;
        ProcessRecord app;

        if (!isolated) {
            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) {
                    Slog.w(TAG, "Exception when starting service " + r.shortName, e);
                }
             }
        } else {
            app = r.isolatedProc;
        }
        if (app == null && !permissionsReviewRequired) {
            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    "service", r.name, false, isolated, false)) == null) {
.......           
                return msg;
            }
            if (isolated) {
                r.isolatedProc = app;
            }
        }
.......
        return null;
    }

我们如果在AndroidManifest.xml中有设置process的话,那么这里procName就会是我们设置的字符串。如果没有的话就会默认是包名。配合这uid会获取到ProcessRecord对象。如果这个ProcessRecord为null的话就是说还没有这个进程存在,所以后面会调用startProcessLocked()方法来创建一个新的进程然后在这个进程里面把这个服务启动。不然就调用realStartServiceLocked()方法在应用程序进程中启动应用Service,我们来看下这个方法:

  private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
......
        r.app = app;
        r.restartTime = r.lastActivity = SystemClock.uptimeMillis();

        final boolean newService = app.services.add(r);
        .......

        boolean created = false;
        try {
......
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
.....
        } catch (DeadObjectException e) {
     .....
        } finally {
     .....
        }
.....
        requestServiceBindingsLocked(r, execInFg);
.....
    }

这个方法里面有两个重要的方法scheduleCreateService和requestServiceBindingsLocked,这两个方法分别是启动服务和绑定服务(会调用Service的onBind方法)操作。

2.scheduleCreateService启动服务

我们看到上面程序调用了 app.thread的scheduleCreateService方法,这里的app.thread是一个bind远程对象,类型为ApplicationThreadProxy,每一个Android应用程序进程里面都有一个ActivtyThread对象和一个ApplicationThread对象,其中是ApplicationThread对象是ActivityThread对象的一个成员变量,是ActivityThreadActivityManagerService之间用来执行进程间通信的。所以我们看看这个ApplicationThreadProxy(这个类在ApplicationThreadNative里面)的scheduleCreateService干了什么:

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

这里通过了Bind机制就调用到了ActivityThread的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()方法:

 private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }

我们这个消息是发送到mH中了,这个mH又是什么呢?这里是H类,我们看他里面的handleMessage()方法:

 public void handleMessage(Message msg) {
     switch (msg.what) {
....
           case CREATE_SERVICE:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
                    handleCreateService((CreateServiceData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
......
    }
}

我们看到这个主要就是调用handleCreateService()方法,这个方法就是创建的Service了:

 private void handleCreateService(CreateServiceData data) {
        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) {
......
        try {
......
            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) {
                throw e.rethrowFromSystemServer();
            }
        } catch (Exception e) {
      .....
        }
    }

我们看到这个方法用类加载器把service加载进内存,然后调用了service的onCreate()方法,到这里我们的服务已经启动起来了。我们接下来看看服务的绑定。

3.requestServiceBindingsLocked 服务的绑定

 前面我们的服务已经启动且调用了Service的onCreate方法,那么接下来绑定的过程就会调用服务的onBind()方法,那么我们接下来来看绑定的方法即ActiveServices的requestServiceBindingsLocked:

  private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)
            throws TransactionTooLargeException {
        for (int i=r.bindings.size()-1; i>=0; i--) {
            IntentBindRecord ibr = r.bindings.valueAt(i);
            if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
                break;
            }
        }
    }

 private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
            boolean execInFg, boolean rebind) throws TransactionTooLargeException {
........
        if ((!i.requested || rebind) && i.apps.size() > 0) {
            try {
.........
                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                        r.app.repProcState);
........
            } catch (TransactionTooLargeException e) {
.........
            } catch (RemoteException e) {
.........
            }
        }
        return true;
    }

 这里传进来的ServiceRecord就是我们的RemoteRouterService服务,函数requestServiceBindingsLocked调用了requestServiceBindingLocked函数来处理绑定服务的操作,然后requestServiceBindingLocked方法会调用r.app.thread.scheduleBindService来绑定服务,跟上面的启动过程类似。我们就直接跳到ActivityThread的handleBindService来讲解:

    private void handleBindService(BindServiceData data) {
        Service s = mServices.get(data.token);
.......   
        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) {
                    throw ex.rethrowFromSystemServer();
                }
            } catch (Exception e) {
.......
            }
        }
    }

 执行ActivityThread.handleCreateService函数中,已经将这个RemoteRouterService实例保存在mServices中,因此,这里首先通过data.token值将它取回来,保存在本地变量s中,接着执行了两个操作,一个操作是调用s.onBind,即RemoteRouterService.onBind获得一个Binder对象,另一个操作就是把这个Binder对象传递给ActivityManagerService。
 到这里我们Service的onCreate和onBind都已经调用完毕,onBind返回的是我们的IRemoteRouterAIDL#Stub(),得到这个对象之后程序就调用publishService()方法,同样的,这里是调用ActivityManagerProxy的publishService通知mLRouterAppcation(Application对象),Service已经启动完毕:

  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);
        data.writeStrongBinder(service);
        mRemote.transact(PUBLISH_SERVICE_TRANSACTION, data, reply, 0);
        reply.readException();
        data.recycle();
        reply.recycle();
    }

这里通过Binder驱动程序就进入到ActivityManagerService的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);
        }
    }

我们看到这个方法里面主要是调用了mServices即ActiveServices对象,所以我们跟进ActiveServices的publishServiceLocked()方法:

    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 clist = r.connections.valueAt(conni);
                        for (int i=0; i

在之前ActiveServices的bindServiceLocked()方法的时候,我们已经将一个ConnectionRecord对象放进ServiceRecord.connections列表中了:

          ConnectionRecord c = new ConnectionRecord(b, activity,
                    connection, flags, clientLabel, clientIntent);

            IBinder binder = connection.asBinder();
            ArrayList clist = s.connections.get(binder);
            if (clist == null) {
                clist = new ArrayList();
                s.connections.put(binder, clist);
            }
            clist.add(c);
            b.connections.add(c);

publishServiceLocked()里面就是将这个ConnectionRecord取出来,然后调用他的connected()方法。那么这里的ConnectionRecord的conn又是什么呢?这个是我们之前ServiceDispatcher的InnerConnection对象,因此,这里执行c.conn.connected函数后就会进入到ServiceDispatcher.InnerConnection#connected函数中去了:

  private static class InnerConnection extends IServiceConnection.Stub {  
            ......  
  
            public void connected(ComponentName name, IBinder service) throws RemoteException {  
                LoadedApk.ServiceDispatcher sd = mDispatcher.get();  
                if (sd != null) {  
                    sd.connected(name, service);  
                }  
            }  
            ......  
        }  
}

这里转发给了ServiceDispatcher的connected方法:

       public void connected(ComponentName name, IBinder service) {
            if (mActivityThread != null) {
                mActivityThread.post(new RunConnection(name, service, 0));
            } else {
                doConnected(name, service);
            }
        }

这里的mActivityThread 是之前通过ActivityThread.getHandler函数得到的,因此,调用它的post函数后,就会把一个消息放到ActivityThread的消息队列中去了。如果不明白消息机制的建议看下Handler,MessageQueue,与Looper三者关系分析,我们最终post的消息会调用到RunConnection中的run方法:

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

这里的mCommand值为0,于是就执行ServiceDispatcher的doConnected方法来进一步操作了:

        public void doConnected(ComponentName name, IBinder service) {
            ServiceDispatcher.ConnectionInfo old;
            ServiceDispatcher.ConnectionInfo info;

            synchronized (this) {
        .......

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

到这里我们可以看到我们调用了mConnection的onServiceConnected()方法。这个mConnection就是我们bindService之前传进来的ServiceConnection对象mServiceConnection:

  private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mRemoteRouterAIDL = IRemoteRouterAIDL.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mRemoteRouterAIDL = null;
        }
    };

所以我们这里就到了onServiceConnected方法里面,我们这里调用了IRemoteRouterAIDL.Stub.asInterface(service),终于我们要开始AIDL生成的源码的分析了。

4.asInterface

我们看到绑定完成会回调ServiceConnection的onServiceConnected方法然后会调用这个方法,这个方法在AIDL文件生成的源码中:

public static com.lenovohit.lrouter_api.IRemoteRouterAIDL asInterface(android.os.IBinder obj)
{
     if ((obj==null)) {
         return null;
     }
    android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
    if (((iin!=null)&&(iin instanceof com.lenovohit.lrouter_api.IRemoteRouterAIDL))) {
         return ((com.lenovohit.lrouter_api.IRemoteRouterAIDL)iin);
    }
     return new com.lenovohit.lrouter_api.IRemoteRouterAIDL.Stub.Proxy(obj);
}

这个方法主要用于将服务端的Binder对象转换成客户端所需的AIDL接口类型的对象,这种转换过程是区分进程的 [如果客户端和服务端位于同一进程,那么此方法返回的就是服务端的Stub对象本身,否则返回的是系统封装后的Stub.proxy对象]。所以如果我们客户端要跨进程调用远程服务的时候,我们都是通过这个proxy代理来访问,这里举例我们要调用stopRouter方法,我们的代理是怎么访问的呢?

@Override public boolean stopRouter(java.lang.String processName) throws android.os.RemoteException
{
    android.os.Parcel _data = android.os.Parcel.obtain();
    android.os.Parcel _reply = android.os.Parcel.obtain();
    boolean _result;
   try {
        _data.writeInterfaceToken(DESCRIPTOR);
        _data.writeString(processName);
        mRemote.transact(Stub.TRANSACTION_stopRouter, _data, _reply, 0);
         _reply.readException();
        _result = (0!=_reply.readInt());
     }
      finally {
         _reply.recycle();
         _data.recycle();
         }
      return _result;
}

我们看到这里这个方法通过Binder机制调用远程RemoteRouterService的stopRouter()方法,因为mRemote就是绑定服务时候传回来的IRemoteRouterAIDL.Stub()的IBinder对象。然后服务端接受到消息的时候就会调用生成文件里面的onTransact方法里面对应的方法:

case TRANSACTION_stopRouter:
{
      data.enforceInterface(DESCRIPTOR);
       java.lang.String _arg0;
      _arg0 = data.readString();
      boolean _result = this.stopRouter(_arg0);
      reply.writeNoException();
      reply.writeInt(((_result)?(1):(0)));
       return true;
}

到这里就会调用到了RemoteRouterServiceIRemoteRouterAIDL.Stub的stopRouter()方法了。好了到这里我们整个流程也就讲完了,其实AIDL文件生成的代码并不难,难的是要明白整个调用过程。
总结:今天讲的内容还是比较多的,结合了bindService的过程来把整个AIDL生成的源代码的流程串了起来,如果感觉比较费劲的话就只要明白这里面的几个角色就行了,不需要整个流程明白,希望我们后面的framework之旅愉快。

你可能感兴趣的:(Binder机制(1)-从framework分析AIDL生成文件)