美文网首页
应用的启动流程分析

应用的启动流程分析

作者: 赛非斯 | 来源:发表于2021-09-26 23:34 被阅读0次

    无论做应用开发还是做系统开发,这个流程我建议都必须掌握的,基本上每个大厂都会问。之前都是在博客园写文章,近来看简书上也有很多大佬,所以后面也会慢慢的在简书上发表一些自己对源码的心得。源码解析都是基于Android10.0

    首先,我们从桌面点击一个图标开始

    • 1、在launcher里面,每个图标被认为是一个item,点击就会触发onListItemClick方法,下面源码我们可以看到它实际是启动Activity的方法。
    android_source_code10.0.0_r40\frameworks\base\core\java\android\app\LauncherActivity.java
     @Override
        protected void onListItemClick(ListView l, View v, int position, long id) {
            Intent intent = intentForPosition(position);
            startActivity(intent);
        }
    
    • 2、接着我们进入frameworks/base/core/java/android/app/Activity.java 的StartActivity方法;为什么?因为LauncherActivity的父类是Activity。
     @Override
        public void startActivity(Intent intent) {
            this.startActivity(intent, null);
        }
    //下面还是内部方法
       @Override
        public void startActivity(Intent intent, @Nullable Bundle options) {
            if (options != null) {
    //到这我们看到不管你怎么启动的Activity,最终都会调用startActivityForResult
                startActivityForResult(intent, -1, options);
            } else {
                // Note we want to go through this call for compatibility with
                // applications that may have overridden the method.
                startActivityForResult(intent, -1);
            }
        }
    
    //这里我们只截图我们关心的流程代码,下面还是Acivity的方法
     public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
                @Nullable Bundle options) {
            if (mParent == null) {
                options = transferSpringboardActivityOptions(options);
                Instrumentation.ActivityResult ar =
                    mInstrumentation.execStartActivity(
                        this, mMainThread.getApplicationThread(), mToken, this,
                        intent, requestCode, options);
                if (ar != null) {
                    mMainThread.sendActivityResult(
                        mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                        ar.getResultData());
                }
    
    • 接着我们进入Instrumentation的类,Activity类里面的Instrumentation怎么来的? attach 方法中构建的!!接着分析 mInstrumentation.execStartActivity 方法:
      frameworks/base/core/java/android/app/Instrumentation.java 这可是掌管Activity的生命周期的管家,我们要想干点坏事,在这处理就行了。这里我们重点关注两点:
      1、whoThread 是个啥,有啥用? 是mMainThread(ActivityThread)对应的Application Thread
      2、ActivityTaskManager.getService() .startActivity 这里通过binder调用到ATMS里面的startActivity
      3、为啥要把ApplicationThread作为参数传给ATMS呢,带着问题我们接着往下看
     @UnsupportedAppUsage
        public ActivityResult execStartActivity(
                Context who, IBinder contextThread, IBinder token, Activity target,
                Intent intent, int requestCode, Bundle options) {
            IApplicationThread whoThread = (IApplicationThread) contextThread;
    ...
     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);
            } 
    ...
    
    • 走>> 我们去ATMS里面一探究竟:
      frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
        @Override
        public final int startActivity(IApplicationThread caller, String callingPackage,
                Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
                int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
            return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                    resultWho, requestCode, startFlags, profilerInfo, bOptions,
                    UserHandle.getCallingUserId());
        }
     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) {
     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();
    }
    //frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.java
     ActivityStarter obtainStarter(Intent intent, String reason) {
            return mFactory.obtain().setIntent(intent).setReason(reason);
        }
    

    -费了这么大劲,他还是把任务扔给ActivityStart去做了
    frameworks/base/services/core/java/com/android/server/wm/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) {
    //做了前期检查,权限、栈等
    //创建了ActivityRecord
    //继续调用
      final int res = startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                    true /* doResume */, checkedOptions, inTask, outActivity, restrictedBgActivity);
    }
    //注意看关键函数startActivityUnchecked
    private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
                    IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                    int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
                    ActivityRecord[] outActivity, boolean restrictedBgActivity) {
            int result = START_CANCELED;
            final ActivityStack startedActivityStack;
            try {
                mService.mWindowManager.deferSurfaceLayout();
                result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                        startFlags, doResume, options, inTask, outActivity, restrictedBgActivity);
            }
    }
    
        // Note: This method should only be called from {@link startActivity}.
        private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
                ActivityRecord[] outActivity, boolean restrictedBgActivity) {
            setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
                    voiceInteractor, restrictedBgActivity);
    //这里主要做了栈的检查,一些设计决定这个Activity以哪种方式创建
     computeLaunchingTaskFlags();
      if (reusedActivity.getTaskRecord() == null) {
                        reusedActivity.setTask(task);
                    }
    }
    ...
    mRootActivityContainer.resumeFocusedStacksTopActivities(
                            mTargetStack, mStartActivity, mOptions);
    ...
    }
    
    //frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java
     boolean resumeFocusedStacksTopActivities(
                ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
    
            if (!mStackSupervisor.readyToResume()) {
                return false;
            }
    
            boolean result = false;
            if (targetStack != null && (targetStack.isTopStackOnDisplay()
                    || getTopDisplayFocusedStack() == targetStack)) {
                result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
            }
    }
    
    
    • 接下来进入栈内的处理逻辑: 如果应用还没有创建就先创建应用,否则resume 它
    frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java
    
     @GuardedBy("mService")
        boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
            if (mInResumeTopActivity) {
                // Don't even start recursing.
                return false;
            }
    
            boolean result = false;
            try {
                // Protect against recursion.
                mInResumeTopActivity = true;
                result = resumeTopActivityInnerLocked(prev, options);
    }
    }
    //接着我们进入核心代码
      @GuardedBy("mService")
        private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
            if (!mService.isBooting() && !mService.isBooted()) {
                // Not ready yet!
                return false;
            }
    ..
        //比如当前是launcher 没有最近任务  launcher又挂了的场景
         if (!hasRunningActivity) {
                // There are no activities left in the stack, let's look somewhere else.
                return resumeNextFocusableActivityWhenStackIsEmpty(prev, options);
            }
    
    //先让上一个应用pause
      boolean pausing = display.pauseBackStacks(userLeaving, next, false);
            if (mResumedActivity != null) {
                if (DEBUG_STATES) Slog.d(TAG_STATES,
                        "resumeTopActivityLocked: Pausing " + mResumedActivity);
                pausing |= startPausingLocked(userLeaving, false, next, false);
            }
       if (next.attachedToProcess()) {
                    next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
                            true /* activityChange */, false /* updateOomAdj */);
                } else if (!next.isProcessRunning()) {
                    // Since the start-process is asynchronous, if we already know the process of next
                    // activity isn't running, we can start the process earlier to save the time to wait
                    // for the current activity to be paused.
                    final boolean isTop = this == display.getFocusedStack();
                    mService.startProcessAsync(next, false /* knownToBeDead */, isTop,
                            isTop ? "pre-top-activity" : "pre-activity");
                }
                if (lastResumed != null) {
                    lastResumed.setWillCloseOrEnterPip(true);
                }
                return true;
            } else if (mResumedActivity == next && next.isState(RESUMED)
                    && display.allResumedActivitiesComplete()) {
                // It is possible for the activity to be resumed when we paused back stacks above if the
                // next activity doesn't have to wait for pause to complete.
                // So, nothing else to-do except:
                // Make sure we have executed any pending transitions, since there
                // should be nothing left to do at this point.
                executeAppTransition(options);
                if (DEBUG_STATES) Slog.d(TAG_STATES,
                        "resumeTopActivityLocked: Top activity resumed (dontWaitForPause) " + next);
                return true;
            }
    //判断当前应用是否创建了
     if (next.attachedToProcess()) {
      final ClientTransaction transaction =
                            ClientTransaction.obtain(next.app.getThread(), next.appToken);
    
     transaction.setLifecycleStateRequest(
                            ResumeActivityItem.obtain(next.app.getReportedProcState(),
                                    dc.isNextTransitionForward()));
                    mService.getLifecycleManager().scheduleTransaction(transaction);
    }else{
    //否则 我重新创建一个
     mStackSupervisor.startSpecificActivityLocked(next, true, true);
    }
    
    }
    
    • 上面讲到如果应用没启动过就创建一个进程,否则resume,创建应用的过程就是fork进程的过程,我们重点讲resume的过程,核心代码啊:
      frameworks/base/services/core/java/com/android/server/wm/ClientLifecycleManager.java
     private final ClientLifecycleManager mLifecycleManager;
    {
    transaction.setLifecycleStateRequest(
                            ResumeActivityItem.obtain(next.app.getReportedProcState(),
                                    dc.isNextTransitionForward()));
                    mService.getLifecycleManager().scheduleTransaction(transaction);
    }
    //frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java
        /** Target client. */
        private IApplicationThread mClient;
    //mClient 就是 IApplicationThread 客户端
     public void schedule() throws RemoteException {
            mClient.scheduleTransaction(this);
        }
    //这里我们就从ActivityStack 通过binder调用 IApplicationThread 
        void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
            final IApplicationThread client = transaction.getClient();
            transaction.schedule();
            if (!(client instanceof Binder)) {
                // If client is not an instance of Binder - it's a remote call and at this point it is
                // safe to recycle the object. All objects used for local calls will be recycled after
                // the transaction is executed on client in ActivityThread.
                transaction.recycle();
            }
        }
    
    
    
    
    • 我们要找的ApplicationThread 服务端就在ActivityThread的内部类
      frameworks/base/core/java/android/app/ActivityThread.java ,我们还知道 public final class ActivityThread extends ClientTransactionHandler 这种继承关系
          @Override
            public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
                ActivityThread.this.scheduleTransaction(transaction);
            }
    
    //frameworks/base/core/java/android/app/ClientTransactionHandler.java
        /** Prepare and schedule transaction for execution. */
        void scheduleTransaction(ClientTransaction transaction) {
            transaction.preExecute(this);
            sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
        }
    这个消息到哪了,到H 的
      case EXECUTE_TRANSACTION:
                        final ClientTransaction transaction = (ClientTransaction) msg.obj;
                        mTransactionExecutor.execute(transaction);
                        if (isSystem()) {
                            // Client transactions inside system process are recycled on the client side
                            // instead of ClientLifecycleManager to avoid being cleared before this
                            // message is handled.
                            transaction.recycle();
                        }
                        // TODO(lifecycler): Recycle locally scheduled transactions.
                        break;
    
    
    frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
         public void execute(ClientTransaction transaction) {
    ..
            executeCallbacks(transaction);
    
            executeLifecycleState(transaction);
    }
    //executeCallbacks->item.execute(mTransactionHandler, token, mPendingActions);
    //回到ActivityStack 传过来的item是 ResumeActivityItem
    //frameworks/base/core/java/android/app/servertransaction/ResumeActivityItem.java
    //client 不久正式ActivityThread吗
       @Override
        public void execute(ClientTransactionHandler client, IBinder token,
                PendingTransactionActions pendingActions) {
            Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
          (token, true /* finalStateRequest */, mIsForward,
                    "RESUME_ACTIVITY");
            Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
        }
    
    • 于是通过 client.handleResumeActivity 又回到了ActivityThread
     @Override
        public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
                String reason) {
       final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
    }
    
     @VisibleForTesting
        public ActivityClientRecord performResumeActivity(IBinder token, boolean finalStateRequest,
                String reason) {
             r.activity.performResume(r.startsNotResumed, reason);
    
                r.state = null;
                r.persistentState = null;
                r.setState(ON_RESUME);
    
                reportTopResumedActivityChanged(r, r.isTopResumedActivity, "topWhenResuming");
    }
    
    • 上面看到又回到Activity.java ,又回到 mInstrumentation.callActivityOnResume(this);
     final void performResume(boolean followedByPause, String reason) {
            dispatchActivityPreResumed();
            performRestart(true /* start */, reason);
            // mResumed is set by the instrumentation
            mInstrumentation.callActivityOnResume(this);
            writeEventLog(LOG_AM_ON_RESUME_CALLED, reason);
       }
        public void callActivityOnResume(Activity activity) {
            activity.mResumed = true;
            activity.onResume();
            
            if (mActivityMonitors != null) {
                synchronized (mSync) {
                    final int N = mActivityMonitors.size();
                    for (int i=0; i<N; i++) {
                        final ActivityMonitor am = mActivityMonitors.get(i);
                        am.match(activity, activity, activity.getIntent());
                    }
                }
            }
        }     
    
    • 看到这里是不是很熟悉了
      activity.onResume(); 生命周期的onresume,没错,就是它。这就是应用的热启动流程
      所谓冷启动就是多了一个创建应用进程的过程,接着前面讲到的
      //否则 我重新创建一个
      mStackSupervisor.startSpecificActivityLocked(next, true, true);

    frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java

      void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
    ...
        final boolean isTop = andResume && r.isTopRunningActivity();
            mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
    }
    //frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
        void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,
                String hostingType) {
            try {
                if (Trace.isTagEnabled(TRACE_TAG_ACTIVITY_MANAGER)) {
                    Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dispatchingStartProcess:"
                            + activity.processName);
                }
                // Post message to start process to avoid possible deadlock of calling into AMS with the
                // ATMS lock held.
                final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess,
                        mAmInternal, activity.processName, activity.info.applicationInfo, knownToBeDead,
                        isTop, hostingType, activity.intent.getComponent());
                mH.sendMessage(m);
            } finally {
                Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
            }
        }
    
    //有到哪了
    frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
            @Override
            public void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead,
                    boolean isTop, String hostingType, ComponentName hostingName) {
                try {
                    if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
                        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "startProcess:"
                                + processName);
                    }
                    synchronized (ActivityManagerService.this) {
                        // If the process is known as top app, set a hint so when the process is
                        // started, the top priority can be applied immediately to avoid cpu being
                        // preempted by other processes before attaching the process of top app.
                        startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
                                new HostingRecord(hostingType, hostingName, isTop),
                                ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, false /* allowWhileBooting */,
                                false /* isolated */, true /* keepIfLarge */);
                    }
                } finally {
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                }
            }
    
        @GuardedBy("this")
        final ProcessRecord startProcessLocked(String processName,
                ApplicationInfo info, boolean knownToBeDead, int intentFlags,
                HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,
                boolean isolated, boolean keepIfLarge) {
            return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
                    hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,
                    keepIfLarge, null /* ABI override */, null /* entryPoint */,
                    null /* entryPointArgs */, null /* crashHandler */);
        }
    
    • core/java/com/android/server/am/ProcessList.java 直接上结果吧,看下面的代码就知道这是socket通信
     private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,
                ProcessRecord app, int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags,
                int mountExternal, String seInfo, String requiredAbi, String instructionSet,
                String invokeWith, long startTime) {
    if (hostingRecord.usesAppZygote()) {
                    final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);
    .....
                    startResult = appZygote.getProcess().start(entryPoint,
                            app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                            app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                            app.info.dataDir, null, app.info.packageName,
                            /*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,
                            app.mDisabledCompatChanges,
                            new String[]{PROC_START_SEQ_IDENT + app.startSeq});
                } else {
                    startResult = Process.start(entryPoint,
                            app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                            app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                            app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags,
                            isTopApp, app.mDisabledCompatChanges,
                            new String[]{PROC_START_SEQ_IDENT + app.startSeq});
                }
    }
    //frameworks/base/core/java/android/os/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());
    
    }
    
    • 创建完应用进程之后紧接着进入
      frameworks/base/core/java/android/app/ActivityThread.java 的main 方法,比较关键代码是
      mgr.attachApplication(mAppThread, startSeq);
      这是干啥,这是要把ApplicationThread 作为参数传给AMS,这样AMS就持有了ApplicationThread 客户端代理的引用,可以通过binder调用ApplicationThread 了。
    public static void main(String[] args) {
     ActivityThread thread = new ActivityThread();
            thread.attach(false, startSeq);
    }
      @UnsupportedAppUsage
        private void attach(boolean system, long startSeq) {
            sCurrentActivityThread = this;
            mSystemThread = system;
            if (!system) {
                android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                        UserHandle.myUserId());
                RuntimeInit.setApplicationObject(mAppThread.asBinder());
                final IActivityManager mgr = ActivityManager.getService();
                try {
                    mgr.attachApplication(mAppThread, startSeq);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
    }
    frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
     @Override
        public final void attachApplication(IApplicationThread thread, long startSeq) {
      ...
    }
    

    《 完结》

    喜欢的点个小红心

    相关文章

      网友评论

          本文标题:应用的启动流程分析

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