美文网首页
APP启动流程

APP启动流程

作者: David_zhou | 来源:发表于2019-11-27 20:51 被阅读0次

    对于四个组件之一的activity, 也是用户接触最多的组件,那么activity背后究竟是如何启动的呢?下面就跟随好奇心寻找activity的启动流程。activity 的启动有两种,一种是从桌面launcher启动,一种是在应用内启动其他activity。第一种和第二种的区别在于是否需要先启动新的进程,接下来我们以最新的android 10代码来分析下。我们主要分析第一种启动方式,第二种方式也会顺带讲解。因为启动流程冗长复杂,因此代码只给出了关键部分。另外通过systrace可以看到启动的过程,所以相关的trace代码予以保留,抓取启动的systrace后,我们可以找到关键的部分,可以让我们更清楚的理解启动的过程。

    第一阶段 activity创建的准备工作

    ​ 应用安装后,图标都会显示在桌面。当我们点击应用图标后,调用的方法是conetxt中的startActivityForResult。conetxt可以译为上下文,可以认为是我们对系统调用的一个入口,比如启动activity和service,获取文件目录,发送广播等。context中启动activity的方法有startActivity和startActivityAsUser等,因为context是个抽象类。启动activity的具体实现在ContextImpl类中,startActivity和startActivityAsUser等几个方法的实现最终调用到以下方法:

    // ContextImpl.java
    @Override
        public void startActivity(Intent intent, Bundle options) {
            warnIfCallingFromSystemProcess();
            // 省略对FLAG_ACTIVITY_NEW_TASK的判断
            mMainThread.getInstrumentation().execStartActivity(
                    getOuterContext(), mMainThread.getApplicationThread(), null,
                    (Activity) null, intent, -1, options);
        }
    

    因为是分析从桌面开始启动的,因此mMainThread不为空。所以直接调用到的execStartActivity()方法。

    // Instrumentation.java
    public ActivityResult execStartActivity(
                Context who, IBinder contextThread, IBinder token, Activity target,
                Intent intent, int requestCode, Bundle options) {
            try {
                intent.migrateExtraStreamToClipData();
                intent.prepareToLeaveProcess(who);
                int result = ActivityTaskManager.getService()
                    .startActivity(whoThread, who.getBasePackageName(), intent,
                            intent.resolveTypeIfNeeded(who.getContentResolver()),
                            token, target != null ? target.mEmbeddedID : null,
                            requestCode, 0, null, options);
                checkStartActivityResult(result, intent);
            } catch (RemoteException e) {
                throw new RuntimeException("Failure from system", e);
            }
            return null;
        }
    

    最终是通过ActivityTaskManager的startActivity来启动activity,得到返回结果后在checkStartActivityResult中处理。从上面的Intent 的prepareToLeaveProcess方法名可以看出,后面会开始跨进程调用,此时准备离开启动activity的进程。ActivityTaskManager是android 10 上新增的类,这个类用来提供一些acivity相关的信息。接下来看下getService方法,代码如下:

    // ActivityTaskManager.java
        public static IActivityTaskManager getService() {
            return IActivityTaskManagerSingleton.get();
        }
    
        private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
                new Singleton<IActivityTaskManager>() {
                    @Override
                    protected IActivityTaskManager create() {
                        final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
                        return IActivityTaskManager.Stub.asInterface(b);
                    }
                };
    

    这个和之前版本的android获取AMS类似,不过这里获取的service是ActivityTaskManagerService。create方法ActivityTaskManagerService类实现了IActivityTaskManager.Stub接口,IActivityTaskManager里面有很多startactivity和 addAppTask等操作activity,task等的方法。ActivityTaskManager.getService()方法获取了一个ActivityTaskManagerService实例,并将远程对象IBinder传给给它。所以跨进程调用的实际是ActivityTaskManagerService的startActivity方法。startActivity最终调用到startActivityAsUser方法,关键代码如下:

    // ActivityTaskManagerService.java
    int startActivityAsUser(IApplicationThread caller, String callingPackage,Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,boolean validateIncomingUser) {
            // TODO: Switch to user app stacks here.
            return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
                    .setCaller(caller)
                    .setCallingPackage(callingPackage)
                    .setResolvedType(resolvedType)
                    .setResultTo(resultTo)
                    .setResultWho(resultWho)
                    .setRequestCode(requestCode)
                    .setStartFlags(startFlags)
                    .setProfilerInfo(profilerInfo)
                    .setActivityOptions(bOptions)
                    .setMayWait(userId)
                    .execute();
        }
    

    getActivityStartController方法获取到ActivityStartController,ActivityStartController这个类是从android 9引入的,这个类是处理启动activity的请求,并为后续的启动activity做好相应的准备。而obtainStarter方法获取到ActivityStarter,ActivityStarter是android7引入的,这个类主要负责解析以及启动activity。在设置一些启动的参数后,调用ActivityStarter的execute()开始执行。execute中调用了ActivityStarter的startActivity()方法,在这个方法中会进行一系列启动之前的检查,包括权限,activity是否存在,是否有匹配intent的activity等。主要代码如下:

    // ActivityStarter.java
    private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            SafeActivityOptions options,
            boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
            TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup,
            PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) {
        // 最终会调用systrace 生成“MetricsLogger:launchObserverNotifyIntentStarted”标签
        mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent);
        final int res = startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                true /* doResume */, checkedOptions, inTask, outActivity, restrictedBgActivity);
        mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(res, outActivity[0]);
        return res;
    }
    

    经过一系列检查之后调用的还是startActivity,这个方法中在调用startActivityUnchecked启动activity之后会对启动的结果进行处理,如果启动失败,会将启动失败的activity关闭等。

      // ActivityStarter.java       
    private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
                    IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                    int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
                    ActivityRecord[] outActivity, boolean restrictedBgActivity) {
            final ActivityStack startedActivityStack;
            try {
                mService.mWindowManager.deferSurfaceLayout();
                result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                        startFlags, doResume, options, inTask, outActivity, restrictedBgActivity);
            } finally {
               // 省略对activity启动结果的处理
                mService.mWindowManager.continueSurfaceLayout();
            }
            postStartActivityProcessing(r, result, startedActivityStack);
            return result;
        }
    } 
    

    前面的方法已经对参数进行过一些检验,因此接下来调用的是startActivityUnchecked方法,这个方法很长,会有一些额外的操作,比如设置Intent的flag,是否需要新的taskRecord,intent是否满足权限等检查。

    // ActivityStarter.java       
    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
                ActivityRecord[] outActivity, boolean restrictedBgActivity) {
            /// 省略非主流程代码
            mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
                    mOptions);
            mRootActivityContainer.updateUserStack(mStartActivity.mUserId, mTargetStack);
            mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTaskRecord(),
                    preferredWindowingMode, mPreferredDisplayId, mTargetStack);
            return START_SUCCESS;
        }
    

    这个函数很长,最后调用ActivityStack的startActivityLocked方法。startActivityLocked里面调用ensureActivitiesVisibleLocked,然后调用makeVisibleAndRestartIfNeeded,最后调用到ActivityStackSupervisor的startSpecificActivityLocked。代码如下

    // ActivityStackSupervisor.java  
    void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
            // Is this activity's application already running?
            final WindowProcessController wpc =
                    mService.getProcessController(r.processName, r.info.applicationInfo.uid);
            if (wpc != null && wpc.hasThread()) {
                try {
                    realStartActivityLocked(r, wpc, andResume, checkConfig);//
                    return;
                } catch (RemoteException e) {
                }
            }
            try {
                Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dispatchingStartProcess:"
                            + r.processName);
                final Message msg = PooledLambda.obtainMessage(
                        ActivityManagerInternal::startProcess, mService.mAmInternal, r.processName,
                        r.info.applicationInfo, knownToBeDead, "activity", r.intent.getComponent());
                mService.mH.sendMessage(msg);
            } finally {
                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
            }
        }
    

    这个函数重点看一下,activity的两种启动方式都会调用到这个方法,如果是在已有进程的基础上启动activity就会走上面的realStartActivityLocked方法,而如果是新启动app,此时线程不存在,就会走下面的ActivityManagerInternal::startProcess方法。
    第一阶段的流程如图所示


    image.png

    第二阶段 进程创建

    ActivityManagerInternal是个抽象类,具体实现是ActivityManagerService的内部类LocalService。代码如下:

    // ActivityManagerService.java
           public void startProcess(String processName, ApplicationInfo info,
                   boolean knownToBeDead, String hostingType, ComponentName hostingName) {
               try {
                   Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "startProcess:"
                               + processName);
                   synchronized (ActivityManagerService.this) {
                       startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
                               new HostingRecord(hostingType, hostingName),
                               false /* allowWhileBooting */, false /* isolated */,
                               true /* keepIfLarge */);
                   }
               } finally {
                   Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
               }
           }
    

    之前的要创建的activity信息就被封装到hostingName中,之后进一步封装到一个HostingRecord对象中,进程创建完成之后回来处理这个信息。startProcessLocked这个方法开始准备创建进程,这个方法调用的是ProcessList的startProcessLocked方法。startProcessLocked后续调用startProcess方法,代码如下:

    // ProcessList.java    
    private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,
                ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
                String seInfo, String requiredAbi, String instructionSet, String invokeWith,
                long startTime) {
            try {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                        app.processName);
                final Process.ProcessStartResult startResult;
                startResult = Process.start(entryPoint,
                         app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                         app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                         app.info.dataDir, invokeWith, app.info.packageName,
                         new String[] {PROC_START_SEQ_IDENT + app.startSeq});
                return startResult;
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            }
        }
    

    startProcess通过Process的start方法完成创建进程的操作,start方法通过新创建的ZygoteProcess完成进程的创建。众所周知,应用程序的进程都是通过zygote创建的,感觉离真相越来越近了。

    // Process.java
    public static final ZygoteProcess ZYGOTE_PROCESS = new ZygoteProcess();
    
    public static ProcessStartResult start(@NonNull final String processClass,
             @Nullable final String niceName,int uid, int gid, @Nullable int[] gids,
             int runtimeFlags,int mountExternal,int targetSdkVersion,@Nullable String seInfo,
             @NonNull String abi,@Nullable String instructionSet,@Nullable String appDataDir,
             @Nullable String invokeWith,@Nullable String packageName,@Nullable String[] zygoteArgs) {
            return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
                        runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                        abi, instructionSet, appDataDir, invokeWith, packageName,
                        /*useUsapPool=*/ true, zygoteArgs);
        }
    

    ZygoteProcess的start调用了startViaZygote方法,在这个方法中完成了一些创建进程参数的准备,代码如下:

    // ZygoteProcess.java    
    private Process.ProcessStartResult startViaZygote(@NonNull final String processClass,
            @Nullable final String niceName,final int uid, final int gid,@Nullable final int[] gids,
            int runtimeFlags, int mountExternal,int targetSdkVersion,@Nullable String seInfo,
            @NonNull String abi,@Nullable String instructionSet,@Nullable String appDataDir,
            @Nullable String invokeWith,boolean startChildZygote,@Nullable String packageName,
            boolean useUsapPool,@Nullable String[] extraArgs)throws ZygoteStartFailedEx {
            ArrayList<String> argsForZygote = new ArrayList<>();
            argsForZygote.add("--runtime-args");
            // 省略准备参数的过程
            synchronized(mLock) {
                // The USAP pool can not be used if the application will not use the systems graphics
                // driver.  If that driver is requested use the Zygote application start path.
                return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),useUsapPool,
                              argsForZygote);
            }
        }
    

    在准备好启动进程的参数后,通过openZygoteSocketIfNeeded创建一个ZygoteState。ZygoteState这个是和zygot进程通信的一个类,创建ZygoteState的代码如下:

    // ZygoteProcess.java   
    private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
            try {
                attemptConnectionToPrimaryZygote();
                if (primaryZygoteState.matches(abi)) {
                    return primaryZygoteState;
                }
                // 省略不匹配的过程
            } catch (IOException ioe) {
            }
            throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
        }
        // ZygoteProcess.java   
        private void attemptConnectionToPrimaryZygote() throws IOException {
            if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
                primaryZygoteState =
                        ZygoteState.connect(mZygoteSocketAddress, mUsapPoolSocketAddress);
                maybeSetApiBlacklistExemptions(primaryZygoteState, false);
                maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);
                maybeSetHiddenApiAccessStatslogSampleRate(primaryZygoteState);
            }
        }
        // ZygoteProcess.java   
        static ZygoteState connect(@NonNull LocalSocketAddress zygoteSocketAddress,
                    @Nullable LocalSocketAddress usapSocketAddress) throws IOException {
                DataInputStream zygoteInputStream;
                BufferedWriter zygoteOutputWriter;
                final LocalSocket zygoteSessionSocket = new LocalSocket();
                try {
                    zygoteSessionSocket.connect(zygoteSocketAddress);// localsocket 的connect()
                    zygoteInputStream = new DataInputStream(zygoteSessionSocket.getInputStream());
                    zygoteOutputWriter =new BufferedWriter(
                        new OutputStreamWriter(zygoteSessionSocket.getOutputStream()),
                            Zygote.SOCKET_BUFFER_SIZE);
                } catch (IOException ex) {
                }
                return new ZygoteState(zygoteSocketAddress, usapSocketAddress,
                                       zygoteSessionSocket, zygoteInputStream, zygoteOutputWriter,
                                       getAbiList(zygoteOutputWriter, zygoteInputStream));
            }
    

    attemptConnectionToPrimaryZygote中通过ygoteState的connect方法创建一个ZygoteState,就是这个对象和这zygote进程通过LocalSocket的方式通信。新建LocalSocket后将连接对象作为参数传递给ZygoteState的构造函数。新建一个ZygoteState对象后将其作为参数调用zygoteSendArgsAndGetResult。zygoteSendArgsAndGetResult中调用了attemptUsapSendArgsAndGetResult方法,代码如下

    // ZygoteProcess.java  
    private Process.ProcessStartResult attemptUsapSendArgsAndGetResult(
                ZygoteState zygoteState, String msgStr)
                throws ZygoteStartFailedEx, IOException {
            try (LocalSocket usapSessionSocket = zygoteState.getUsapSessionSocket()) {
                final BufferedWriter usapWriter =
                        new BufferedWriter(
                                new OutputStreamWriter(usapSessionSocket.getOutputStream()),
                                Zygote.SOCKET_BUFFER_SIZE);
                final DataInputStream usapReader =
                        new DataInputStream(usapSessionSocket.getInputStream());
                usapWriter.write(msgStr);
                usapWriter.flush();
                Process.ProcessStartResult result = new Process.ProcessStartResult();
                result.pid = usapReader.readInt();
                if (result.pid >= 0) {
                    return result;
                } 
            }
        }
    

    这里就是将之前准备好的创建进程的参数通过LocalSocke传递给zygote进程,这个进程有一个ZygoteServer来接受其他进程传递过来的信息,ZygoteServer中有个方法runSelectLoop,会开启死循环接受其他进程发起的socket请求。对于其他进程的请求,会调用的ZygoteConnection的processOneCommand进程处理。

    // Zygote.java 
    Runnable processOneCommand(ZygoteServer zygoteServer) {
            String args[];ZygoteArguments parsedArgs = null;FileDescriptor[] descriptors;
            int pid = -1;
            FileDescriptor childPipeFd = null;
            FileDescriptor serverPipeFd = null;
            parsedArgs = new ZygoteArguments(args);
          
            Zygote.applyUidSecurityPolicy(parsedArgs, peer);
            Zygote.applyInvokeWithSecurityPolicy(parsedArgs, peer);
            Zygote.applyDebuggerSystemProperty(parsedArgs);
            Zygote.applyInvokeWithSystemProperty(parsedArgs);
            pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,
                    parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
                    parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
                    parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mTargetSdkVersion);
            try {
                if (pid == 0) {
                    // in child
                    zygoteServer.setForkChild();
                    zygoteServer.closeServerSocket();
                    IoUtils.closeQuietly(serverPipeFd);
                    serverPipeFd = null;
                    return handleChildProc(parsedArgs, descriptors, childPipeFd,
                            parsedArgs.mStartChildZygote);
                } else {
                    // In the parent. A pid < 0 indicates a failure and will be handled in
                    // handleParentProc.
                    IoUtils.closeQuietly(childPipeFd);
                    childPipeFd = null;
                    handleParentProc(pid, descriptors, serverPipeFd);
                    return null;
                }
            } 
        }
    
     public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
                int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
                int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
                int targetSdkVersion) {
            resetNicePriority();
            int pid = nativeForkAndSpecialize(
                    uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
                    fdsToIgnore, startChildZygote, instructionSet, appDataDir);
            // Enable tracing as soon as possible for the child process.
            if (pid == 0) {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
            }
            return pid;
        }
    
    private static native int nativeForkAndSpecialize(int uid, int gid, int[] gids,
                int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
                int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet,
                String appDataDir);
    

    processOneCommand中调用zygote的forkAndSpecialize进行创建进程的操作,forkAndSpecialize中调用native方法nativeForkAndSpecialize完成进程真正的创建,linux层最终调用fork完成进程的创建。值得注意的是fork方法,这是个神奇的方法,神奇的地方在于有两个返回值。方法的返回值pid,如果pid等于0,表示当前进程是新创建出来的子进程,不为0 表示原有进程。创建完成之后会到processOneCommand,如果是子进程,还会调用handleChildProc。在这个方法里完成一些对刚创建进程的一些初始操作。这个方法继续调用ZygoteInit的zygoteInit方法,zygoteInit的代码如下:

    // ZygoteInit.java
      public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,
                ClassLoader classLoader) {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
            RuntimeInit.redirectLogStreams();
            RuntimeInit.commonInit();
            ZygoteInit.nativeZygoteInit();
            return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
        }
    

    关注下RuntimeInit的applicationInit这个方法,在这个方法会进行虚拟机的一些设置之后继续调用findStaticMain方法。
    这个阶段的流程如图所示:

    image.png

    第三阶段 新进程的启动

    findStaticMain通过反射的方式调用了ActivityThread的main方法。至此,我们新启动的进程开始执行。

    // RuntimeInit.java 
    protected static Runnable findStaticMain(String className, String[] argv,
                ClassLoader classLoader) {
            Class<?> cl;
            try {
                cl = Class.forName(className, true, classLoader);
            } catch (ClassNotFoundException ex) {
            }
            Method m;
            try {
                m = cl.getMethod("main", new Class[] { String[].class });
            } catch (NoSuchMethodException ex) {
            }
            return new MethodAndArgsCaller(m, argv);
        }
    
     public void run() {
                try {
                    mMethod.invoke(null, new Object[] { mArgs });
                } catch (IllegalAccessException ex) {
                    throw new RuntimeException(ex);
                } 
            }
    

    至此,就回到熟悉的ActivityThread了,开始调用main方法。main是一个程序的入口,这个也是android应用的启动入口。

    // ActivityThread.java    
    public static void main(String[] args) {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
            Looper.prepareMainLooper();
            ActivityThread thread = new ActivityThread();
            thread.attach(false, startSeq);
            if (sMainThreadHandler == null) {
                sMainThreadHandler = thread.getHandler();
            }
            Looper.loop();
            throw new RuntimeException("Main thread loop unexpectedly exited");
        }
    

    Looper的loop是个死循环,开始轮询直到主动退出,因此我们的应用会一直运行,不会结束。loop的代码如下:

    // Looper.java
    public static void loop() {
            for (;;) {
                Message msg = queue.next(); // might block
                if (msg == null) {
                    // No message indicates that the message queue is quitting.
                    return;
                }
                // 省略其他代码
            }
        }
    

    死循环的关键在于上面的queue.next方法,这个方法会调用nativePollOnce。nativePollOnce是个native方法,这个方法不简单,这个方法会监听一个管道,如果管道有数据,则读。否则会阻塞,类似于linux层的epoll方法。

    回过来看main中的重点方法attach(),

    // ActivityThread.java    
    private void attach(boolean system, long startSeq) {
            sCurrentActivityThread = this;
            mSystemThread = system;
            if (!system) {
                RuntimeInit.setApplicationObject(mAppThread.asBinder());
                final IActivityManager mgr = ActivityManager.getService();
                try {
                    mgr.attachApplication(mAppThread, startSeq);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            } 
        }
    

    ActivityManager的getService()返回的是IActivityManager ,真正调用的是ActivityManagerService 的attachApplication 方法。这个地方是通过binder进行的跨进程调用,所以我们直接看下attachApplication 方法,代码如下:

    // ActivityManagerService.java 
    private final boolean attachApplicationLocked(IApplicationThread thread,
                int pid, int callingUid, long startSeq){
         // 省略部分代码
            try {
                mAtmInternal.preBindApplication(app.getWindowProcessController());
                final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
                thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                        null, null, null, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.isPersistent(),
                        new Configuration(app.getWindowProcessController().getConfiguration()),
                        app.compat, getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial, autofillOptions, contentCaptureOptions);
                mProcessList.updateLruProcessLocked(app, false, null);
            } catch (Exception e) {
                //省略异常处理代码
            }
            // See if the top visible activity is waiting to run in this process...
            if (normalMode) {
                try {
                    didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
                } catch (Exception e) {
                    Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                    badApp = true;
                }
            }
            // 省略对services,broadcast receiver的处理部分  
            return true;
        }
    

    我们先看thread的bindApplication方法,thread是ApplicationThread类,充当ams在app进程的client。这个方法也是跨进程的,实际上调用的ApplicationThread类的bindApplication。ApplicationThread是ActivityThread内部类,ApplicationThread和ActivityThread因为已经在同一个进程了,所以可以通过H这个中间类以handle的方式通信。ApplicationThread的bindApplication实际上是发送一个message,处理message 的代码如下:

    // ActivityThread.java  
     public void handleMessage(Message msg) {
            switch (msg.what) {
                case BIND_APPLICATION:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
                    AppBindData data = (AppBindData)msg.obj;
                    handleBindApplication(data);
                    break;
                  }  
                  // 省略处理其他msg的代码
            }
    

    这个阶段的流程如图所示:


    image.png

    第四阶段 Application的创建

    handleBindApplication方法开始处理ApplicationThread发送的msg,在handleBindApplication方法中会初始化一些关键的类,比如Instrumentation,loadedApk等,代码如下:

    // ActivityThread.java   
    private void handleBindApplication(AppBindData data) {
            // 省略部分代码
            data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);// 创建loadedapk
            try {
                final ClassLoader cl = instrContext.getClassLoader();
                mInstrumentation = (Instrumentation)
                        cl.loadClass(data.instrumentationName.getClassName()).newInstance();
                } 
            try {
                // If the app is being launched for full backup or restore, bring it up in
                // a restricted environment with the base application class.
                app = data.info.makeApplication(data.restrictedBackupMode, null);
                mInstrumentation.onCreate(data.instrumentationArgs);
                mInstrumentation.callApplicationOnCreate(app);
            } 
        }
    

    handleBindApplication方法中首先通过反射的方式创建Instrumentation,之后通过LoadedApk的makeApplication创建Application。最后调用Instrumentation的onCreate和callApplicationOnCreate方法,先看下makeApplication方法。

    // LoadedApk.java    
    public Application makeApplication(boolean forceDefaultAppClass,
                Instrumentation instrumentation) {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
            Application app = null;
            String appClass = mApplicationInfo.className;
            try {
                app = mActivityThread.mInstrumentation.newApplication(
                        cl, appClass, appContext);
            } catch (Exception e) {
            }
            instrumentation.callApplicationOnCreate(app);
            return app;
        }
    
    // Instrumentation.java
     public Application newApplication(ClassLoader cl, String className, Context context)
                throws InstantiationException, IllegalAccessException, 
                ClassNotFoundException {
            Application app = getFactory(context.getPackageName())
                    .instantiateApplication(cl, className);
            app.attach(context);
            return app;
        }
     
    // AppComponentFactory.java
    public @NonNull Application instantiateApplication(@NonNull ClassLoader cl,
                @NonNull String className)
                throws InstantiationException, IllegalAccessException, ClassNotFoundException {
            return (Application) cl.loadClass(className).newInstance();
        }
    
    // Application.java
    final void attach(Context context) {
            attachBaseContext(context);
            mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
        }
    

    newApplication方法最终也是通过反射的方式创建Application,其中的className是app中的application。因为app安装的时候系统会去解析manifest中的内容,因此查询系统可以知道要启动的application的具体类名,知道类名后通过反射的方式创建applictaion对象。之后调用attach方法,可以看到attachBaseContext()的调用是早于Application的onCreate方法。回到makeApplication方法,创建Applicaton之后,通过Instrumentation的callApplicationOnCreate方法调用了创建的Applicaton对象的onCreate方法。至此终于走到应用的Application的onCreate方法了。
    第四阶段的流程如图所示:


    image.png

    第五阶段 activity的创建

    执行完应用程序的Application的Oncreate方法后,handleBindApplication的执行也就结束。回到AMS中的attachApplicationLocked方法,执行完thread的bindApplication()后还需要处理activity。k

    // ActivityManagerService.java 
     private final boolean attachApplicationLocked(IApplicationThread thread,
                int pid, int callingUid, long startSeq) {
            thread.bindApplication();
            // See if the top visible activity is waiting to run in this process...
             if (normalMode) {
                try {
                    didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
                    } catch (Exception e) {
                }
            }
    }
    

    mAtmInternal是ActivityTaskManagerInternal的实现类,也就是ActivityTaskManagerService的内部类LocalService。在localService的attachApplication方法中调用了RootActivityContainer的attachApplication方法。

    // RootActivityContainer.java 
     boolean attachApplication(WindowProcessController app) throws RemoteException {
            for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
                if (stack != null) {
                    for (int i = 0; i < size; i++) {
                        final ActivityRecord activity = mTmpActivityList.get(i);
                        if (activity.app == null && app.mUid == activity.info.applicationInfo.uid
                                && processName.equals(activity.processName)) {
                            try {
                                if (mStackSupervisor.realStartActivityLocked(activity, app,
                                        top == activity /* andResume */, true /* checkConfig */)) {
                                    didSomething = true;
                                }
                            } catch (RemoteException e) {}
                        }
                    }
                }
            }
        }
    

    看到熟悉的realStartActivityLocked方法了,这个方法我们之前在的startSpecificActivityLocked看到过,只不过当时因为没有进程存在,所以并没有执行这个方法。下面我们看一下这个方法。

    // ActivityStackSupervisor.java
    boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
                boolean andResume, boolean checkConfig) throws RemoteException {
            try {
                // Create activity launch transaction.
                final ClientTransaction clientTransaction = ClientTransaction.obtain(
                        proc.getThread(), r.appToken);
                clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
                        System.identityHashCode(r), r.info,
                        // TODO: Have this take the merged configuration instead of separate global
                        // and override configs.
                        mergedConfiguration.getGlobalConfiguration(),
                        mergedConfiguration.getOverrideConfiguration(), r.compat,
                        r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
                        r.icicle, r.persistentState, results, newIntents,
                        dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
                        r.assistToken));
                // Set desired final state.
                final ActivityLifecycleItem lifecycleItem;
                if (andResume) {
                    lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
                } else {
                    lifecycleItem = PauseActivityItem.obtain();
                }
                clientTransaction.setLifecycleStateRequest(lifecycleItem);
                // Schedule transaction.
                mService.getLifecycleManager().scheduleTransaction(clientTransaction);
                return true;
            }
        }
    

    新建了一个ClientTransaction对象后,设置了LaunchActivityItem的callback。然后调用mService的getLifecycleManager()获取到ClientLifecycleManager,然后调用ClientLifecycleManager的scheduleTransaction开始发起请求。下面看scheduleTransaction这个方法,代码如下:

    // ClientLifecycleManager.java
     void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
            final IApplicationThread client = transaction.getClient();
            transaction.schedule();
            if (!(client instanceof Binder)) {
                transaction.recycle();
            }
        }
    
    // ClientTransaction.java
    private IApplicationThread mClient;
    public void schedule() throws RemoteException {
            mClient.scheduleTransaction(this);
        }
    

    mClient实际上是ApplicationThread在AMS的client端,所以下面就看下ApplicationThread的scheduleTransaction方法。

    // ActivityThread.java
    public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
                ActivityThread.this.scheduleTransaction(transaction);
            }
    

    直接调用ActivityThread的scheduleTransaction,但这个方法实现在ActivityThread的父类ClientTransactionHandler中。这个方法的实现就是发送message,发送和处理的逻辑在

    // ClientTransactionHandler.java
    void scheduleTransaction(ClientTransaction transaction) {
            transaction.preExecute(this);
            sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
        }
    
    // ActivityThread.java
    private final TransactionExecutor mTransactionExecutor = new TransactionExecutor(this);
    public void handleMessage(Message msg) {
           if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
           switch (msg.what) {
                 case EXECUTE_TRANSACTION:
                 final ClientTransaction transaction = (ClientTransaction) msg.obj;
                 mTransactionExecutor.execute(transaction);
                 break;
            }
        }
    

    mTransactionExecutor初始化时将ActivityThread对象作为参数传递到构造函数中,在ClientTransaction的execute会调用callback,而这个callback在前面设置的是LaunchActivityItem 。最终调用到LaunchActivityItem 的execute方法。

      // LaunchActivityItem.java
        public void execute(ClientTransactionHandler client, IBinder token,
                PendingTransactionActions pendingActions) {
            Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
            ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
                    mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState,                               mPersistentState,mPendingResults, mPendingNewIntents, mIsForward,mProfilerInfo, 
                    client, mAssistToken);
            client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
            Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
        }
    

    此处的client就是前面作为构造函数参数的ActivityThread对象,因此这里调用的ActivityThread的handleLaunchActivity。

    // ActivityThread.java    
    public Activity handleLaunchActivity(ActivityClientRecord r,
                PendingTransactionActions pendingActions, Intent customIntent) {
            final Activity a = performLaunchActivity(r, customIntent);
            return a;
        }
    
        private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
            ContextImpl appContext = createBaseContextForActivity(r);
            Activity activity = null;
            try {
                java.lang.ClassLoader cl = appContext.getClassLoader();
                activity = mInstrumentation.newActivity(
                        cl, component.getClassName(), r.intent);
             } catch (Exception e) {
            }
            try {
                Application app = r.packageInfo.makeApplication(false, mInstrumentation);
                if (activity != null) {
                    activity.attach(appContext, this, getInstrumentation(), r.token,
                            r.ident, app, r.intent, r.activityInfo, title, r.parent,
                            r.embeddedID, r.lastNonConfigurationInstances, config,
                            r.referrer, r.voiceInteractor, window, r.configCallback,
                            r.assistToken);
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
            } catch (SuperNotCalledException e) {
                throw e;
            } catch (Exception e) {
            }
            return activity;
        }
    
        // Instrumentation.java
        public Activity newActivity(ClassLoader cl, String className,
                Intent intent)
                throws InstantiationException, IllegalAccessException,
                ClassNotFoundException {
            String pkg = intent != null && intent.getComponent() != null
                    ? intent.getComponent().getPackageName() : null;
            return getFactory(pkg).instantiateActivity(cl, className, intent);
        }
    
        // AppComponentFactory.java
        public @NonNull Activity instantiateActivity(@NonNull ClassLoader cl, @NonNull String className, @Nullable Intent intent)throws InstantiationException, IllegalAccessException, ClassNotFoundException {
            return (Activity) cl.loadClass(className).newInstance();
        }
    

    performLaunchActivity中通过mInstrumentation的newActivity方法创建了一个activity。activity与一般的java对象很大一个区别是activity存在上下文信息,所以创建出actvity对象后Activity的attach方法,将activity和ActivityThread,Instrumentation,Application等重要的类关联上。关联之后调用Instrumentation的callActivityOnCreate方法,准备执行activity对象的onCreate方法。调用的过程如下:

    // Instrumentation.java
     public void callActivityOnCreate(Activity activity, Bundle icicle) {
            prePerformCreate(activity);
            activity.performCreate(icicle);
            postPerformCreate(activity);
        }
    
    // Activity.java
    final void performCreate(Bundle icicle) {
            performCreate(icicle, null);
        }
    
    // Activity.java 
    final void performCreate(Bundle icicle, PersistableBundle persistentState) {
            dispatchActivityPreCreated(icicle);
            onCreate(icicle);
            dispatchActivityPostCreated(icicle);
        }
    

    在performCreate中调用了activity的onCreate方法,至此activity已经创建,并且开始走生命周期。
    第五阶段的流程如图所示:


    image.png

    总算走到最后,新的app进程已经创建,第一个activity也开始创建,后续就可以执行应用程序的业务逻辑。启动流程实在太长,一来是因为牵扯到启动应用的进程,系统进程,新创建的进程,进程通信本身就有点复杂,更别说三个进程。尤其是新创建的进程要完成很多初始化操作。二来是因为activity的创建很复杂,activity说是应用程序最重要的组件,也是个和各个系统都有交互的复杂组件,牵扯的类也特别多。

    和之前的启动流程相比,出现了很多新的类,比如ClientTransactionHandler和ActivityStartController是从android 9开始引入,而ActivityStarter是android7引入的。ActivityTaskManager却是android 10引入的,启动流程一直在优化。

    流程很复杂,难免有不妥或错误的地方,欢迎指正。

    在分析启动的流程中,参考了现有资料,感谢先行者的经验总结和无私分享。

    参考文献

    Android Activity 启动详解

    Android进阶(四):Activity启动过程(最详细&最简单)

    App启动流程:启动App进程

    Activity的启动流程-基于Android10源码

    相关文章

      网友评论

          本文标题:APP启动流程

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