必威体育Betway必威体育官网
当前位置:首页 > IT技术

Android Service启动(二) bindService()启动过程以及原理解析

时间:2019-10-26 16:43:24来源:IT技术作者:seo实验室小编阅读:56次「手机版」
 

android service

本篇文章主要讲解bindservice()绑定Service的过程。(Android的版本依旧是26)

通过bindService()绑定一个Service时,最终都是调用的contextWrAPPer的bindService()方法,我们来看下这个方法

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

上述方法中调用了mBase对象的bindService()方法,mBase的类型是Context,Context的实现类是ContextImpl,我们来看下ContextImpl的bindService()方法

@Override
public boolean bindService(Intent service, ServiceConnection conn,int flags) {
    warnIfcallingFromSystemProcess();
    return bindServiceCommon(service, conn, flags, mMainThread.gethandler(),
                Process.myUserHandle());
}
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler handler, UserHandle user) {
        // Keep this in sync with 
    DevicePolicyManager.bindDeviceAdminServiceAsUser.
    IServiceConnection sd;
    if (conn == null) {
        throw new illegalargumentException("connection is null");
    }
    if (mPackageInfo != null) {
        /*
         * sd其实指向的是一个ServiceDispatch.InnerConnection的对象
         * 最终调用ServiceConnection的onServiceConnected()方法也是通过这个对象   
         */
        sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
    } else {
        throw new runtimeexception("Not supported in system context");
    }
    //检查合法性
    validateServiceIntent(service);
    try {

        ......
    
        //调用activitymanagerService的bindService()方法
        int res = ActivityManager.getService().bindService(
            mMainThread.getApplicationThread(), getActivityToken(), service,
            service.resolveTypeIfneeded(getcontentResolver()),
            sd, flags, getOpPackageName(), user.getIdentifier());

        ......

    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

由上述代码可知,相比较startService()的过程,在调用ActivityManagerService的bindService()方法之前,在bindServiceCommon()方法中多一个获取sd对象,即ServiceDispatch.InnerConnection类的对象的过程,mPackageInfo是LoadedApk类的一个引用,我们来看下mPackageInfo.getServiceDispatcher()中到底做了什么

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) {
            if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c);
            sd = map.get(c);
        }
        if (sd == null) {
           /*创建ServiceDispatcher对象
            *而在本方法中最终return的sd.getIServiceConnection()的值也是在ServiceDispatcher 
            *的构造方法中初始化的,稍后的文章中会讲到这一点。
            */
            sd = new ServiceDispatcher(c, context, handler, flags);
            if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c);
            if (map == null) {
                map = new ArrayMap<>();
                mServices.put(context, map);
            }
            map.put(c, sd);
        } else {
            sd.validate(context, handler);
        }
        //其实最终return的是ServiceDispatcher的内部类InnerConnection对象
        return sd.getIServiceConnection();
    }
}

上述代码中提到,getServiceDispatcher()方法最终返回的sd.getIServiceConnection()是ServiceDispatcher中的内部类InnerConnection对象,我们先来看一下上述方法最终return的sd.getIServiceConnection()到底是什么

IServiceConnection getIServiceConnection() {
    return mIServiceConnection;
}

可以看到该方法最终return的是一个IServiceConnection对象,看样子像是一个跨进程通信要用的东西,那么这个对象是在哪里创建的呢

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

由上述代码可知,mIServiceConnection是在ServiceDispatcher的构造方法中创建的,最终mIServiceConnection引用指向的是以ServiceDispatcher为参数构造的InnerConnection这个内部类的对象。我们来一下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, boolean dead)
            throws RemoteException {
        LoadedApk.ServiceDispatcher sd = mDispatcher.get();
        if (sd != null) {
            sd.connected(name, service, dead);
        }
    }
}

InnerConnection继承了IServiceConnection.Stub,看样子应该可以进行跨进程间的通信,内部持有了外部类ServiceDispatcher类的弱引用,代码量比较少,除了构造方法之外,只有一个connected()方法,在这个connected()方法中,获取了外部传递过来的ServiceDispatcher对象,并调用了ServiceDispatcher的connected()方法,我们来看下这个方法

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

可以看到connected()方法中会执行RunConnection的run()方法或者doConnected()方法,下面我们来看下RunConnection类

private final class RunConnection implements Runnable {
    RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
        mName = name;
        mService = service;
        mCommand = command;
        mDead = dead;
    }

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

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

我们可以看到,在RunConnection类的run()方法中,其实也执行了doConnected()方法,我们来看下这个方法

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

        synchronized (this) {

            ......

            /*
             * 这个判断逻辑要稍微提一下
             * 对于同一个Service,通过bindService()方法bind过一次之后,再次调用 
               bindService(),不会再调用ServiceConnection的onServiceConnected()方法
             * 原因应该就在这里(分析没错的话,应该就是这里)
             * 由下面的代码可知,当已经这存在这么一个Service或者说已经bind过的时候,代码到这 
               里就直接return了
             */
            if (old != null && old.binder == service) {
                // Huh, already have this one.  Oh well!
                return;
            }

            ......                

        }

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

上述doConnected()方法中,省略了部分不太重要的代码,剩余的部分应该一目了然,值得一提的是,当我们多次调用bindService()绑定同一个Service的时候,其实只会绑定一次,原因就是在上述的代码中会有判断,如果已经绑定过对应的Service,就不再执行下面的代码,如果是首次调用bindService(),或者绑定不同的Service的时候,会往下执行代码,调用ServiceConnection的onServiceDisconnected()方法或者onBindingDied()方法,取消和旧的Service的连接,最终调用onServiceConnected()方法来建立新的连接。

由于ServiceConnection不能够进行跨进程通信,所以要通过ServiceDispatcher.InnerConnection来保存ServiceConnection的信息,从而进行跨进程通信

好了,关于ServiceDispatch类,以及ServiceDispatch.InnerConnection类的功能大体已经介绍完毕了

下面我们继续回到bindServiceCommon()方法中来,当获取到sd,也就是ServiceDispatch.InnerConnection类的对象之后,就会去执行ActivityManagerService的bindService()方法,即ActivityManager.getService().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);
    }
}

上述方法会调用ActiveServices的bindServiceLocked()方法

int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, final IServiceConnection connection, int flags,
            String callingPackage, final int userId) throws TransactionTooLargeException {
        
    ......

    //根据用户传递进来Intent来检索相对应的服务
    ServiceLookupResult res =
        retrieveServiceLocked(service, resolvedType, callingPackage, 
        Binder.getCallingPid(),Binder.getCallingUid(), userId, true, callerFg, 
        isBindExternal);
        
    ......

    ServiceRecord s = res.record;

    ......

    try {
     
        //创建AppBindRecord对象记录着当前ServiceRecord,intent以及发起方的进程信息
        AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);

        ......

        if ((flags&Context.BIND_AUTO_CREATE) != 0) {
            s.lastActivity = SystemClock.uptimeMillis();
            /* 
             * 启动Service,这个过程和startService()一致
             * 只不过会区分bindService()和startService(),来执行不同的代码逻辑
             */
            if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
                    permissionsreviewrequired) != null) {
                return 0;
            }
        }

        ......

        if (s.app != null && b.intent.received) {
            /*
             * c.conn就是上文中我们提到的ServiceDispatcher.InnerConnection的对象
             * 如果Service正在运行,会直接调用他的connected()方法,
             * 具体connected()中代码是怎么执行的,上文中已经提到。
             */
            try {
                c.conn.connected(s.name, b.intent.binder, false);
            } catch (Exception 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) {
            requestServiceBindingLocked(s, b.intent, callerFg, false);
        }

        getServiceMapLocked(s.userId).ensureNotStartingBackgroundLocked(s);

    } finally {
        Binder.restoreCallingIdentity(origId);
    }

    return 1;
}

上问中retrieveServiceLocked()方法我就不多做介绍了,有兴趣的朋友可以自己去了解一下,下面我们来简单的看一下s.retrieveAppBindingLocked()方法

public AppBindRecord retrieveAppBindingLocked(Intent intent,
        ProcessRecord app) {
    Intent.FilterComparison filter = new Intent.FilterComparison(intent);
    IntentBindRecord i = bindings.get(filter);
    if (i == null) {
        i = new IntentBindRecord(this, filter);
        bindings.put(filter, i);
    }
    AppBindRecord a = i.apps.get(app);
    if (a != null) {
        return a;
    }
    a = new AppBindRecord(this, i, app);
    i.apps.put(app, a);
    return a;
}

这个方法很简单,bindings我理解应该是存储了所有已经bind了的Service,这个方法的作用应该就是往bindlings里面put了值,请记住这个bindlings,后面有用。

接下来,我们来看下bindServiceLocked()中的bringUpServiceLocked()方法,这个方法的作用是启动一个Service,同样的,startService()的过程中也会调用这个方法,我在上一篇介绍startService()启动过程的博客中也对这个方法做了详细的介绍,因为这个方法比较重要,本文再对这个方法做一些讲解,与上篇博客不同的是,针对该方法,上篇博客是针对startService()来介绍的这个方法,而本篇博客是针对bindService()介绍的该方法

private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,boolean whileRestarting, boolean permissionsReviewRequired)
        throws TransactionTooLargeException {
        
    /*
     * 个人理解:
     * 由本方法的参数可知,r是ServiceRecord的对象,ServiceRecord代表着一个Service记录
     * 联系整个Service的启动过程可知:
     * 首次调用bindService()启动一个Service时候,r.app应该为null,下面的if判断不成立
     * 如果不是首次调用bindService()方法,则下面的if判断成立,调用 
       sendServiceArgsLocked()方法,然后return,
     * 针对bindService()这个过程,在sendServiceArgsLocked()方法的开始处就已经return了,
       并没有往下执行,可以说sendServiceArgsLocked()方法和bindService()这个过程无关
     * 此处不对sendServiceArgsLocked()方法做过多解释,因为该方法主要是针对startService()        
       这个过程的,稍后下文中会讲到
     */       
    if (r.app != null && r.app.thread != null) {
        sendServiceArgsLocked(r, execInFg, false);
        return null;
    }

    ......

    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);
                //执行realStarServiceLocked(),开始正式执行Servcie的启动过过程
                realStartServiceLocked(r, app, execInFg);
                return null;
            } catch (TransactionTooLargeException e) {
                ......
            }
        }
    } else {
        ......
    }

   ......

   return null;
}

上述方法的注释中已经描述的很清楚了,下面我简单的解释一下为什么bindService()的过程中sendServiceArgsLocked()方法在刚开始处就return了,我们来简单看下sendServiceArgsLocked()方法的代码

private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
        boolean oomAdjusted) throws TransactionTooLargeException {
    final int N = r.pendingStarts.size();
    if (N == 0) {
        return;
    }

    ......

}

如果我理解的没错的话,原因就是,在sendServiceArgsLocked()方法的开始处,r.pendingStarts.size() = 0,因为pendingStarts是在startService()的过程中add值的,有兴趣的朋友可以自己查看一下源码,我就不针对这个小问题过多的解释了,之前也说过,代码也是人写的,过多的纠结细节问题,只能是只见树木,不见森林。

好了,我们回到bringUpServiceLocked()中来,接下来就会执行·realStartServiceLocked(),这个方法上篇博客也已经介绍过了,下面我们再回顾一下

private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        
        ......

        /* r是ServiceRecord的对象,对应了一个Service 
         * r.app是ProcessRecord的对象,对应了app所在的进程
         * 首次调用bindService()时,会执行本方法
         * 而r.app = app的作用相当于把Service与进程关联起来
         */
        r.app = app;
        
        ......

        try {
            
            ......

            //app.thread其实就是ActivityThread中ApplicationThread类的对象,
            //调用ApplicationThread的scheduleCreateService()方法
            //顾名思义,该方法就最终调用的应该就是Service的onCreate()方法 
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
            ......
        } catch (DeadObjectException e) {
            ......
        } finally {
            ......    
        }

        /*
         * 该方法是通过bindService()绑定Service的时候才去真正的调用,从而调用onBind()方法
         * 当通过startService()方法来开启一个Service的时候,该方法内部的逻辑不成立
         * 稍后会介绍这个方法的内容
         */
        requestServiceBindingsLocked(r, execInFg);

        ......

        /* 该方法通过startService()开启一个Service的时候会去真正的调用,从而调用 
           onStartCommon()方法
         * 当通过bindService()来绑定一个Service的时候,该方法的内部逻辑不成立
         * 上一篇博客中已经对该方法做了详细的介绍,因为bindService()基本不涉及到该方法,本文 
           对该方法不再做介绍
         */
            
        sendServiceArgsLocked(r, execInFg, true);
        
        ......

}

下面我们先看下上述方法中提到的app.thread.scheduleCreateService()方法,其实就是ActivityThread中ApplicationThread的scheduleCreateService()方法,看下Service的onCreate()是怎么执行的,其实startService()的这个过程和bindService()的这个过程基本是一样的,为了文章的完整性,我从上篇博客把这一小部分的代码copy过来了,算是回顾一下吧(真心有强迫症~_~)

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

如果看过我前几篇Activity启动相关博客的朋友,对上述方法这种类型的代码结构应该不陌生,基本上和Activity启动过程中调用的ApplicationThread方法都是一致的,调用sendMessage()方法,通过Handler发送一个消息,然后在Handler的handleMessage()方法中去处理这个消息,这一小块的相关代码我就不详细说了,也比较简单,不过还是把代码粘贴出来。

private void sendMessage(int what, Object obj) {
    sendMessage(what, obj, 0, 0, false);
}
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这个Handler的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;
               
           ......     
           
        }
       
    ......

}

由上述方法可知,在Handler的handleMessage()方法中,处于这个事件时,回去调用handleCreateService()方法,我们来看下这个方法

private void handleCreateService(CreateServiceData data) {

        ......

        //通过getPackageInfoNoCheck()方法获取一个LoadedApk的对象
        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
            //通过反射的方式,调用ClassLoader的loadClass()方法,创建一个Service对象
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = (Service) cl.loadClass(data.info.name).newinstance();
        } catch (Exception e) {
            ......
        }

        try {

            ......

            //创建一个ContextImpl对象
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);

            //获取Application对象
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            //调用Service的attach()方法
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
            //调用Service的onCreate()方法
            service.onCreate();
            mServices.put(data.token, service);
            ......
        } catch (Exception e) {
            ......
        }
}

上述方法的注释中已经解释的很清楚了,我就不多做解释了,不过需要提一点的是,在上述方法中有两个方法getPackageInfoNoCheck()以及packageInfo.makeApplication()这个两个方法,getPackageInfoNoCheck()方法获取的是一个LoadedApk对象,LoadedApk对象是apk文件在内存中的表示,apk文件的相关信息,比如apk文件中的资源,甚至是代码里面的Activity、Service等组件的信息都可以通过此对象获取,而且packageInfo.makeApplication()方法获取的是一个Application对象,若Application已经创建过,则直接return之前创建的Application对象,对这两个方法,这里我就简单的描述一下,就不贴出代码解释了,有想了解的朋友,可以看一下我之前的一篇博客  Android Activity启动(一) Application创建的过程以及原理分析,也涉及到相关的内容,讲解的也比较详细。到此为止,Service的onCreate()方法的执行流程已经介绍完毕了。

我们再次回到realStartServiceLocked()中来,总结一下该方法中app.thread.scheduleCreateService()方法,调用了ApplicationThread的scheduleCreateService()方法,通过Handler处理事件,调用了ActivityThread的handleCreateService()方法,通过反射的方式获取Service的对象,然后依次调用Service的attach()方法和onCreate()方法。

 下面我们来继续看下realStartServiceLocked()方法中的app.thread.scheduleCreateService()之后执行的requestServiceBindingLocked()方法

private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)
        throws TransactionTooLargeException {
    //在startService()的过程中bindings.size() = 0,不会执行for循环
    for (int i=r.bindings.size()-1; i>=0; i--) {
        IntentBindRecord ibr = r.bindings.valueAt(i);
        if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
            break;
        }
    }
}

在上述方法中会遍历bindings,从而调用requestServiceBindingLocked()方法,这个方法最终才会去调用Service的onBind()方法,而bindings我在上文中已经加了红色字体标注,只在bindService()中会add值,在startService()过程中并不会对其添加值,这也是为什么在startService()和bindService()执行的方法都是一样的,但是结果却不一样。

我们来看下requestServiceBindingLocked()方法

private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,boolean execInFg, boolean rebind) throws TransactionTooLargeException {
        
    ......

    if ((!i.requested || rebind) && i.apps.size() > 0) {
        try {
            bumpServiceExecutingLocked(r, execInFg, "bind");
            r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
            //调用ApplicationThread的scheduleBindService()
            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) {
            ......
        } catch (RemoteException e) {
            ......
        }
    }
    return true;
}

在上述方法中,调用了ApplicationThread的scheduleBindService(),我们来看下这个方法

public final void scheduleBindService(IBinder token, Intent intent,
        boolean rebind, int processState) {
    updateProcessState(processState, false);
    BindServiceData s = new BindServiceData();
    s.token = token;
    s.intent = intent;
    s.rebind = rebind;

    if (DEBUG_SERVICE)
        Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " 
              uid="+ Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
    sendMessage(H.BIND_SERVICE, s);
}
private void sendMessage(int what, Object obj) {
    sendMessage(what, obj, 0, 0, false);
}
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);
}
public void handleMessage(Message msg) {
    if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
    switch (msg.what) {
            
        ......    

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

很明显,ApplicationThread的scheduleBindService()方法中,也是发送了一个消息,最终在Handler的handleMessage()中处理了这个消息,调用了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) {
                    //调用Service的onBind()方法
                    IBinder binder = s.onBind(data.intent);
                    ActivityManager.getService().publishService(
                            data.token, data.intent, binder);
                } else {
                    //调用Service的onRebind()方法
                    s.onRebind(data.intent);
                    ActivityManager.getService().serviceDoneExecuting(
                            data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                }
                ensureJitEnabled();
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        } catch (Exception e) {
            ......
        }
    }
}

我们可以看到在handleBindService()方法中调用了Service的onBind()方法,然后通过ActivityManager.getService()获取到ActivityManagerService的对象,调用其publishService()方法,我们来看一下这个方法

public void publishService(IBinder token, Intent intent, IBinder service) {
        
    ......

    synchronized(this) {
        ......
        mServices.publishServiceLocked((ServiceRecord)token, intent, service);
    }
}
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++) {

                        ......

                        try {
                            /*
                             * 关键代码,下面的方法最终会回调ServiceConnection的
                               onServiceConnected()方法
                             */  
                            c.conn.connected(r.name, service, false);
                        } catch (Exception e) {
                          ......
                        }
                    }
                }
            }

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

在上述代码中,c.conn.connected()方法比较重要,其中c.conn就是上文中提到的ServiceDispatch.InnerConnection的对象,然后调用它的connected()方法,关于connected()方法上文中已经有了比较详细的介绍,这里就不多提了。

到此为止,我们关于bindService()的启动过程已经介绍完毕了,下面我来总结一下:

当我们调用bindService()方法的时候,

(1)会调用ContextImpl的bindService()方法,然后获取到一个ServiceDispatch.InnerConnection的对象,可以跨进程通信,

(2)调用ActivityManagerService的bindService()方法,然后调用bringUpServiceLocked()方法,这个方法在startService()和bindService()的过程中都会调用

(3)执行realStartServiceLocked()方法,这个方法中通过调用ActivityThread中ApplicationThread的scheduleCreateService()方法,真正执行了Service的创建过程,即onCreate()

(4)调用了requestServiceBindingsLocked()方法,在这个方法中,会去调用ActivityThread中ApplicationThread的scheduleBindService()方法来执行Service的bind过程,即onBind()

(5)然后调用ActivityManagerService的publishService(),然后调用publishServiceLocked()方法,在这个方法中会调用ServiceDispatch.InnerConnection的connected()方法,最终回调ServiceConnection的onServiceConnected()方法。

(额,写完了,篇幅有点长,有出错的地方欢迎批评指正,谢谢!!!)

文章最后发布于: 2019-03-13 21:14:13

相关阅读

Hbuilder android 在线更新功能 后端获取最新版本号和

     写这个博文的意义在于,做了一个使用纯h5网页的东西,然后想用hbuilder在外面包一层,这样就能android和ios都能同时使用,hb

Android逆向之某拜蓝牙开锁原理探究

准备工作

黑马Android开发视频教程125集

专题地址:http://www.apkbus.com/heima/ 黑马Android入门到精通 视频教程 01.什么是3G? 03_an

msm8909 模块android 驱动编写

sc20_gpio.c ``` #include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #inc

谈谈Android中的persistent属性

在我们开发系统级的App时,很有可能就会用persistent属性。当在AndroidManifest.xml中将persistent属性设置为true时,那么该App就会

分享到:

栏目导航

推荐阅读

热门阅读