Service的启动.绑定过程

1.

1.一个service只要是通过start方法启动的.无论调用几次,无论是否调用bindService.都只能通过stop方法结束且,统只会创建一个Service实例.
2.一个startService方法就会对应一个onStartCommand,bindService不会回调onStartCommand方法
3.通过bindService启动的服务,只能通过unbindService接触绑定,调用该Service的Context不存在了(如Activity被Finish——因为bindService启动的Service的生命周期依附于启动它的Context),系统在这时会自动停止该Service。
4.当手机屏幕发生旋转时,如果Activity设置的是自动旋转的话,在旋转的过程中,Activity会重新创建,那么之前通过bindService 建立的连接便会断开(之前的Context不存在了),服务也会被自动停止
5.多次调用bindeService. onBind不会多次执行.
6.如果同时使用startService 与bindService 方法启动Service,需要终止该Service时,要调用stopService 和unbindService 方法(unbindService 依附于启动它的Context,startServicec 并不依附于启动它的Context。如果先调用unbindService ,这时服务并不会被终止,当调用stopService 后,服务才会被终止;如果先调用stopService ,服务也不会被终止,当调用unbindService 或者之前调用bindService 的Context不存在了(如Activity被finish掉了)服务才会自动停止)
6.onStartCommand的返回值,默认情况下,使用startService()方法激活的Service组件是粘性的,

START_STICKY:粘性的,被意外中止后自动重启,但丢失原来激活它的Intent
START_NO_STICKY:非粘性的,被意外中止后不会重新启动;
START_REDELIVER_INTENT:粘性的且重新发送Intent,即被意外中止后自动重启,
且该Service组件将得到原来用于激活它的Intent对象;

7.一个App里,同一个Activity多次bind一个服务,除了第一次,后面的bind不会有任何onBind、onServiceConnected打印。不同的Activity去bind一个服务,第一次bind有onBind、onServiceConnected打印,后面的bind只会有onServiceConnected打印

2.启动过程

启动过程的调用关系
  1. ContextWrapper的startService.
    所有的service,activity都继承自ContextWrapper,其实就是继承自Context.而ContextWrapper是一个包装类,主要的Context核心功能在ComtextImpl类里,而系统创建Activity和Service时,就为我们创建了ContextImpl类.存在ContextWrapper的mBase变量里.
public ComponentName startService(Intent service) { 调用了ContextImpl的方法,接着看
        return mBase.startService(service);
    }
  1. ContextImpl.startService
1.
 public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, mUser);
    }
2. 这个方法最重要的就是.跨进程调用Ams来启动service.
private ComponentName startServiceCommon(Intent service, UserHandle user) {
        try {
            validateServiceIntent(service); //1.验证intent的合法性
            service.prepareToLeaveProcess();
              //2.这是核心代码.ActivityManagerNative.getDefault()就是ActivityManagerProxy,是Ams的本地binder代理.
            ComponentName cn = ActivityManagerNative.getDefault().startService(
                mMainThread.getApplicationThread(), service,
                service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
            if (cn != null) {
                if (cn.getPackageName().equals("!")) {
                    throw new SecurityException( //3不具备调用目标Service的权限
                            "Not allowed to start service " + service
                            + " without permission " + cn.getClassName());
                } else if (cn.getPackageName().equals("!!")) {
                    throw new SecurityException(//4// 无法启动目标Service的处理
                            "Unable to start service " + service
                            + ": " + cn.getClassName());
                }
            }
            return cn;
        } catch (RemoteException e) {
            return null;
        }
    }
  1. Ams.startService 接下来就是Ams对service的操作.接着看.
  //参数IApplicationThread  caller 就是ActivityThread的内部类Application在服务端的代理
   public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, int userId) {
        //1.决绝孤立的进程执行 starService操作
        enforceNotIsolatedCaller("startService");
       // 2.拒绝包含可能造成内存泄露的文件描述符的Intent
        if (service != null && service.hasFileDescriptors() == true) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }
 
        synchronized(this) {
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
    //3.这里调用了ActiveServices 的方法.ActiveServices负责Service的组件调用和维护Service的状态信息
            ComponentName res = mServices.startServiceLocked(caller, service,
                    resolvedType, callingPid, callingUid, userId);
            Binder.restoreCallingIdentity(origId);
            return res;
        }
  1. ActiveServices.startServiceLocked 本方对调用者检测,同时.如果是后台进程.要延迟启动.
 ComponentName startServiceLocked(IApplicationThread caller,
            Intent service, String resolvedType,
            int callingPid, int callingUid, int userId) {
      
        final boolean callerFg;
        if (caller != null) {//1.这个mAm就是ActivityManagerService
            final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
            if (callerApp == null) {//2.在ActivityManagerService中查询不到调用者,直接抛出异常。
                throw new SecurityException(
                        "Unable to find app for caller " + caller
                        + " (pid=" + Binder.getCallingPid()
                        + ") when starting service " + service);
            }
             //3.判断调用方是前台进程还是后台进程 
            callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE;
        } else {
            callerFg = true;
        }
        //4.检索匹配Service组件信息
        ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType,
                    callingPid, callingUid, userId, true, callerFg);
        if (res == null) { //5.没有匹配到Service组件就返回
            return null;
        }
 
        ServiceRecord r = res.record;

         //5. 如果目标的Service正在被请求重启,但还未重启,取消这个请求
        if (unscheduleServiceRestartLocked(r, callingUid, false)) {
            if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
        }
        r.lastActivity = SystemClock.uptimeMillis();
        r.startRequested = true;
        r.delayedStop = false;
        r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                service, neededGrants));//这个ServiceRecord是Service的记录,会贯穿整个启动过程

        final ServiceMap smap = getServiceMap(r.userId);//smap是一个handler
        boolean addToStarting = false;
          //6.这里是对后台服务的处理,如果启动的是后台服务.就延迟启动他.
    防止多个进程启动service发生
        if (!callerFg && r.app == null && mAm.mStartedUsers.get(r.userId) != null) {
            ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false);
            if (proc == null || proc.curProcState > ActivityManager.PROCESS_STATE_RECEIVER) {
                if (r.delayed) {
              //7. 目标Service正在启动中,但还没有启动完成
                    return r.name;
                }
                if (smap.mStartingBackground.size() >= mMaxStartingBackground) {
                   //8.该进程有其它组件正在启动,加入到延迟启动列表,等待它完成后再启动。
                    smap.mDelayedStartList.add(r);
                    r.delayed = true;
                    return r.name;
                } 
                addToStarting = true;
            } else if (proc.curProcState >= ActivityManager.PROCESS_STATE_SERVICE) {
                addToStarting = true;
            
            } 
        } //8.继续调用.启动service
        return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
    }
  1. AcivityService.startServiceInnerLocked
    启动了对Service内存消耗和电量消耗的跟踪,
    最重要的是调用bringUpServiceLocked 真正启动service
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service,
            ServiceRecord r, boolean callerFg, boolean addToStarting) {
        ProcessStats.ServiceState stracker = r.getTracker();
        if (stracker != null) {//1.跟踪Service的内存消耗
            stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
        }
        r.callStart = false;
        synchronized (r.stats.getBatteryStats()) {
            r.stats.startRunningLocked();//2.跟踪Service的耗电量
        }
           //3.通知客户端进程启动Service
        String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false);
        if (error != null) {
            return new ComponentName("!!", error);//4.启动失败.
        }

        if (r.startRequested && addToStarting) {
            boolean first = smap.mStartingBackground.size() == 0;
            smap.mStartingBackground.add(r);
            r.startingBgTimeout = SystemClock.uptimeMillis() + BG_START_TIMEOUT;//5.设定客户端Service启动超时的时间
            if (DEBUG_DELAYED_SERVICE) {
                RuntimeException here = new RuntimeException("here");
                here.fillInStackTrace();
                Slog.v(TAG, "Starting background (first=" + first + "): " + r, here);
            } else if (DEBUG_DELAYED_STARTS) {
                Slog.v(TAG, "Starting background (first=" + first + "): " + r);
            }
            if (first) {
                smap.rescheduleDelayedStarts();
            }
        } else if (callerFg) {
            smap.ensureNotStartingBackground(r);
        }
        return r.name;
    }
  1. AcivityService.bringUpServiceLocked
    这个方法就是如果service正在启动就什么都不做,如果service的进程已存在就接着启动service,
    如果进程不存在,则要先启动进程.
private final String bringUpServiceLocked(ServiceRecord r,
            int intentFlags, boolean execInFg, boolean whileRestarting) {
   
        if (r.app != null && r.app.thread != null) {
        //1.如果已经启动.这个方法会通过ApplicationThread传递到ActivityThread
    然后调用wevice的onStartCommand方法
            sendServiceArgsLocked(r, execInFg, false);
            return null;
        }
        //2.如果目标Service正在等待restart完成,什么都不用做,直接返回
        if (!whileRestarting && r.restartDelay > 0) {
            // If waiting for a restart, then do nothing.
            return null;
        }
      //3.从正在重启的Service列表中移除目标Service
        if (mRestartingServices.remove(r)) {
            clearRestartingIfNeededLocked(r);
        }

        // 4.目标Service不再是delayed状态
        if (r.delayed) {
            if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "REM FR DELAY LIST (bring up): " + r);
            getServiceMap(r.userId).mDelayedStartList.remove(r);
            r.delayed = false;
        }

        
        // 5.确保目标Service所属的User处于started状态,否则不能启动service
        if (mAm.mStartedUsers.get(r.userId) == null) {
            String msg = "Unable to launch app "
                    + r.appInfo.packageName + "/"
                    + r.appInfo.uid + " for service "
                    + r.intent.getIntent() + ": user " + r.userId + " is stopped";
            bringDownServiceLocked(r);
            return msg;
        }

        //6.Service即将被启动,它所属的Package不能被停止
        try {
            AppGlobals.getPackageManager().setPackageStoppedState(
                    r.packageName, false, r.userId);
        } catch (RemoteException e) {
        }  

        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 {//7.此时目标进程已创建,为该进程添加package,创建并启动目标Service
                    app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
                    realStartServiceLocked(r, app, execInFg);
                    return null;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting service " + r.shortName, e);
                }
            }
        } else {
            app = r.isolatedProc;
        }

         //8.没有目标进程,通过ActivityManagerService来创建目标进程,调用将阻塞到目标进程创建完成为止
        if (app == null) {
            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    "service", r.name, false, isolated, false)) == null) {
             //9.运行到这里说明目标进程创建失败
                String msg = "Unable to launch app "
                        + r.appInfo.packageName + "/"
                        + r.appInfo.uid + " for service "
                        + r.intent.getIntent() + ": process is bad";
                bringDownServiceLocked(r);
                return msg;
            }
            if (isolated) {
                r.isolatedProc = app;
            }
        }
      //10.将目标Service添加到 正在启动Service但未启动完成 的Service列表中
        if (!mPendingServices.contains(r)) {
            mPendingServices.add(r);
        }
        return null;
    }
  1. ActivityService.realStartServiceLocked 接着看正常的执行流程
    这个方法的重要部分就是远程调用到ActivityThread中的onStart,onBind,onStartCommand方法.
 private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        
        r.app = app;
        r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
        app.services.add(r);
        bumpServiceExecutingLocked(r, execInFg, "create");
        mAm.updateLruProcessLocked(app, false, null);
        mAm.updateOomAdjLocked();

        boolean created = false;
        try {
            synchronized (r.stats.getBatteryStats()) {
                r.stats.startLaunchedLocked();
            }
   //1.确保目标App的Dex已经优化完成
            mAm.ensurePackageDexOpt(r.serviceInfo.packageName);
            app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
 //2.通过ApplicationThread.夸进程到ActivityThread启动service.执行service的onAttach,onCreat
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
            r.postNotification();
            created = true;
        } catch (DeadObjectException e) { 
            mAm.appDiedLocked(app);
        } finally {
            if (!created) {//
                app.services.remove(r);
                r.app = null;
                scheduleServiceRestartLocked(r, false);
                return;
            }
        }
//3. 如果Service需要绑定,则绑定目标Service,bindingServices时一定会执行.
他最后会执行到onBind方法.
        requestServiceBindingsLocked(r, execInFg);

        updateServiceClientActivitiesLocked(app, null, true);

 
        if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
            r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                    null, null));
        }
//4.通知客户端ApplicationThread调用目标Service的onStartCommand方法
        sendServiceArgsLocked(r, execInFg, true);

        if (r.delayed) {
            if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "REM FR DELAY LIST (new proc): " + r);
            getServiceMap(r.userId).mDelayedStartList.remove(r);
            r.delayed = false;
        }

        if (r.delayedStop) {
            // Oh and hey we've already been asked to stop!
            r.delayedStop = false;
            if (r.startRequested) {
                if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "Applying delayed stop (from start): " + r);
                stopServiceLocked(r);
            }
        }
    }
  1. app.thread.scheduleCreateService是核心方法.app.thread 就是ApplicationThread在服务器端的代理,这是binder机制,这里不说了.最后就是ApplicationThread发送message,交给ActivityThread的handler处理,最后待用了handleCreateService 方法.内部就是加载了service,执行他的attach,onCreate,并通知ams
    AcitivityThread.handleCreateService
private void handleCreateService(CreateServiceData data) {
      //1.如果当前已经准备好gc了.那么取消gc,因为我们要添加新东西
        unscheduleGcIdler();
      //2.取得App对应的LoadedApk
        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
      //3. 通过反射来创建Service实例
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = (Service) cl.loadClass(data.info.name).newInstance();
        } catch (Exception e) {
        }
        try {
             //4.创建Service的base context
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);
            //5.取得Application
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            //6.填充信息到Service
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManagerNative.getDefault());
            service.onCreate();
             //7.将创建完成的Service放入mServices这个Map中
            mServices.put(data.token, service);
            try {
            //8 通知服务端,Service启动完成。 
                ActivityManagerNative.getDefault().serviceDoneExecuting(
                        data.token, 0, 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);
            }
        }
    }
  1. 步骤7.4的方法sendServiceArgsLocked 最后调用到ActivityThread.handleServiceArgs
    其实就是执行 onStartCommand
private void handleServiceArgs(ServiceArgsData data) {
        Service s = mServices.get(data.token);
        if (s != null) {
            try {
                if (data.args != null) {
                    data.args.setExtrasClassLoader(s.getClassLoader());
                    data.args.prepareToEnterProcess();
                }
                int res;
                if (!data.taskRemoved) { //1.调用onStartCommand
                    res = s.onStartCommand(data.args, data.flags, data.startId);
                } else {
        //2.如果你写了这个标签 FLAG_STOP_WITH_TASK |FLAG_STOP_WITH_TASK就走这里.(目前不懂)
                    s.onTaskRemoved(data.args);
                    res = Service.START_TASK_REMOVED_COMPLETE;
                }
                QueuedWork.waitToFinish();
                try {//2.通知ams,service已经启动成功
                    ActivityManagerNative.getDefault().serviceDoneExecuting(
                            data.token, 1, data.startId, res);
                } 
                ensureJitEnabled();
            } catch (Exception e) {
            }
        }
    }

3.绑定过程

service_bind.png
  1. 先看一下绑定的写法.
  Intent service = new Intent(this , ServcieDemo.class);
        /**
         * 第一个参数:intent对象
         * 第二个参数:servcieConnection  用于监听服务当前的状态
         * 第三个参数:BIND_AUTO_CREATE 服务自动创建,然后绑定。
         */
        bindService(service, new MyConn(),  BIND_AUTO_CREATE);
  1. 看下MyConn的类
class MyConn implements ServiceConnection{
        /**
         * 如果服务能够成功绑定上,那么这个方法将会调用,启动的参数service就是服务返回的内部对象 MyBinder
         */
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //获取到服务内部返回的代理对象 ,用binder承接起来
            binder = (MyBinder) service;
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {}
    }

3.在看下service里和重要代码

 public IBinder onBind(Intent intent) { //service内部方法
        //返回内部代理对象
        return new MyBinder();
    }
class MyBinder extends Binder{//自己写的service内部类
        /**
         * 内部人员中固有的方法,它的作用就让别人来访问它,然后它自己去访问服务中的方法。
         * 通过迂回的手段达到从外部类调用服务中的方法效果。
         */
         public void callMethodInService(String name , int money){
             methodInService(name , money);
         }
    }

4.总结一下.就是service里通过onBind 会返回给绑定service的Activity一个Binder代理,我们通过这个Binder可以访问调用Service的服务.当然这个Binder可以是同一个进程的,这种很简单,也可能因为Service是另一个进程,这就设计ipc,所以系统对Connection在内部又做了封装,就是为了适应跨进程的问题.
5.看代码.

ContextWrapper的绑定方法,也是调用ContextImpl的方法.同startService一样的.
    @Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        return mBase.bindService(service, conn, flags);
    }

ContextImpl类内部
  public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        warnIfCallingFromSystemProcess();
        return bindServiceCommon(service, conn, flags, Process.myUserHandle());
    }
//1.这个conn就是我们绑定时候写的conn.
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
            UserHandle user) {
        IServiceConnection sd;
 
        if (mPackageInfo != null) {
//2.mPackageInfo是LoadedApk类.这里对conn进行了封装,使conn里的binder可以支持IPC
            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
                    mMainThread.getHandler(), flags);
        } else {
            throw new RuntimeException("Not supported in system context");
        }
        validateServiceIntent(service);
        try {
            IBinder token = getActivityToken();
            //3.这里调用的Ams的bindService方法,可以看到.这里没有把conn传输过去,而是传递的sd对象
            int res = ActivityManagerNative.getDefault().bindService(
                mMainThread.getApplicationThread(), getActivityToken(),
                service, service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, user.getIdentifier());
            
            return res != 0;
        } catch (RemoteException e) {
            return false;
        }
    }

6.先看一下5.1的代码,在LoadedApk中.LoadeApk内部有个mServices,存放所有Context对应的
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map ,在这个map里,每个Connection
又对应一个ServiceDispatcher, ServiceDispatcher内部有个InnerConnection的内部类,这个类继承自Stub,
也就是一个Binder,是用来夸进程通讯用的.调用Ams的bindServices时,会调用InnerConnection的方法,InnerConnection在通知connection.ServiceDispatcher则是把二者联系在一起.


ublic final IServiceConnection getServiceDispatcher(ServiceConnection c,
            Context context, Handler handler, int flags) {
        synchronized (mServices) {
            LoadedApk.ServiceDispatcher sd = null;//1.得到context对应的map对象.
            ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
            if (map != null) {
                sd = map.get(c);//2.得到ServiceDispatcher对象,
            }
            if (sd == null) {//3.创建ServiceDispatcher对象是内部也创建了InnerConnection对象,
                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();//4.这里返回的就是InnerConnection对象.
        }
    }

7.接着看5.3的代码.调用到Ams的BindService
原理同startService一样.都是在ActiveServices里处理.

    public int bindService(IApplicationThread caller, IBinder token,
            Intent service, String resolvedType,

       //1.拒绝包含可能造成内存泄露的文件描述符的Intent
        if (service != null && service.hasFileDescriptors() == true) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }
        synchronized(this) {
            return mServices.bindServiceLocked(caller, token, service, resolvedType,
                    connection, flags, userId);
        }
    }

8.ActiveServices.bindServiceLocked
方法的目的是找到调用者,然后封装绑定相关的数据. AppBindRecord ConnectionRecord

 int bindServiceLocked(IApplicationThread caller, IBinder token,
            Intent service, String resolvedType,
            IServiceConnection connection, int flags, int userId) {
       //1.在ActivityManagerService中查询不到调用者,直接抛出异常。
        final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
        if (callerApp == null) {
            throw new SecurityException(
                    "Unable to find app for caller " + caller
                    + " (pid=" + Binder.getCallingPid()
                    + ") when binding service " + service);
        }

        ActivityRecord activity = null;
        if (token != null) {//2.activity没找到. ActivityRecord 是activity的数据记录对象.
            activity = ActivityRecord.isInStackLocked(token);
            if (activity == null) {
                Slog.w(TAG, "Binding with unknown activity: " + token);
                return 0;
            }
        }

        int clientLabel = 0;
        PendingIntent clientIntent = null;

        final boolean callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE;
//3.是获取根据intent、binder等数据获取Service的信息,其中ServiceLookupResult包含了ServiceRecord和权限信息
        ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType,
                    Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg);
        if (res == null) {
            return 0;
        }
        if (res.record == null) {
            return -1;
        }
        ServiceRecord s = res.record;

        final long origId = Binder.clearCallingIdentity();
 //4.这里跟踪service的消耗.
            if ((flags&Context.BIND_AUTO_CREATE) != 0) {
                s.lastActivity = SystemClock.uptimeMillis();
                if (!s.hasAutoCreateConnections()) {
                    // This is the first binding, let the tracker know.
                    ProcessStats.ServiceState stracker = s.getTracker();
                    if (stracker != null) {
                        stracker.setBound(true, mAm.mProcessStats.getMemFactorLocked(),
                                s.lastActivity);
                    }
                }
            }
            //5.维持应用和service的关系
            AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
//6.进程和Service建立起的本次通信,记一次ConnectionRecord
            ConnectionRecord c = new ConnectionRecord(b, activity,
                    connection, flags, clientLabel, clientIntent);

            IBinder binder = connection.asBinder();
      
   //7.主要代码,调用bringUpServiceLocked继续绑定线程
//BIND_TREAT_LIKE_ACTIVITY可以降低Service被杀的概率、重新回调connected、rebind等
            if ((flags&Context.BIND_AUTO_CREATE) != 0) {
                s.lastActivity = SystemClock.uptimeMillis();
                if (bringUpServiceLocked(s, service.getFlags(), callerFg, false) != null) {
                    return 0;
                }
            }

            if (s.app != null) {
                if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
                    s.app.treatLikeActivity = true;
                }
                // 8.使service变得更重要,应该是改变进程的优先级.
                mAm.updateLruProcessLocked(s.app, s.app.hasClientActivities
                        || s.app.treatLikeActivity, b.client);
                mAm.updateOomAdjLocked(s.app);
            }

           //9.服务已经启动.直接发布连接
            if (s.app != null && b.intent.received) {
                // Service is already running, so we can immediately
                // publish the connection.
                try {
                    c.conn.connected(s.name, b.intent.binder);
                } catch (Exception e) {
                    Slog.w(TAG, "Failure sending service " + s.shortName
                            + " to connection " + c.conn.asBinder()
                            + " (in " + c.binding.client.processName + ")", e);
                }

                // If this is the first app connected back to this binding,
                // and the service had previously asked to be told when
                // rebound, then do so 
                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);
            }
            getServiceMap(s.userId).ensureNotStartingBackground(s);
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
        return 1;
    }
  1. 接着看ActivityServices.bringUpServiceLocked ,这里的执行和启动service的步骤6 以后都是差不多的,因为是同样的方法,bringUpServiceLocked在调用realStartServiceLocked,这里会执行startService过程中7.3的requestServiceBindingsLocked方法.我们在这里看
  private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg) {
        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) {
        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 {
//1.r.app.thread就是ApplicationThread在Ams端的代理,这个方法会夸进程掉调用到ApplicationThread的方法,然后发送message执行到ActivityThread 的主线程.
                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;
    }

10.ActivityThread.handleBindService
本地处理service的方法.回调了onBind方法,同时通知了Ams

 private void handleBindService(BindServiceData data) {
//1.先根据Token 取出service.
        Service s = mServices.get(data.token);
    
        if (s != null) {
            try {
                data.intent.setExtrasClassLoader(s.getClassLoader());
                data.intent.prepareToEnterProcess();
                try {
                    if (!data.rebind) {
//1.调用了service的onBind方法,onBind方法会返回给客户端一个Binder对象,
到这里原则上service已经绑定成功了.但是客户端还不知道,所以我们要通过
调用客户端的SerciveConnection的onServiceConnected方法.
                        IBinder binder = s.onBind(data.intent);
//2.这个重要,通知Ams,注意,这里的binder是service中用户提供的binder,
                        ActivityManagerNative.getDefault().publishService(
                                data.token, data.intent, binder);
                    } else {
                        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);
                }
            }
        }

11.ActivtiyManagerService.publishService
还是交给了ActivityServices来处理.

    public void publishService(IBinder token, Intent intent, IBinder service) {
        // Refuse possible leaked file descriptors //1.拒绝可能存在的文件描述符泄漏.
        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");
            }//2.还是通过ActivityServices来处理
            mServices.publishServiceLocked((ServiceRecord)token, intent, service);
        }
    }
ActivityServices.publishServiceLocked方法执行了ServiceDispatcher.InnerConnection的connected方法
 void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
        final long origId = Binder.clearCallingIdentity();
        try { 
            if (r != null) {
                Intent.FilterComparison filter
                        = new Intent.FilterComparison(intent);
                IntentBindRecord b = r.bindings.get(filter);
                if (b != null && !b.received) {
                    b.binder = service;
                    b.requested = true;
                    b.received = true;
                    for (int conni=r.connections.size()-1; conni>=0; conni--) {
                        ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
                        for (int i=0; i<clist.size(); i++) {
                            ConnectionRecord c = clist.get(i);
                            if (!filter.equals(c.binding.intent.intent)) {
                                continue;
                            }
//1.这里是核心代码,调用conn的connected方法,此时的IBinder  service是来自客户端.
conn 是IServiceConnection类,其实就是最开始的  ServiceDispatcher的内部类InnerConnection的代理.
                            try {
                                c.conn.connected(r.name, service);
                            } catch (Exception e) {
                            }
                        }
                    }
                }
                serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }

11.看InnerConnection.connected方法.
其实就是调用了ServiceDispatcher 的connected方法.

InnerConnection.connected
 public void connected(ComponentName name, IBinder service) throws RemoteException {
                LoadedApk.ServiceDispatcher sd = mDispatcher.get();
                if (sd != null) {
                    sd.connected(name, service);//1.执行ServiceDiaptacher的connected方法
                }
            }
ServiceDiaptacher.connected
    public void connected(ComponentName name, IBinder service) {
            if (mActivityThread != null) {
   //2.主要执行这个.因为mActivityThread 是主线程的handler,不会为空,
其实最后就是执行RunConnection的run方法.在主线程中.接着看.
                mActivityThread.post(new RunConnection(name, service, 0));
            } else {
                doConnected(name, service);
            }
        }
RunConnection.run
    public void run() {
                if (mCommand == 0) {
//这里,因为上边传入的是0,RunConnection是ServiceDispatcher 的内部类,
doConnected在ServiceDispatcher 中
                    doConnected(mName, mService);
                } else if (mCommand == 1) {
                    doDeath(mName, mService);
                }
            }

12.ServiceDispatcher.doConnected
这里最终完成了用户绑定service是传入的ServiceConnection.onServiceConnected方法.

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

            synchronized (this) {
                if (mForgotten) {
               //如果正在解绑service,就忽略connection
                    return;
                }
                old = mActiveConnections.get(name);
                if (old != null && old.binder == service) {
                    // 存在connection. 返回
                    return;
                }

                if (service != null) {
                    // A new service is being connected... set it all up.
                    mDied = false;
                    info = new ConnectionInfo();
                    info.binder = service;
                    info.deathMonitor = new DeathMonitor(name, service);
                    try {
                        service.linkToDeath(info.deathMonitor, 0);
                        mActiveConnections.put(name, info);//保存content对应的connection.
                    } catch (RemoteException e) {
                        mActiveConnections.remove(name);
                        return;
                    }

                } else {
                    // The named service is being disconnected... clean up.
                    mActiveConnections.remove(name);
                }

                if (old != null) {//旧的绑定操作取消死亡监听
                    old.binder.unlinkToDeath(old.deathMonitor, 0);
                }
            }

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

推荐阅读更多精彩内容