美文网首页
bindService源码流程

bindService源码流程

作者: loveCandyTQJ | 来源:发表于2018-05-26 15:11 被阅读0次

    前沿

    上一篇文章给大家分析了一下Binder的交互流程,这篇文章分析一下上篇遗留的bindService执行流程,当我们调用了bindService系统为我们做了些什么。

    首先,当我们想要去绑定一个远程service时,我们需要写以下代码:

        Intent intent = new Intent(this,MyService.class);
        bindService(intent,connection,BIND_AUTO_CREATE);
    

    这时候我们就要进入bindService

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

    这时候我们发现这个调用了mBase.bindService.进入这个方法才发现是个抽象方法。我去,那怎么办,我们需要找到他真正的子类实现,这里就不给大家卖关子了,我们真正的子类实现是ContextImpl这个类,那我们去看一下这个类中的bindService吧。

        @Override                                                                         
        public boolean bindService(Intent service, ServiceConnection conn,                
                int flags) {                                                              
            warnIfCallingFromSystemProcess();                                             
            return bindServiceCommon(service, conn, flags, Process.myUserHandle());       
        }                                                                                 
    
     private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,   
             UserHandle user) {                                                             
         IServiceConnection sd;                                                                                                                                          
         if (mPackageInfo != null) { 
             //这里先记录以下,一会还会回来                                                    
             sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),                
                     mMainThread.getHandler(), flags);                                      
         }                                                                               
         validateServiceIntent(service);                                                    
         try {                                                                              
             IBinder token = getActivityToken();                                            
             //省略一些代码。                                                           
             service.prepareToLeaveProcess();                                               
             int res = ActivityManagerNative.getDefault().bindService(                      
                 mMainThread.getApplicationThread(), getActivityToken(),                    
                 service, service.resolveTypeIfNeeded(getContentResolver()),                
                 sd, flags, user.getIdentifier());                                          
             if (res < 0) {                                                                 
                 throw new SecurityException(                                               
                         "Not allowed to bind to service " + service);                      
             }                                                                              
             return res != 0;                                                               
         } catch (RemoteException e) {                                                      
             return false;                                                                  
         }                                                                                  
     }                                                                                      
    

    这时候就会调用ActivityManagerNative.getDefault().bindService这个ActivityManagerNative.getDefault()代码如下:

        private static final Singleton<IActivityManager> gDefault = 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;
            }
        };
    

    通过ServiceManager 去获取了一个binder,并把这个binder返回了,是一个IActivityManager如果大家看过很多底层代码就会很熟悉这样的接口类,我们通过这个接口可以猜出其子类是ActivityManagerService。我们去这个类中的bindService一探究竟。

    public int bindService(IApplicationThread caller, IBinder token,
            Intent service, String resolvedType,
            IServiceConnection connection, int flags, int userId) {
        synchronized(this) {
            return mServices.bindServiceLocked(caller, token, service, resolvedType,
                    connection, flags, userId);
        }
    }
    

    调用了bindServiceLocked方法

    // 省略掉一些有关Activity的启动流程,我们再后面再说
       private final void realStartServiceLocked(ServiceRecord r,
                ProcessRecord app, boolean execInFg) throws RemoteException {
            if (app.thread == null) {
                throw new RemoteException();
            }
            requestServiceBindingsLocked(r, execInFg);
       }
    

    最后会调用requestServiceBindingsLocked方法

    private final boolean requestServiceBindingLocked(ServiceRecord r,
            IntentBindRecord i, boolean execInFg, boolean rebind) {
        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 (RemoteException e) {
                if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
                return false;
            }
        }
        return true;
    }
    

    这里我们看r.app.thread.scheduleBindService这个方法,但是你又会问,点不进去啊,这个scheduleBindService在哪里呢。我们进到ProcessRecord里面看一下

    final class ProcessRecord {
        private final BatteryStatsImpl mBatteryStats; // where to collect runtime statistics
        final ApplicationInfo info; // all about the first app in the process
        final boolean isolated;     // true if this is a special isolated process
        final int uid;              // uid of process; may be different from 'info' if isolated
        final int userId;           // user of process.
        final String processName;   // name of the process
        // List of packages running in the process
        final ArrayMap<String, ProcessStats.ProcessState> pkgList
                = new ArrayMap<String, ProcessStats.ProcessState>();
        IApplicationThread thread;
    

    发现又是一个IApplicationThread那我们的实现类是是就可以猜出是ApplicationThread这个类呢,其实这样想我们是对的,但是在这里你是找不到这个类的,我在开始找的时候也很头疼,找了半天发现不是我所想的那样。这里的ApplicationThread是一个内部类,它在ActivityThread中。让我们继续走刚刚的方吧。

    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;
        Binder.getCallingPid());
        sendMessage(H.BIND_SERVICE, s);
    }
    

    这里通过H 发送了一个BIND_SERVICE消息

    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对象,每次启动Service,系统都会记录到mServices中
        Service s = mServices.get(data.token);
        if (s != null) {
            try {
                data.intent.setExtrasClassLoader(s.getClassLoader());
                try {
                    //判断service是否未绑定过了
                    if (!data.rebind) {
                        //没有绑定需要走onBind
                        IBinder binder = s.onBind(data.intent);
                        ActivityManagerNative.getDefault().publishService(
                                data.token, data.intent, binder);
                    } else {
                        //绑定过需要走onRebind
                        s.onRebind(data.intent);
                        ActivityManagerNative.getDefault().serviceDoneExecuting(
                                data.token, 0, 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);
                }
            }
        }
    }
    

    这里会判断是否已经绑定过了,如果未绑定就回调onBind方法,绑定过了就会回调onRebingd方法。最后会调用publishService方法,我们在前面见过这个类,而且知道他的子类是ActivityManagerService,那我们去里面看看吧。

    public void publishService(IBinder token, Intent intent, IBinder service) {
        synchronized(this) {
            mServices.publishServiceLocked((ServiceRecord)token, intent, service);
        }
    }
    

    调用了publishServiceLocked这里我们只贴关键代码

    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, "Not publishing to: " + c);
                if (DEBUG_SERVICE) Slog.v(
                        TAG, "Bound intent: " + c.binding.intent.intent);
                if (DEBUG_SERVICE) Slog.v(
                        TAG, "Published intent: " + intent);
                continue;
            }
            if (DEBUG_SERVICE) Slog.v(TAG, "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);
            }
        }
    }
    

    这时候就会去ConnectionRecord list中去查找,找到就开始调用c.conn.connected(r.name, service),那这个conn又是什么呢,我们点进去看一下。

    final class ConnectionRecord {
        final IServiceConnection conn; 
    

    是不是感觉很熟悉,那我们按照以前的套路去查一下ServiceConnection这个类吧,但是你会失望的发现他还是个接口,那咋办,还记得我在上面有个地方说一会还会回来看这里的地方么。我们去看看。

     if (mPackageInfo != null) {                                            
         sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),    
                 mMainThread.getHandler(), flags);                          
     }                                                             
    

    发现进入到了LoadedApk中的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) {
                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();
        }
    }
    

    这里把LoadedApk.ServiceDispatcher放进了一个map中,这里就是我们上面要找的那个conn,让我们看一下这个类的实现吧。

    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);
            }
        }
    }
    
    public void connected(ComponentName name, IBinder service) {
            doConnected(name, service);
    }
    
    public void doConnected(ComponentName name, IBinder service) {
        if (service != null) {
            mConnection.onServiceConnected(name, service);
        }
    }
    

    经过一连串的方法调用,终于看到了我们认识的方法mConnection.onServiceConnected(name, service);
    最后会吧IBinder回调到我们的客户端。到这里bindService的流程就完了。

    UML图如下:
    bindService.jpg

    喜欢的请大家点赞哦!不对的地方请留言指出,谢谢。

    相关文章

      网友评论

          本文标题:bindService源码流程

          本文链接:https://www.haomeiwen.com/subject/gvmujftx.html