Android Service 启动流程

1,605 阅读3分钟

概述

Service启动流程和Activity启动流程有些相似,不了解Activity启动流程的可以看我之前的一篇博客Android App启动过程

Start Service 流程

Context.startService()

首先我们先从 context.startService()这个方法为起点进行分析,我们看下他的源码

## ContextWrapper.java
public class ContextWrapper extends Context {
    public ComponentName startService(Intent service) {
        return mBase.startService(service); //其中mBase为ContextImpl对象 
    }
}

这个方法又调用了ContextImpl.startService

## ContextImpl.java
class ContextImpl extends Context {
    @Override
    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, mUser); 
    }
    
    private ComponentName startServiceCommon(Intent service, UserHandle user) {
    try {
    ...
        ComponentName cn = ActivityManagerNative.getDefault().startService(
            mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(getContentResolver()), getOpPackageName(), user.getIdentifier());
   ...
        return cn;
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
}

我们看到最后调用了ActivityManagerNative.getDefault().startService,其中ActivityManagerNative.getDefault()就是ActivityManagerService,这时就完成了从调用进程system_server进程,其中是通过Binder传输的信息

AMS.startService

下面我们看一下AMS到底做了什么

 ## ActivityManagerService.java
 public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, boolean requireForeground, String callingPackage, int userId)
            throws TransactionTooLargeException {
        ····
        synchronized(this) {
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            ComponentName res;
            try {
                res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, userId);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
            return res;
        }
    }

这个方法又调用了ActivityService#startServiceLocked

    ## ActivityService.java
    ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
            throws TransactionTooLargeException {
            
            ···
        ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType, callingPackage,
                    callingPid, callingUid, userId, true, callerFg, false, false);
        if (res == null) {
            return null;
        }
        if (res.record == null) {
            return new ComponentName("!", res.permission != null
                    ? res.permission : "private to package");
        }

        ServiceRecord r = res.record;
        ···
        ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
        return cmp;
        }
            
            
            

继续调用了ActivityService#startServiceInnerLocked

 ## ActivityService.java
 ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
            boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
        ···
        String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
        if (error != null) {
            return new ComponentName("!!", error);
        }
        ···

        return r.name;
    }

继续调用了ActivityService#bringUpServiceLocked

  private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
            
         ···

        if (!isolated) {
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
                        + " app=" + app);
            //如果Service进程存在
            if (app != null && app.thread != null) {
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
                    //启动Service
                    realStartServiceLocked(r, app, execInFg);
                    return null;
                } catch (TransactionTooLargeException e) {
                    throw e;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting service " + r.shortName, e);
                }

                // If a dead object exception was thrown -- fall through to
                // restart the application.
            }
        } 

        //如果不存在此进程,则
        if (app == null && !permissionsReviewRequired) {
            //启动运行的线程
            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    hostingType, r.name, false, isolated, false)) == null) {
                String msg = "Unable to launch app "
                        + r.appInfo.packageName + "/"
                        + r.appInfo.uid + " for service "
                        + r.intent.getIntent() + ": process is bad";
                Slog.w(TAG, msg);
                bringDownServiceLocked(r);
                return msg;
            }
            if (isolated) {
                r.isolatedProc = app;
            }
        }

        return null;
    }

这个方法主要做了俩件事

  • 如果Service进程已经存在,则直接调用realStartServiceLocked
  • 如果Service进程不存在,则直接执行startProcessLocked方法创建进程,进过层层的调用,最终会调用到AMS.attachApplicationLocked方法,然后执行realStartServiceLocked方法

AMS.attachApplicationLocked

private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {
    ...
    thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
            profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
            app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
            isRestrictedBackupMode || !normalMode, app.persistent,
            new Configuration(mConfiguration), app.compat,
            getCommonServicesLocked(app.isolated),
            mCoreSettingsObserver.getCoreSettingsLocked());

    ...
    if (!badApp) {
        try {
            //寻找所有需要在该进程中运行的服务 
            didSomething |= mServices.attachApplicationLocked(app, processName);
        } catch (Exception e) {
            badApp = true;
        }
    }
    ...
    return true;
}

继续调用 AS.attachApplicationLocked

 boolean attachApplicationLocked(ProcessRecord proc, String processName)
            throws RemoteException {
        boolean didSomething = false;
        ...
        if (mPendingServices.size() > 0) {
            ServiceRecord sr = null;
            try {
                for (int i=0; i<mPendingServices.size(); i++) {
                    sr = mPendingServices.get(i);
                    if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
                            || !processName.equals(sr.processName))) {
                        continue;
                    }

                    mPendingServices.remove(i);
                    i--;
                    proc.addPackage(sr.appInfo.packageName, sr.appInfo.longVersionCode,
                            mAm.mProcessStats);
                    //启动Service
                    realStartServiceLocked(sr, proc, sr.createdFromFg);
                    didSomething = true;
                  ...
                }
          
        }

这个方法调用了realStartServiceLocked


    private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
          ...
          app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
            r.postNotification();
            created = true;
            
            ...
        
        }

这个方法内部调用了app.thread.scheduleCreateService,而app.threadIApplicationThread类型的,他的实现是ActivityThread的内部类ApplicationThread是一个Binder,下面我们看一下ApplicationThread#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);
        }

这个方法其实是发送了一个消息给Handler,这个HandlerActivityThread的内部类H

  class H extends Handler {
   public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            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方法

 private void handleCreateService(CreateServiceData data) {
 

        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
            //获取类加载器
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            //加载Service实例
            service = packageInfo.getAppFactory()
                    .instantiateService(cl, data.info.name, data.intent);
        }

        try {
            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
            //创建Service的Context
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);

            Application app = packageInfo.makeApplication(false, mInstrumentation);
            //初始化Service
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
            //调用Service的onCreate方法
            service.onCreate();
            mServices.put(data.token, service);
            try {
                ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to create service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }
    }

到这里Service就启动完成了

总结

整个StartService过程,从进程的角度看Service的启动流程

  • ProcessA进程采用Binder形式向syster_server进程发起startService请求
  • syster_server进程收到请求后,向zygote进程发送创建进程的请求
  • zygote进程fork出新的进程,进出新进程的ActivityThreadmain方法
  • 新进程通过Bindersyster_server进程发起attachApplication请求
  • syster_server进程收到请求后,进过一系列的准备后,通过Binder向新进程发送scheduleCreateService请求
  • 新进程收到请求后,通过Handler发送CREATE_SERVICE消息
  • 主线程收到message,创建Service,并回调onCreate

参考:gityuan.com/2016/03/06/…