Android Service 啓動流程

概述

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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章