Activity启动流程源码解析上(8.0)

上个小节我们学习了跨进程通信,相信大家对于AIDL已经很熟悉了,今天我们趁热打铁,一起来看下Activity的启动流程。对AIDL还不了解的小伙伴请先移步至上小节文章:https://www.jianshu.com/p/1f1472991d72

我们知道,Activity有两种常见的启动方式,一种是在桌面点击应用图标,进入应用程序的主界面,另一种方式就是用户在应用程序的Activity点击某个按钮或者其他跳转到另一个Activity。我先简单说下Android系统的启动顺序:init进程 -> Zygote进程 -> SystemServer进程 -> 应用程序进程。我们大家都知道,Android系统是基于Linux内核的,所以首先启动Linux的init进程,接着由init进程启动Zygote(受精卵)进程。Zygote进程可以说是所有Android进程的父进程,后续启动的SystemServer进程和各种应用程序进程都是由Zygote进程fork出来的。而我们的手机桌面就是Android系统启动的第一个应用程序进程,上述两种Activity的启动方式底层都是通过IPC机制来实现的。

我先举个栗子来考考大家,当我们在应用程序中由ActivityA跳转到ActivityB,两者的生命周期方法执行的顺序是怎样的呢?答案是:ActivityA onPause -> ActivityB onCreate -> ActivityB onStart -> ActivityB onResume -> ActivityA onStop。这个也是面试官经常问的一个小知识点,如果你答错的话可要好好补习下基础知识啦哈哈哈,在这里我们就以两者的生命周期方法执行顺序为引线,来从源码的角度看下Activity的启动流程。

下面的代码我们再熟悉不过了:

    Intent intent = new Intent(MainActivity.this,OtherActivity.class);
    startActivity(intent);

跟进去startActivity方法看下:

    #Activity

    @Override
    public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }

    -- >

    @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            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);
        }
    }

    -->
    
    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
        startActivityForResult(intent, requestCode, null);
    }

    -->

    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());
            }
            if (requestCode >= 0) {
               
                mStartedActivity = true;
            }

            cancelInputsAndStartExitTransition(options);
            // TODO Consider clearing/flushing other event sources and events for child windows.
        } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

可以看到方法最终会调用到mInstrumentation.execStartActivity方法,我们接着跟:

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        Uri referrer = target != null ? target.onProvideReferrer() : null;
        if (referrer != null) {
            intent.putExtra(Intent.EXTRA_REFERRER, referrer);
        }
       
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);

            // 重点
            int result = ActivityManager.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;
    }

上述代码有删减,我们可以看到方法中调用到 ActivityManager.getService().startActivity方法。ActivityManager.getService()方法获取到的是什么呢?我们跟进去看下:

    # ActivityManager
    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

接着看下IActivityManagerSingleton的定义:

    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

IActivityManagerSingleton的get方法直接将am返回出去了,am又是什么呢?可以看到am是通过IActivityManager.Stub.asInterface(b); 获取到的,am所属类型为 IActivityManager 。看到这里大家有没有一种似曾相识的感觉?AIDL,对的!我们的应用程序就属于客户端进程,而SystemServer进程则是服务端进程,在IActivityManager 接口中定义了我们应用程序进程到SystemServer进程单向通信需要调用的各种方法。SystemServer进程中对应的Binder实现类就是ActivityManagerService(简称AMS),AMS中的方法都是运行在服务端的Binder线程池中。SystemServer进程到我们的应用进程单向通信的接口为IApplicationThread,对应的Binder实现类为ApplicationThread,大家翻看源码就可以发现,ApplicationThread是ActivityThread的内部类,同样ApplicationThread类中的方法都是运行在客户端的Binder线程池中,正因为如此,所以我们收到服务端进程的指令后需要借助Handler,也就是mH(Handler)切换到UI线程进行处理。

我们回过头接着看,代码中调用ActivityManager.getService().startActivity方法,也就是调用到AMS的startActivity方法,我们跟进去ActivityManagerService这个类去看下:

    @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());
    }

可以看到方法中直接调用了startActivityAsUser方法,我们接着跟下去,接下来的代码量有点多,做好准备哈哈。

    #ActivityManagerService
    @Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
        enforceNotIsolatedCaller("startActivity");
        userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                userId, false, ALLOW_FULL_ONLY, "startActivity", null);
        // TODO: Switch to user app stacks here.
        return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, bOptions, false, userId, null, null,
                "startActivityAsUser");
    }

    -->

    #ActivityStarter             //代码适当删减
    final int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, WaitResult outResult,
            Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
            IActivityContainer iContainer, TaskRecord inTask, String reason) {

            final ActivityRecord[] outRecord = new ActivityRecord[1];
            //重点
            int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
                    aInfo, rInfo, voiceSession, voiceInteractor,
                    resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                    options, ignoreTargetSecurity, componentSpecified, outRecord, container,
                    inTask, reason);

            Binder.restoreCallingIdentity(origId);

    }

    -->

   #ActivityStarter
   int startActivityLocked(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,
            ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
            ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
            TaskRecord inTask, String reason) {

        if (TextUtils.isEmpty(reason)) {
            throw new IllegalArgumentException("Need to specify a reason.");
        }
        mLastStartReason = reason;
        mLastStartActivityTimeMs = System.currentTimeMillis();
        mLastStartActivityRecord[0] = null;
        //重点
        mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
                aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
                callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
                container, inTask);

        if (outActivity != null) {
            // mLastStartActivityRecord[0] is set in the call to startActivity above.
            outActivity[0] = mLastStartActivityRecord[0];
        }
        return mLastStartActivityResult;
    }

    -->
 
    #ActivityStarter
    /** DO NOT call this method directly. Use {@link #startActivityLocked} instead. */
    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,
            ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
            ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
            TaskRecord inTask) {
    //重点
    return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
                options, inTask, outActivity);
    }

    -->

    #ActivityStarter
    private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {
        int result = START_CANCELED;
        try {
            mService.mWindowManager.deferSurfaceLayout();
            //重点
            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, outActivity);
        } finally {
            // If we are not able to proceed, disassociate the activity from the task. Leaving an
            // activity in an incomplete state can lead to issues, such as performing operations
            // without a window container.
            if (!ActivityManager.isStartResultSuccessful(result)
                    && mStartActivity.getTask() != null) {
                mStartActivity.getTask().removeActivity(mStartActivity);
            }
            mService.mWindowManager.continueSurfaceLayout();
        }

        postStartActivityProcessing(r, result, mSupervisor.getLastStack().mStackId,  mSourceRecord,
                mTargetStack);

        return result;
    }

    -->

    #ActivityStarter
    // 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) {
    //重点
    mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                        mOptions);
    }

好吧,终于调用到ActivityStackSupervisor类了,我们接着跟:

   #ActivityStackSupervisor
   boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
        if (targetStack != null && isFocusedStack(targetStack)) {
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }
        final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
        if (r == null || r.state != RESUMED) {
            //重点   在这里r可以理解为将要执行onPause方法的上一个Activity
            mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
        } else if (r.state == RESUMED) {
            // Kick off any lingering app transitions form the MoveTaskToFront operation.
            mFocusedStack.executeAppTransition(targetOptions);
        }
        return false;
    }

    -->

    #ActivityStack
    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        if (mStackSupervisor.inResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }

        boolean result = false;
        try {
            // Protect against recursion.
            mStackSupervisor.inResumeTopActivity = true;
            // 重点
            result = resumeTopActivityInnerLocked(prev, options);
        } finally {
            mStackSupervisor.inResumeTopActivity = false;
        }
      
        return result;
    }

    -->

    #ActivityStack
    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
   
       if (mResumedActivity != null) {
            //重点 mResumedActivity 指的就是将要执行onPause方法的上一个Activity,这里可以说是onPause方法执行的入口
            pausing |= startPausingLocked(userLeaving, false, next, false);
        }
    }

我跟跟跟:

    #ActivityStack
    /**
     * Start pausing the currently resumed activity.  It is an error to call this if there
     * is already an activity being paused or there is no resumed activity
     * @return Returns true if an activity now is in the PAUSING state, and we are waiting for
     * it to tell us when it is done.
     */
    final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
            ActivityRecord resuming, boolean pauseImmediately) {

         ActivityRecord prev = mResumedActivity;
         mResumedActivity = null;

           try {
                EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
                        prev.userId, System.identityHashCode(prev),
                        prev.shortComponentName);
                mService.updateUsageStats(prev, false);
                prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                        userLeaving, prev.configChangeFlags, pauseImmediately);
            } catch (Exception e) {
                // Ignore exception, if process died other code will cleanup.
                Slog.w(TAG, "Exception thrown during pause", e);
                mPausingActivity = null;
                mLastPausedActivity = null;
                mLastNoHistoryActivity = null;
            }

我们先看下注解,大概意思就是说这个方法是用来执行上个Activity的onPause方法的,如果上个Activity在此之前已经为paused状态的话,调用这个方法会出错。在调用到try代码块中的prev.app.thread.schedulePauseActivity方法后,会直接return true,然后等待客户端进程告诉我们结果。然后在resumeTopActivityInnerLocked方法中由于startPausingLocked方法的返回值为true,会使得pausing 的值为true,后续进入一个if语句直接return掉了,代码不会继续向下执行。至于调用到try代码块中的prev.app.thread.schedulePauseActivity方法后,为什么会直接return true,大家看下代码细节就会明白了,这里就不过细分析了。在上述方法中有一个重要的点需要我们注意下,那就是try代码块执行前的上述两行代码,可以看到,代码中首先将mResumedActivity赋值给prev,接着将 mResumedActivity 置为null。为什么要这么操作呢?答案就是后续的IPC过程中会再次调用到ActivityStack类的resumeTopActivityInnerLocked方法,这个时候由于mResumedActivity已经为null,程序不会进入到if语句块再次执行startPausingLocked方法,而是会接着向下执行。

我们可以看到,在上述代码中,最终会调用到prev.app.thread.schedulePauseActivity方法,也就是调用到客户端进程ApplicationThread类的schedulePauseActivity方法。不知道大家在这里有没有想过,我们的应用程序客户端进程是怎么将ApplicationThread注册到SystemServer进程的呢?答案当然是在我们的应用程序客户端进程启动的时候啦,怎么你不信?我们上代码哈哈:

我们都知道,我们的应用程序进程启动的起点就是它的ActivityThread类的main方法,下面我们一起来看下(代码有删减):

    public static void main(String[] args) {
        
        // 1.
        Looper.prepareMainLooper();
        // 2.
        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        // 3.
        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

我们可以看到,代码中首先调用了 Looper.prepareMainLooper();接着创建了一个当前ActivityThread 类的实例对象,调用它的attach方法,最后调用到Looper.loop();方法进行循环。重点就在这个attach方法,我们跟进去看下:

    private void attach(boolean system) {
            final IActivityManager mgr = ActivityManager.getService();
            try {
                // 重点
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
    }

上述代码有所删减,我们可以看到attach方法中最终会调用到 mgr.attachApplication方法,将mAppThread作为参数,传递过去,mAppThread是什么呢?我们看下:

    final ApplicationThread mAppThread = new ApplicationThread();

哈哈,可以看到mAppThread 就是ApplicationThread 类的一个实例对象,也就是说attach方法中调用到mgr.attachApplication方法,将ApplicationThread 类的实例对象mAppThread 作为参数传递过去。通过mgr的定义我们可以知道,这是从客户端进程到SystemServer进程的一次IPC,所以最终会调用到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);
        }
    }

    -->

    private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
        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;

可以看到attachApplicationLocked方法中调用到app.makeActive方法(app类型为ProcessRecord),将我们ApplicationThread 类的实例对象作为第一个参数传递了过去,我们跟进去makeActive方法看下:

    public void makeActive(IApplicationThread _thread, ProcessStatsService tracker) {
        if (thread == null) {
            final ProcessState origBase = baseProcessTracker;
            if (origBase != null) {
                origBase.setState(ProcessStats.STATE_NOTHING,
                        tracker.getMemFactorLocked(), SystemClock.uptimeMillis(), pkgList);
                origBase.makeInactive();
            }
            baseProcessTracker = tracker.getProcessStateLocked(info.packageName, uid,
                    info.versionCode, processName);
            baseProcessTracker.makeActive();
            for (int i=0; i<pkgList.size(); i++) {
                ProcessStats.ProcessStateHolder holder = pkgList.valueAt(i);
                if (holder.state != null && holder.state != origBase) {
                    holder.state.makeInactive();
                }
                holder.state = tracker.getProcessStateLocked(pkgList.keyAt(i), uid,
                        info.versionCode, processName);
                if (holder.state != baseProcessTracker) {
                    holder.state.makeActive();
                }
            }
        }
        thread = _thread;
    }

可以看到在makeActive方法的最后,将我们ApplicationThread 类的实例对象赋值给app(ProcessRecord类型)的成员变量thread ,这样就完成了注册。

好了,我们回过头接着看,在上述startPausingLocked方法中,最终调用到prev.app.thread.schedulePauseActivity方法,也就是调用到客户端进程ApplicationThread类的schedulePauseActivity方法,我们跟过去看下:

    public final void schedulePauseActivity(IBinder token, boolean finished,
                boolean userLeaving, int configChanges, boolean dontReport) {
            int seq = getLifecycleSeq();
            if (DEBUG_ORDER) Slog.d(TAG, "pauseActivity " + ActivityThread.this
                    + " operation received seq: " + seq);
            sendMessage(
                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
                    token,
                    (userLeaving ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0),
                    configChanges,
                    seq);
    }

可以看到客户端进程ApplicationThread类的schedulePauseActivity方法中直接调用了sendMessage方法,接着跟:

    private void sendMessage(int what, Object obj, int arg1, int arg2, int seq) {
        if (DEBUG_MESSAGES) Slog.v(
                TAG, "SCHEDULE " + mH.codeToString(what) + " arg1=" + arg1 + " arg2=" + arg2 +
                        "seq= " + seq);
        Message msg = Message.obtain();
        msg.what = what;
        SomeArgs args = SomeArgs.obtain();
        args.arg1 = obj;
        args.argi1 = arg1;
        args.argi2 = arg2;
        args.argi3 = seq;
        msg.obj = args;
        mH.sendMessage(msg);
    }

可以看到sendMessage方法中直接调用mH(Handler)的sendMessage方法发送了一条消息,大家想下,这里为什么需要借助Handler来发送一条消息呢?答案就是ApplicationThread类的schedulePauseActivity方法是执行在客户端进程的Binder线程池中,需要切换至UI线程,肯定要借助伟大的Handler啦。下面我们到mH的handleMessage方法中看下:

    public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
                case RELAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;
                    handleRelaunchActivity(r);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;

                //重点
                case PAUSE_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
                    SomeArgs args = (SomeArgs) msg.obj;
                    handlePauseActivity((IBinder) args.arg1, false,
                            (args.argi1 & USER_LEAVING) != 0, args.argi2,
                            (args.argi1 & DONT_REPORT) != 0, args.argi3);
                    maybeSnapshot();
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
                case PAUSE_ACTIVITY_FINISHING: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
                    SomeArgs args = (SomeArgs) msg.obj;
                    handlePauseActivity((IBinder) args.arg1, true, (args.argi1 & USER_LEAVING) != 0,
                            args.argi2, (args.argi1 & DONT_REPORT) != 0, args.argi3);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
                case STOP_ACTIVITY_SHOW: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
                    SomeArgs args = (SomeArgs) msg.obj;
                    handleStopActivity((IBinder) args.arg1, true, args.argi2, args.argi3);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
                case STOP_ACTIVITY_HIDE: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
                    SomeArgs args = (SomeArgs) msg.obj;
                    handleStopActivity((IBinder) args.arg1, false, args.argi2, args.argi3);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;

                ......

可以看到在 case PAUSE_ACTIVITY 语句段调用了handlePauseActivity方法,这个就是用来执行上个Activity的onPause方法的入口,我们跟进去:

    private void handlePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport, int seq) {
        ActivityClientRecord r = mActivities.get(token);
          
            //1.
            performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");
       
            if (!dontReport) {
                try {
                    //2.
                    ActivityManager.getService().activityPaused(token);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            }
            mSomeActivitiesChanged = true;
        }
    }

在这里我们先来看下标注 1 处,调用到performPauseActivity方法,还等什么,肯定跟进去啊哈哈:

   final Bundle performPauseActivity(IBinder token, boolean finished,
            boolean saveState, String reason) {
        ActivityClientRecord r = mActivities.get(token);
        return r != null ? performPauseActivity(r, finished, saveState, reason) : null;
    }

    -->
    
    final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
            boolean saveState, String reason) {
       
        if (!r.activity.mFinished && saveState) {
            //1.
            callCallActivityOnSaveInstanceState(r);
        }
         //2.
        performPauseActivityIfNeeded(r, reason);
    }

标注 1 处的方法最终会回调Activity的onSaveInstanceState方法,我们一般情况下会重写onSaveInstanceState方法来进行保存数据,大家感兴趣的可以点开源码看下,这里就不展开分析了,我们一起来看下 2 处的performPauseActivityIfNeeded方法,跟进去:

   private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
        try {
            r.activity.mCalled = false;
            //重点  跟进去
            mInstrumentation.callActivityOnPause(r.activity);
            }
        } catch (SuperNotCalledException e) {
            throw e;
        } 
    }

    -->

    #Instrumentation
    public void callActivityOnPause(Activity activity) {
        activity.performPause();
    }

    -->

    #Activity
    final void performPause() {
        mDoReportFullyDrawn = false;
        mFragments.dispatchPause();
        mCalled = false;
        //哈哈哈哈哈哈哈哈哈找到了!
        onPause();
        mResumed = false;
        if (!mCalled && getApplicationInfo().targetSdkVersion
                >= android.os.Build.VERSION_CODES.GINGERBREAD) {
            throw new SuperNotCalledException(
                    "Activity " + mComponent.toShortString() +
                    " did not call through to super.onPause()");
        }
        mResumed = false;
    }

最终终于在performPause方法中找到Activity的onPause方法回调了!容老夫大笑两分钟先哈哈哈。

好了,让我们回到handlePauseActivity方法接着看下 2 处代码,可以看到 2 处调用到ActivityManager.getService().activityPaused方法,这是一次由客户端进程向SystemServer进程发起的单向IPC,最终会调用到AMS的activityPaused方法。

欲知后事如何,请看下回分解,时间不早了,我要先洗洗睡了,明早还要早起上班。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343