美文网首页
从startService窥探App创建流程

从startService窥探App创建流程

作者: zhllp | 来源:发表于2019-03-08 01:20 被阅读0次

    0.写在最前

    当我们在activity调用startService启动一个service,同时在AndroidManifest中指定process时,将会开启一个新的进程,并在这个进程运行这个Service。

    1.ContextImpl.startService()

       @Override
        public ComponentName startService(Intent service) {
            warnIfCallingFromSystemProcess();
            return startServiceCommon(service, false, mUser);
        }
    
    
        private ComponentName startServiceCommon(Intent service, boolean requireForeground,
                UserHandle user) {
            try {
                validateServiceIntent(service);
                service.prepareToLeaveProcess(this);
                // ActivityManagerProxy,最终会调用ActivityManagerService
                ComponentName cn = ActivityManager.getService().startService(
                    mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                                getContentResolver()), requireForeground,
                                getOpPackageName(), user.getIdentifier());
                if (cn != null) {
                    if (cn.getPackageName().equals("!")) {
                        throw new SecurityException(
                                "Not allowed to start service " + service
                                + " without permission " + cn.getClassName());
                    } else if (cn.getPackageName().equals("!!")) {
                        throw new SecurityException(
                                "Unable to start service " + service
                                + ": " + cn.getClassName());
                    } else if (cn.getPackageName().equals("?")) {
                        throw new IllegalStateException(
                                "Not allowed to start service " + service + ": " + cn.getClassName());
                    }
                }
                return cn;
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    
    

    2.AcvitityManagerService.startService()

    
    
        @Override
        public ComponentName startService(IApplicationThread caller, Intent service,
                String resolvedType, boolean requireForeground, String callingPackage, int userId)
                throws TransactionTooLargeException {
    
              
                //获取调用方的pid和uid
                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;
            }
        }
    
    

    3.接下来的调用流程ActiveServices.startServiceLocked ->ActiveServices.startServiceInnerLocked ->ActiveServices.bringUpServiceLocked

        private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
                boolean whileRestarting, boolean permissionsReviewRequired)
                throws TransactionTooLargeException {
    
            if (r.app != null && r.app.thread != null) {
                sendServiceArgsLocked(r, execInFg, false);
                return null;
            }
    
            ...
            ...
            final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
            final String procName = r.processName;
            String hostingType = "service";
            ProcessRecord app;
    
            //     当在service的配置清单里设置 android:isolatedProcess="true"
            //      将会开启新的进程执行
    
            if (!isolated) {
                app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
           
      
                if (app != null && app.thread != null) {
                    try {
                        app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, 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 (app == null && !permissionsReviewRequired) {
                //根据上述判断,此时app从ProcessRecord取值为空,说明当前系统并不此进程
               //则会调用到ActivityManagerService.startProcessLocked()方法
              //似曾相识,在上一章文章也分析过,调用此方法最终会开启一个新的进程,并做一系列的初始化操作
              //最终会到ActivityThread.main()方法
                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;
                }
            }
    
            if (r.fgRequired) {
                mAm.tempWhitelistUidLocked(r.appInfo.uid,
                        SERVICE_START_FOREGROUND_TIMEOUT, "fg-service-launch");
            }
    
            //加入到Pending队列中,当新的进程创建完毕后会继续在pending队里取出这个service
            if (!mPendingServices.contains(r)) {
                mPendingServices.add(r);
            }
          ...
          ...
            return null;
        }
    
    

    接上一章《Android启动流程》的分析,AMS与Zygote通信,fork出一个子进程,同时进行一系列的初始化操作后,最后会来到ActivityThread.main()方法

    注意:startProcess之后会将当前service加入pending列表中,以便后续进程初始化完后再从中取出来进行一系列操作。

    4 AcitivityThread.main

    
        public static void main(String[] args) {
    
            ...
            ...
    
            Process.setArgV0("<pre-initialized>");
          
            //准备main looper
            Looper.prepareMainLooper();
    
            ActivityThread thread = new ActivityThread();
            thread.attach(false);
    
            if (sMainThreadHandler == null) {
                sMainThreadHandler = thread.getHandler();
            }
            
            //开启消息循环
            Looper.loop();
    
            throw new RuntimeException("Main thread loop unexpectedly exited");
        }
    
    

    5.ActivityThead.attach()

    
        private void attach(boolean system) {
            sCurrentActivityThread = this;
            mSystemThread = system;
            
            //此时system=false,什么时候会是true?还记得上一篇分析说过吗,当system_server时,system为true
            if (!system) {
                ViewRootImpl.addFirstDrawHandler(new Runnable() {
                    @Override
                    public void run() {
                        ensureJitEnabled();
                    }
                });
    
                RuntimeInit.setApplicationObject(mAppThread.asBinder());
                final IActivityManager mgr = ActivityManager.getService();
                try {
                    mgr.attachApplication(mAppThread);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
                // Watch for getting close to heap limit.
                BinderInternal.addGcWatcher(new Runnable() {
                    @Override public void run() {
                        if (!mSomeActivitiesChanged) {
                            return;
                        }
                        Runtime runtime = Runtime.getRuntime();
                        long dalvikMax = runtime.maxMemory();
                        long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
                        if (dalvikUsed > ((3*dalvikMax)/4)) {
                            if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
                                    + " total=" + (runtime.totalMemory()/1024)
                                    + " used=" + (dalvikUsed/1024));
                            mSomeActivitiesChanged = false;
                            try {
                                mgr.releaseSomeActivities(mAppThread);
                            } catch (RemoteException e) {
                                throw e.rethrowFromSystemServer();
                            }
                        }
                    }
                });
            } else {
                // Don't set application object here -- if the system crashes,
                // we can't display an alert, we just want to die die die.
                android.ddm.DdmHandleAppName.setAppName("system_process",
                        UserHandle.myUserId());
                try {
                    mInstrumentation = new Instrumentation();
                    ContextImpl context = ContextImpl.createAppContext(
                            this, getSystemContext().mPackageInfo);
                    mInitialApplication = context.mPackageInfo.makeApplication(true, null);
                    mInitialApplication.onCreate();
                } catch (Exception e) {
                    throw new RuntimeException(
                            "Unable to instantiate Application():" + e.toString(), e);
                }
            }
            ...
            ...
    
    

    进入非system的判断语句执行逻辑

        //确保开启Jit
         ViewRootImpl.addFirstDrawHandler(new Runnable() {
                    @Override
                    public void run() {
                        ensureJitEnabled();
                    }
                });
          
        //获取ActivityManagerService在本地进程代理对象proxy
       //最终会调用ActivityManagerService.attachApplication()
        final IActivityManager mgr = ActivityManager.getService();
                try {
                    mgr.attachApplication(mAppThread);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
    
    

    mAppThread是个啥?

    
        final ApplicationThread mAppThread = new ApplicationThread();
    
    //继承自Binder
    private class ApplicationThread extends IApplicationThread.Stub {
               
    }
    
    

    mApplicationThead可以被看做作ActivityThead在远程(ActivityManagerService)的代理对象

    6 AMS.attachApplication

       @Override
        public final void attachApplication(IApplicationThread thread) {
            synchronized (this) {
                int callingPid = Binder.getCallingPid();
                final long origId = Binder.clearCallingIdentity();
                attachApplicationLocked(thread, callingPid);
                Binder.restoreCallingIdentity(origId);
            }
        }
    
    
    
    
            // Find the application record that is being attached...  either via
            // the pid if we are running in multiple processes, or just pull the
            // next app record if we are emulating process with anonymous threads.
            ProcessRecord app;
            long startTime = SystemClock.uptimeMillis();
            if (pid != MY_PID && pid >= 0) {
                synchronized (mPidsSelfLocked) {
                    app = mPidsSelfLocked.get(pid);
                }
            } else {
                app = null;
            }
    
            //此时
            if (app == null) {
                Slog.w(TAG, "No pending application record for pid " + pid
                        + " (IApplicationThread " + thread + "); dropping process");
                EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
                if (pid > 0 && pid != MY_PID) {
                    killProcessQuiet(pid);
                    //TODO: killProcessGroup(app.info.uid, pid);
                } else {
                    try {
                        thread.scheduleExit();
                    } catch (Exception e) {
                        // Ignore exceptions.
                    }
                }
                return false;
            }
    
            // If this application record is still attached to a previous
            // process, clean it up now.
            if (app.thread != null) {
                handleAppDiedLocked(app, true, true);
            }
    
            // Tell the process all about itself.
    
            if (DEBUG_ALL) Slog.v(
                    TAG, "Binding process pid " + pid + " to record " + app);
    
            final String processName = app.processName;
            try {
                AppDeathRecipient adr = new AppDeathRecipient(
                        app, pid, thread);
                thread.asBinder().linkToDeath(adr, 0);
                app.deathRecipient = adr;
            } catch (RemoteException e) {
                app.resetPackageList(mProcessStats);
                startProcessLocked(app, "link fail", processName);
                return false;
            }
    
            EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.userId, app.pid, app.processName);
    
            app.makeActive(thread, mProcessStats);
            app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;
            app.curSchedGroup = app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
            app.forcingToImportant = null;
            updateProcessForegroundLocked(app, false, false);
            app.hasShownUi = false;
            app.debugging = false;
            app.cached = false;
            app.killedByAm = false;
            app.killed = false;
    
    
            mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
    
            boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
            List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null;
    
          //安装provider比Application初始化还要早
    
            if (providers != null && checkAppInLaunchingProvidersLocked(app)) {
                Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG);
                msg.obj = app;
                mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_PUBLISH_TIMEOUT);
            }
    
            checkTime(startTime, "attachApplicationLocked: before bindApplication");
    
            if (!normalMode) {
                Slog.i(TAG, "Launching preboot mode app: " + app);
            }
    
                ...
                ...
                checkTime(startTime, "attachApplicationLocked: immediately before bindApplication");
                mStackSupervisor.mActivityMetricsLogger.notifyBindApplication(app);
                if (app.instr != null) {
                    thread.bindApplication(processName, appInfo, providers,
                            app.instr.mClass,
                            profilerInfo, app.instr.mArguments,
                            app.instr.mWatcher,
                            app.instr.mUiAutomationConnection, testMode,
                            mBinderTransactionTrackingEnabled, enableTrackAllocation,
                            isRestrictedBackupMode || !normalMode, app.persistent,
                            new Configuration(getGlobalConfiguration()), app.compat,
                            getCommonServicesLocked(app.isolated),
                            mCoreSettingsObserver.getCoreSettingsLocked(),
                            buildSerial);
                } else {
                    thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                            null, null, null, testMode,
                            mBinderTransactionTrackingEnabled, enableTrackAllocation,
                            isRestrictedBackupMode || !normalMode, app.persistent,
                            new Configuration(getGlobalConfiguration()), app.compat,
                            getCommonServicesLocked(app.isolated),
                            mCoreSettingsObserver.getCoreSettingsLocked(),
                            buildSerial);
                }
    
           boolean badApp = false;
            boolean didSomething = false;
    
            // 针对Activity做一下事情
            if (normalMode) {
                try {
                    if (mStackSupervisor.attachApplicationLocked(app)) {
                        didSomething = true;
                    }
                } catch (Exception e) {
                    Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                    badApp = true;
                }
            }
    
            // 
            if (!badApp) {
                try {
                    didSomething |= mServices.attachApplicationLocked(app, processName);
                    checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");
                } catch (Exception e) {
                    Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
                    badApp = true;
                }
            }
    
            // Check if a next-broadcast receiver is in this process...
            if (!badApp && isPendingBroadcastProcessLocked(pid)) {
                try {
                    didSomething |= sendPendingBroadcastsLocked(app);
                    checkTime(startTime, "attachApplicationLocked: after sendPendingBroadcastsLocked");
                } catch (Exception e) {
                    // If the app died trying to launch the receiver we declare it 'bad'
                    Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e);
                    badApp = true;
                }
            }
              
    
    
    

    接着调用thead.bindApplication()方法,而thread则是ApplicationThread,接下来又会回到用户进程

    7 ApplicationThread.bindApplication()

            public final void bindApplication(String processName, ApplicationInfo appInfo,
                    List<ProviderInfo> providers, ComponentName instrumentationName,
                    ProfilerInfo profilerInfo, Bundle instrumentationArgs,
                    IInstrumentationWatcher instrumentationWatcher,
                    IUiAutomationConnection instrumentationUiConnection, int debugMode,
                    boolean enableBinderTracking, boolean trackAllocation,
                    boolean isRestrictedBackupMode, boolean persistent, Configuration config,
                    CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
                    String buildSerial) {
    
                if (services != null) {
                    // Setup the service cache in the ServiceManager
                    ServiceManager.initServiceCache(services);
                }
    
                setCoreSettings(coreSettings);
    
                AppBindData data = new AppBindData();
                data.processName = processName;
                data.appInfo = appInfo;
                data.providers = providers;
                data.instrumentationName = instrumentationName;
                data.instrumentationArgs = instrumentationArgs;
                data.instrumentationWatcher = instrumentationWatcher;
                data.instrumentationUiAutomationConnection = instrumentationUiConnection;
                data.debugMode = debugMode;
                data.enableBinderTracking = enableBinderTracking;
                data.trackAllocation = trackAllocation;
                data.restrictedBackupMode = isRestrictedBackupMode;
                data.persistent = persistent;
                data.config = config;
                data.compatInfo = compatInfo;
                data.initProfilerInfo = profilerInfo;
                data.buildSerial = buildSerial;
                sendMessage(H.BIND_APPLICATION, data);
            }
    
    

    接着通过mH这个handler发送消息,最终调用ActivityThead.handleBindApplication()

    8 ActivityThead.handleBindApplication()

          //忽略掉初始化配置一堆东西      
    
            final InstrumentationInfo ii;
            if (data.instrumentationName != null) {
                try {
                    ii = new ApplicationPackageManager(null, getPackageManager())
                            .getInstrumentationInfo(data.instrumentationName, 0);
                } catch (PackageManager.NameNotFoundException e) {
                    throw new RuntimeException(
                            "Unable to find instrumentation info for: " + data.instrumentationName);
                }
    
                mInstrumentationPackageName = ii.packageName;
                mInstrumentationAppDir = ii.sourceDir;
                mInstrumentationSplitAppDirs = ii.splitSourceDirs;
                mInstrumentationLibDir = getInstrumentationLibrary(data.appInfo, ii);
                mInstrumentedAppDir = data.info.getAppDir();
                mInstrumentedSplitAppDirs = data.info.getSplitAppDirs();
                mInstrumentedLibDir = data.info.getLibDir();
            } else {
                ii = null;
            }
    
            final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
            updateLocaleListFromAppContext(appContext,
                    mResourcesManager.getConfiguration().getLocales());
    
            if (!Process.isIsolated()) {
                setupGraphicsSupport(appContext);
            }
    
            if (ii != null) {
                final ApplicationInfo instrApp = new ApplicationInfo();
                ii.copyTo(instrApp);
                instrApp.initForUser(UserHandle.myUserId());
                final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                        appContext.getClassLoader(), false, true, false);
                final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
    
                try {
                    final ClassLoader cl = instrContext.getClassLoader();
                    mInstrumentation = (Instrumentation)
                        cl.loadClass(data.instrumentationName.getClassName()).newInstance();
                } catch (Exception e) {
                    throw new RuntimeException(
                        "Unable to instantiate instrumentation "
                        + data.instrumentationName + ": " + e.toString(), e);
                }
    
                final ComponentName component = new ComponentName(ii.packageName, ii.name);
                mInstrumentation.init(this, instrContext, appContext, component,
                        data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
    
                if (mProfiler.profileFile != null && !ii.handleProfiling
                        && mProfiler.profileFd == null) {
                    mProfiler.handlingProfiling = true;
                    final File file = new File(mProfiler.profileFile);
                    file.getParentFile().mkdirs();
                    Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
                }
            } else {
                mInstrumentation = new Instrumentation();
            }
    
            if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
                dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
            } else {
                // Small heap, clamp to the current growth limit and let the heap release
                // pages after the growth limit to the non growth limit capacity. b/18387825
                dalvik.system.VMRuntime.getRuntime().clampGrowthLimit();
            }
    
    
            
            Application app;
            try {
             
                //最终在Instrumentation类中通过反射实例化一个application,并调用application.onCreate() 生命周期函数
                app = data.info.makeApplication(data.restrictedBackupMode, null);
                mInitialApplication = app;
    
                // don't bring up providers in restricted mode; they may depend on the
                // app's custom Application class
                if (!data.restrictedBackupMode) {
                    if (!ArrayUtils.isEmpty(data.providers)) {
                        installContentProviders(app, data.providers);
                        // For process that contains content providers, we want to
                        // ensure that the JIT is enabled "at some point".
                        mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
                    }
                }
    
                // Do this after providers, since instrumentation tests generally start their
                // test thread at this point, and we don't want that racing.
                try {
                    mInstrumentation.onCreate(data.instrumentationArgs);
                }
                catch (Exception e) {
                    throw new RuntimeException(
                        "Exception thrown in onCreate() of "
                        + data.instrumentationName + ": " + e.toString(), e);
                }
                try {
                    mInstrumentation.callApplicationOnCreate(app);
                } catch (Exception e) {
                    if (!mInstrumentation.onException(app, e)) {
                        throw new RuntimeException(
                          "Unable to create application " + app.getClass().getName()
                          + ": " + e.toString(), e);
                    }
                }
            } finally {
                ...
            }
    
            // Preload fonts resources
            FontsContract.setApplicationContextForResources(appContext);
            try {
                final ApplicationInfo info =
                        getPackageManager().getApplicationInfo(
                                data.appInfo.packageName,
                                PackageManager.GET_META_DATA /*flags*/,
                                UserHandle.myUserId());
                if (info.metaData != null) {
                    final int preloadedFontsResource = info.metaData.getInt(
                            ApplicationInfo.METADATA_PRELOADED_FONTS, 0);
                    if (preloadedFontsResource != 0) {
                        data.info.getResources().preloadFonts(preloadedFontsResource);
                    }
                }
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    
    

    1.Instrumentation最初这个类是为了测试用途,系统向开发者暴露一些app创建过程中的信息以便测试,后来发展成 hook这个类可以为插件化提供所有能力(动态分发activity,service。。。),谷歌当初也没想到还可以这样用。插件化的过程这里不细说,如果有时间将插件化的原理也整理一下

    1. Provider的安装要早于Application的实例化。

    9 回到AMS.attachApplicationLocked()

    
            if (app.instr != null) {
                    thread.bindApplication(processName, appInfo, providers,
                            app.instr.mClass,
                            profilerInfo, app.instr.mArguments,
                            app.instr.mWatcher,
                            app.instr.mUiAutomationConnection, testMode,
                            mBinderTransactionTrackingEnabled, enableTrackAllocation,
                            isRestrictedBackupMode || !normalMode, app.persistent,
                            new Configuration(getGlobalConfiguration()), app.compat,
                            getCommonServicesLocked(app.isolated),
                            mCoreSettingsObserver.getCoreSettingsLocked(),
                            buildSerial);
                } else {
                    thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                            null, null, null, testMode,
                            mBinderTransactionTrackingEnabled, enableTrackAllocation,
                            isRestrictedBackupMode || !normalMode, app.persistent,
                            new Configuration(getGlobalConfiguration()), app.compat,
                            getCommonServicesLocked(app.isolated),
                            mCoreSettingsObserver.getCoreSettingsLocked(),
                            buildSerial);
                }
        
                ....
                ....
            
            //此时进程已经创建完,Application也已实例完
            //然后再mServices的pending列表找出需要执行的service
            if (!badApp) {
                try {
                    didSomething |= mServices.attachApplicationLocked(app, processName);
                    checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");
                } catch (Exception e) {
                    Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
                    badApp = true;
                }
            }
    
    
    

    10 ActiveServices.attachApplicationLocked

    最终会调用realStartServiceLocked()

        private final void realStartServiceLocked(ServiceRecord r,
                ProcessRecord app, boolean execInFg) throws RemoteException {
            ...
            ... 
            r.app = app;
            r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
            final boolean newService = app.services.add(r);
            //定时器
            bumpServiceExecutingLocked(r, execInFg, "create");
            mAm.updateLruProcessLocked(app, false, null);
            updateServiceForegroundLocked(r.app, /* oomAdj= */ false);
            mAm.updateOomAdjLocked();
    
            boolean created = false;
            try {
    
                synchronized (r.stats.getBatteryStats()) {
                    r.stats.startLaunchedLocked();
                }
                mAm.notifyPackageUse(r.serviceInfo.packageName,                                 PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
                app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
    
                //调用ApplicationThread的scheduleCreateService
                app.thread.scheduleCreateService(r, r.serviceInfo,
                        mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                        app.repProcState);
                r.postNotification();
                created = true;
            } catch (DeadObjectException e) {
                Slog.w(TAG, "Application dead when creating service " + r);
                mAm.appDiedLocked(app);
                throw e;
            } finally {
                if (!created) {
                    // Keep the executeNesting count accurate.
                    final boolean inDestroying = mDestroyingServices.contains(r);
                    serviceDoneExecutingLocked(r, inDestroying, inDestroying);
    
                    // Cleanup.
                    if (newService) {
                        app.services.remove(r);
                        r.app = null;
                    }
    
                    // Retry.
                    if (!inDestroying) {
                        scheduleServiceRestartLocked(r, false);
                    }
                }
            }
    
            if (r.whitelistManager) {
                app.whitelistManager = true;
            }
    
            //执行完onCreate执行,调用此方法bindService  
            requestServiceBindingsLocked(r, execInFg);
    
            updateServiceClientActivitiesLocked(app, null, true);
    
            // If the service is in the started state, and there are no
            // pending arguments, then fake up one so its                           onStartCommand() will
            // be called.
            if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
                r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                        null, null, 0));
            }
            
            //发送参数到client端,最终会导致onStartCommand触发
            sendServiceArgsLocked(r, execInFg, true);
    
    
        }
    
    

    说明一下:

    1. bumpServiceExecutingLocked将会开启一个定时器,
      这也是Service.onCreate执行超过某个时间会触发ANR的由来,为什么说是某个时间呢?根据是否在前台进程执行service判断的,如果是在前台,则为20s,如果为后台,则为10*20s=200s

    2. app.thread.scheduleCreateService()最终会调用到service.onCreate()

    3. requestServiceBindingsLocked(r, execInFg) 最终会调到bindService(),本章不作分析

    4.sendServiceArgsLocked最终会调用到service.onStartCommand()

    接下来继续分析scheduleCreateService,最终会调用ActivityThread.handleCreateService()

    11 ActivityThread.handleCreateService()

    
        private void handleCreateService(CreateServiceData data) {
          ....
           Service service = null;
            //反射实例化service
            try {
                java.lang.ClassLoader cl = packageInfo.getClassLoader();
                service = (Service) cl.loadClass(data.info.name).newInstance();
            } catch (Exception e) {
                if (!mInstrumentation.onException(service, e)) {
                    throw new RuntimeException(
                        "Unable to instantiate service " + data.info.name
                        + ": " + e.toString(), e);
                }
            }
          
    
            try {
    
                ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
                context.setOuterContext(service);
    
                Application app = packageInfo.makeApplication(false, mInstrumentation);
                service.attach(context, this, data.info.name, data.token, app,
                        ActivityManager.getService());
                //调用service的生命周期函数
                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();
                }
           .....
        }
    
    

    12 ActivityThread.handleServiceArgs

    过程10中最后执行sendServiceArgsLocked最终会到ActivityThread.handleServiceArgs

    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) {
                          //回调service的onStartCommand的生命周期函数
                         res = s.onStartCommand(data.args, data.flags,data.startId);
                     
                  ...
                  //取消ANR定时器,并进行一些收尾工作,这里不作分析了
        ActivityManager.getService().serviceDoneExecuting(
                                data.token, SERVICE_DONE_EXECUTING_START, data.startId, res)
            }
        }
    
    

    AMS.serviceDoneExecuting(),会根据type,res修改ServiceRecord的某些值

    11 不算总结的总结

    至此,整个流程分析完,后续有空补个流程图吧,- -!

    相关文章

      网友评论

          本文标题:从startService窥探App创建流程

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