Android进阶解密②—Service的启动

Service的启动分为两种,startService和bindService;

1.StartService

startService启动流程可以分为两步,ContextImpl到AMS,AMS到ActivityThread

ContextImpl到AMS

Service是基于装饰器模式的,装饰器是ContextImpl,被装饰类的接口是ContextWraper,Service是被装饰类,它将startService()请求交给装饰器ContextImpl去处理:

ContextImpl
    private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
        try {
            ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), requireForeground,
                            getOpPackageName(), user.getIdentifier());
            return cn;
        }  
    }

ContextImpl的startServiceCommon()中调用了IActivityManager的startService();上一篇文章提过IActivityManager,这是AMS在用户进程的Binder代理对象;

AMS到ActivityThread

企业咚咚20200921102802.jpg

在AMS中,通过一个核心类ActiveServices来完成Service的启动,主要涉及到三个方法:

  • startServiceInnerLocked():准备ServiceRecord,ServiceRecord和ProcessRecord,ActivityRecord一样,记录了Service的所有信息;
  • bringUpServiceLock():判断Service运行的进程
  • realStartServiceLocked():调用app.thread发起Binder通信通知ApplicationThread;

ActivityThread

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

在ApplicationThread中发出了一个Message,H.CREATE_SERVICE

H的处理

                case CREATE_SERVICE:
                    handleCreateService((CreateServiceData)msg.obj);
                    break;

    private void handleCreateService(CreateServiceData data) {
        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        //  分析1
        Service service = null;
        try {
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = (Service) cl.loadClass(data.info.name).newInstance();
        } 

        try {
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            //   分析2
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
            //  分析3
            service.onCreate();
            mServices.put(data.token, service);
        } 
    }
  • 通过ClassLoader构建Service实例对象
  • 绑定ContextImpl
  • 调用onCreate()

补充:AMS进程的ActiveServices的realStartServiceLocked中发起了两个Binder通信,一次用于启动Service,一次用于调用onStartCommand();流程和第一次一样,消息是SERVICE_ARGS

2. BindService:

BindService也是由ContextImpl发起的,通过用户进程代理iActivityManager传递给AMS,过程和上面一样,重点来看AMS中bindService()的逻辑;

AMS的bindService逻辑都交给了ActiveServices
    int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, final IServiceConnection connection, int flags,
            String callingPackage, final int userId) throws TransactionTooLargeException {
...
                //   分析1
                if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
                        permissionsReviewRequired) != null) {
                    return 0;
                }
...

                //  分析2
                requestServiceBindingLocked(s, b.intent, callerFg, false);
      }
  • bindService首先调用bringUp去启动Service,这里上文已经说过,和startService一样,
  • 第二步通过requestServiceBindingLocked()绑定Service的生命周期;

ActiveServices:

    private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
            boolean execInFg, boolean rebind) throws TransactionTooLargeException {
...
           r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,r.app.repProcState);
...
    }

在这里将绑定的请求交给了ActivityThread类的Application;

ActivityThread

        public final void scheduleBindService(IBinder token, Intent intent, boolean rebind, int processState) {
            sendMessage(H.BIND_SERVICE, s);
     }

H.handleMessage():

      case UNBIND_SERVICE:          
           handlebindService((BindServiceData)msg.obj);               
           break;


    private void handleBindService(BindServiceData data) {
        if (s != null) {
                try {
                    //  分析1
                    if (!data.rebind) {
                        IBinder binder = s.onBind(data.intent);
                        //  分析2
                        ActivityManager.getService().publishService(
                                data.token, data.intent, binder);
                    } else {
                        s.onRebind(data.intent);
                        ActivityManager.getService().serviceDoneExecuting(
                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                    }
             }
      }
  • 在这里会根据Service是否启动过调用onBind()或者onRebind()
  • 如果没有绑定过,会发出一个binder消息,调用AMS中的 publishService()
publishService最终调用ActiveServices的publishServiceLocked:
   void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
...
       c.conn.connected(r.name, service, false);
...   
    }

c.conn是iServiceConnection,是用户进程的ServiceConnection在AMS进程的代理,他的具体实现是ServiceDispatcher.innerConnection,而ServiceDispatcher是LoadedApk的内部类:

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

调用了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);
            }
        }

在这里发出了一个主线程的Handler消息,发出的是一个Runnable,我们看一下run():

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


        public void doConnected(ComponentName name, IBinder service, boolean dead) {
...
          mConnection.onServiceConnected(name, service);
...
        }

在这里调用了onServiceConnect(),客户端的ServiceConnection会执行相同的回调;