美文网首页
Activity启动源码分析(2)--Pause过程

Activity启动源码分析(2)--Pause过程

作者: 月止风溟 | 来源:发表于2019-10-07 23:00 被阅读0次

    前两篇的内容在这里。
    Activity启动源码分析--总篇
    Activity启动源码分析--预启动过程(1)

    1.目的

    这篇的话,会涉及到从Service到Client的通信,可以看到跨进程通信里,google的架构设计方式。
    看代码前先放图:


    Activity Pause过程

    2.源码

    上一篇讲到,预启动的最后两步,倒数第二部是将当前显示的Activity做pause操作。调用到了mStackSupervisor.pauseBackStacks(userLeaving, next, false)
    ActivityStackSupervisor

    /**
         * Pause all activities in either all of the stacks or just the back stacks.
         * @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving().
         * @param resuming The resuming activity.
         * @param dontWait The resuming activity isn't going to wait for all activities to be paused
         *                 before resuming.
         * @return true if any activity was paused as a result of this call.
         */
        boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming, boolean dontWait) {
            boolean someActivityPaused = false;
            for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
                final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
                for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                    final ActivityStack stack = display.getChildAt(stackNdx);
                    if (!isFocusedStack(stack) && stack.getResumedActivity() != null) {
                        if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
                                " mResumedActivity=" + stack.getResumedActivity());
                        someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
                                dontWait);
                    }
                }
            }
            return someActivityPaused;
        }
    

    它这边是直接调用了ActivityStack的startPausingLocked方法。
    ActivityStack

        final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
                ActivityRecord resuming, boolean pauseImmediately) {
            ...
            if (prev.app != null && prev.app.thread != null) {
                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
                try {
                    EventLogTags.writeAmPauseActivity(prev.userId, System.identityHashCode(prev),
                            prev.shortComponentName, "userLeaving=" + userLeaving);
                    mService.updateUsageStats(prev, false);
    
                    //mService是一个ActivityManagerService对象,它的getLifecycleManager方法返回一个ActivityManagerService对象。
                    mService.getLifecycleManager().scheduleTransaction(prev.app.thread, prev.appToken,
                            PauseActivityItem.obtain(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;
                }
            } else {
                mPausingActivity = null;
                mLastPausedActivity = null;
                mLastNoHistoryActivity = null;
            }
    
            // If we are not going to sleep, we want to ensure the device is
            // awake until the next activity is started.
            if (!uiSleeping && !mService.isSleepingOrShuttingDownLocked()) {
                mStackSupervisor.acquireLaunchWakelock();
            }
    
            if (mPausingActivity != null) {
                // Have the window manager pause its key dispatching until the new
                // activity has started.  If we're pausing the activity just because
                // the screen is being turned off and the UI is sleeping, don't interrupt
                // key dispatch; the same activity will pick it up again on wakeup.
                if (!uiSleeping) {
                    prev.pauseKeyDispatchingLocked();
                } else if (DEBUG_PAUSE) {
                     Slog.v(TAG_PAUSE, "Key dispatch not paused for screen off");
                }
    
                if (pauseImmediately) {
                    // If the caller said they don't want to wait for the pause, then complete
                    // the pause now.
                    completePauseLocked(false, resuming);
                    return false;
    
                } else {
                    schedulePauseTimeout(prev);
                    return true;
                }
    
            } else {
                // This activity failed to schedule the
                // pause, so just treat it as being paused now.
                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Activity not running, resuming next.");
                if (resuming == null) {
                    mStackSupervisor.resumeFocusedStackTopActivityLocked();
                }
                return false;
            }
        }
    

    ClientLifecycleManager

        //从上面传来了一个PauseActivityItem,它是ActivityLifecycleItem的子类
        void scheduleTransaction(@NonNull IApplicationThread client, @NonNull IBinder activityToken,
                @NonNull ActivityLifecycleItem stateRequest) throws RemoteException {
            final ClientTransaction clientTransaction = transactionWithState(client, activityToken,
                    stateRequest);
            scheduleTransaction(clientTransaction);
        }
    
        //将从上面传来的PauseActivityItem封装成了ClientTransaction
        private static ClientTransaction transactionWithState(@NonNull IApplicationThread client,
                @NonNull IBinder activityToken, @NonNull ActivityLifecycleItem stateRequest) {
            final ClientTransaction clientTransaction = ClientTransaction.obtain(client, activityToken);
            clientTransaction.setLifecycleStateRequest(stateRequest);
            return clientTransaction;
        }
    
        //这里通过binder的方式,让Client执行上面的ClientTransaction
        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();
            }
        }
    

    ClientTransaction

        public void schedule() throws RemoteException {
            mClient.scheduleTransaction(this);
        }
    

    这里的话,可以放一下总篇里总结的调用图。

    Client->Service
    其实从上面那一步,可以看出,已经从System_server进程回到了app进程。那么app对应的IApplicationThread的实体类,就是ApplicationThread。
    ApplicationThread
         public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
                ActivityThread.this.scheduleTransaction(transaction);
            }
    

    ActivityThread执行了scheduleTransaction方法。但是ActivityThread里没有scheduleTransaction的实现方法。那我们可以从它的父类ClientTransactionHandler里,找到这个方法的内容。
    ClientTransactionHandler

        /** Prepare and schedule transaction for execution. */
        void scheduleTransaction(ClientTransaction transaction) {
            transaction.preExecute(this);
            sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
        }
    
        abstract void sendMessage(int what, Object obj);
    

    sendMessage的实现方法又需要回到ActivityThread。
    ActivityThread

        private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
            if (DEBUG_MESSAGES) Slog.v(
                TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
                + ": " + arg1 + " / " + obj);
            Message msg = Message.obtain();
            msg.what = what;
            msg.obj = obj;
            msg.arg1 = arg1;
            msg.arg2 = arg2;
            if (async) {
                msg.setAsynchronous(true);
            }
            mH.sendMessage(msg);
        }
    

    mH是ActivityThread里的H类型的成员变量。mH可是一个神奇的Handler,这个可以之后详讲。

        class H extends Handler {
    
            public static final int EXECUTE_TRANSACTION = 159;
    
            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;
        }
    

    TransactionExecutor

    
        /**
         * Resolve transaction.
         * First all callbacks will be executed in the order they appear in the list. If a callback
         * requires a certain pre- or post-execution state, the client will be transitioned accordingly.
         * Then the client will cycle to the final lifecycle state if provided. Otherwise, it will
         * either remain in the initial state, or last state needed by a callback.
         */
        public void execute(ClientTransaction transaction) {
            final IBinder token = transaction.getActivityToken();
            log("Start resolving transaction for client: " + mTransactionHandler + ", token: " + token);
    
            //这里就执行Service传来的ClientTransaction里的callback。从前面看,pause时没有设置这个
            executeCallbacks(transaction);
    
            //这里就执行Service传来的ClientTransaction里的stateRequest。自然就是上面传来的PauseActivityItem
            executeLifecycleState(transaction);
            mPendingActions.clear();
            log("End resolving transaction");
        }
    
        /** Cycle through all states requested by callbacks and execute them at proper times. */
        @VisibleForTesting
        public void executeCallbacks(ClientTransaction transaction) {
            final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
            if (callbacks == null) {
                // No callbacks to execute, return early.
                return;
            }
            log("Resolving callbacks");
    
            final IBinder token = transaction.getActivityToken();
            ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
    
            // In case when post-execution state of the last callback matches the final state requested
            // for the activity in this transaction, we won't do the last transition here and do it when
            // moving to final state instead (because it may contain additional parameters from server).
            final ActivityLifecycleItem finalStateRequest = transaction.getLifecycleStateRequest();
            final int finalState = finalStateRequest != null ? finalStateRequest.getTargetState()
                    : UNDEFINED;
            // Index of the last callback that requests some post-execution state.
            final int lastCallbackRequestingState = lastCallbackRequestingState(transaction);
    
            final int size = callbacks.size();
            for (int i = 0; i < size; ++i) {
                final ClientTransactionItem item = callbacks.get(i);
                log("Resolving callback: " + item);
                final int postExecutionState = item.getPostExecutionState();
                final int closestPreExecutionState = mHelper.getClosestPreExecutionState(r,
                        item.getPostExecutionState());
                if (closestPreExecutionState != UNDEFINED) {
                    cycleToPath(r, closestPreExecutionState);
                }
    
                item.execute(mTransactionHandler, token, mPendingActions);
                item.postExecute(mTransactionHandler, token, mPendingActions);
                if (r == null) {
                    // Launch activity request will create an activity record.
                    r = mTransactionHandler.getActivityClient(token);
                }
    
                if (postExecutionState != UNDEFINED && r != null) {
                    // Skip the very last transition and perform it by explicit state request instead.
                    final boolean shouldExcludeLastTransition =
                            i == lastCallbackRequestingState && finalState == postExecutionState;
                    cycleToPath(r, postExecutionState, shouldExcludeLastTransition);
                }
            }
        }
    
        /** Transition to the final state if requested by the transaction. */
        private void executeLifecycleState(ClientTransaction transaction) {
            final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
            if (lifecycleItem == null) {
                // No lifecycle request, return early.
                return;
            }
            log("Resolving lifecycle state: " + lifecycleItem);
    
            final IBinder token = transaction.getActivityToken();
            final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
    
            if (r == null) {
                // Ignore requests for non-existent client records for now.
                return;
            }
    
            //这里就有意思了,这里避免了生命周期跳阶段执行。如只能从onCreate->onStart->onResume。而不能是onCreate->onResume
            // Cycle to the state right before the final requested state.
            cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */);
    
            //执行对应的lifecycleItem
            // Execute the final transition with proper parameters.
            lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
            lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
        }
    
    

    PauseActivityItem

        @Override
        public void execute(ClientTransactionHandler client, IBinder token,
                PendingTransactionActions pendingActions) {
            Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
            client.handlePauseActivity(token, mFinished, mUserLeaving, mConfigChanges, pendingActions,
                    "PAUSE_ACTIVITY_ITEM");
            Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
        }
    

    其实从ClientTransactionHandler这个名字我们就知道,需要回到ActivityThread里面去找handlePauseActivity这个方法了。

    ActivityThread

        @Override
        public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving,
                int configChanges, PendingTransactionActions pendingActions, String reason) {
            ActivityClientRecord r = mActivities.get(token);
            if (r != null) {
                if (userLeaving) {
                    performUserLeavingActivity(r);
                }
    
                r.activity.mConfigChangeFlags |= configChanges;
                performPauseActivity(r, finished, reason, pendingActions);
    
                // Make sure any pending writes are now committed.
                if (r.isPreHoneycomb()) {
                    QueuedWork.waitToFinish();
                }
                mSomeActivitiesChanged = true;
            }
        }
    
        private Bundle performPauseActivity(ActivityClientRecord r, boolean finished, String reason,
                PendingTransactionActions pendingActions) {
            if (r.paused) {
                if (r.activity.mFinished) {
                    // If we are finishing, we won't call onResume() in certain cases.
                    // So here we likewise don't want to call onPause() if the activity
                    // isn't resumed.
                    return null;
                }
                RuntimeException e = new RuntimeException(
                        "Performing pause of activity that is not resumed: "
                        + r.intent.getComponent().toShortString());
                Slog.e(TAG, e.getMessage(), e);
            }
            if (finished) {
                r.activity.mFinished = true;
            }
    
            // Pre-Honeycomb apps always save their state before pausing
            final boolean shouldSaveState = !r.activity.mFinished && r.isPreHoneycomb();
            if (shouldSaveState) {
                callActivityOnSaveInstanceState(r);
            }
    
            performPauseActivityIfNeeded(r, reason);
    
            // Notify any outstanding on paused listeners
            ArrayList<OnActivityPausedListener> listeners;
            synchronized (mOnPauseListeners) {
                listeners = mOnPauseListeners.remove(r.activity);
            }
            int size = (listeners != null ? listeners.size() : 0);
            for (int i = 0; i < size; i++) {
                listeners.get(i).onPaused(r.activity);
            }
    
            final Bundle oldState = pendingActions != null ? pendingActions.getOldState() : null;
            if (oldState != null) {
                // We need to keep around the original state, in case we need to be created again.
                // But we only do this for pre-Honeycomb apps, which always save their state when
                // pausing, so we can not have them save their state when restarting from a paused
                // state. For HC and later, we want to (and can) let the state be saved as the
                // normal part of stopping the activity.
                if (r.isPreHoneycomb()) {
                    r.state = oldState;
                }
            }
    
            return shouldSaveState ? r.state : null;
        }
    
        private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
            if (r.paused) {
                // You are already paused silly...
                return;
            }
    
            try {
                r.activity.mCalled = false;
                mInstrumentation.callActivityOnPause(r.activity);
                if (!r.activity.mCalled) {
                    throw new SuperNotCalledException("Activity " + safeToComponentShortString(r.intent)
                            + " did not call through to super.onPause()");
                }
            } catch (SuperNotCalledException e) {
                throw e;
            } catch (Exception e) {
                if (!mInstrumentation.onException(r.activity, e)) {
                    throw new RuntimeException("Unable to pause activity "
                            + safeToComponentShortString(r.intent) + ": " + e.toString(), e);
                }
            }
            r.setState(ON_PAUSE);
        }
    

    ActivityThread的handlePauseActivity->performPauseActivity->performPauseActivityIfNeeded。回到了Instrumentation。
    Instrumentation

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

    终于见到了performPause()。onPause的生命周期回调终于找到了出处。可喜可贺可喜可贺。

    参考文档:

    1. (Android 9.0)Activity启动流程源码分析
    2. Android源码解析之(十四)-->Activity启动流程
    3. ActivityStarter之startActivityUnchecked

    相关文章

      网友评论

          本文标题:Activity启动源码分析(2)--Pause过程

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