Android10客户端事务管理ClientLifecycleManager源码解析

2022-10-11 17:52:31
目录
正文ClientLifecycleManagerClientTransactionTransactionExecutorexecuteLifecycleState

正文

在Android>

生命周期管理是google在Android 9才引入的设计,在Android 9之前,activity 存在生命周期的概念,但并无生命周期管理这一说法。为了方便生命周期的切换以及相关业务的管理,google采用了事务的思想,将生命周期抽象为客户端事务的一部分来统一管理。下图是客户端事务管理完整的UML图:

相关类说明:

    ClientLifecycleManager: 客户端事务管理类,包括且不限于处理Activity生命周期转换事务,同时也包括 与客户端相关的其他事务处理。ClientTransaction:事务集类,一个事务集可以存放一系列Callback事务及一个生命周期事务。TransactionExecutor:事务执行器,让事务以正确的顺序执行。BaseClientRequest :事务的抽象类,定义了preExecuteexecutepostExecute三个接口,分别代表事务执行前、执行中、执行后三个阶段的回调方法。ActivityLifecycleItem:abstract class,Activity生命周期事务类,其子类有DestroyActivityItemPauseActivityItemStopActivityItemResumeActivityItem,表示具体的activity生命周期转换事务。ClientTransactionItem:abstract class,客户端事务类,ActivityLifecycleItem是它的子类之一。除此之外,还有如下内置的客户端事务:
    Transaction NameDesc
    ConfigurationChangeItemApp configuration 改变的消息
    WindowVisibilityItemWindow可见性发生改变的消息
    MoveToDisplayItemActivity 移动到不同的显示设备的消息
    MultiWindowModeChangeItem多窗口模式改变的消息
    ActivityConfigurationChangeItemActivity configuration 改变的回调
    PipModeChangeItem画中画模式改变的消息
    ActivityResultItemActivity result的回调
    NewIntentItemNew intent消息
    TopResumedActivityChangeItemTop resumed activity 改变的回调
    ActivityRelaunchItem重启Activity的回调
    LaunchActivityItem请求启动一个Activity

    ClientLifecycleManager

    ClientLifecycleManagerActivityTaskManagerService中初始化了唯一的实例,所有的事务操作,必须通过ATMS中的实例来发起。如:>mService.getLifecycleManager().scheduleTransaction(clientTransaction);。

    ClientLifecycleManager的源码如下:

    class ClientLifecycleManager {
        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();
            }
        }
        void scheduleTransaction(@NonNull IApplicationThread client, @NonNull IBinder activityToken,
                @NonNull ActivityLifecycleItem stateRequest) throws RemoteException {
            final ClientTransaction clientTransaction = transactionWithState(client, activityToken,
                    stateRequest);
            scheduleTransaction(clientTransaction);
        }
        void scheduleTransaction(@NonNull IApplicationThread client, @NonNull IBinder activityToken,
                @NonNull ClientTransactionItem callback) throws RemoteException {
            final ClientTransaction clientTransaction = transactionWithCallback(client, activityToken,
                    callback);
            scheduleTransaction(clientTransaction);
        }
        void scheduleTransaction(@NonNull IApplicationThread client,
                @NonNull ClientTransactionItem callback) throws RemoteException {
            final ClientTransaction clientTransaction = transactionWithCallback(client,
                    null /* activityToken */, callback);
            scheduleTransaction(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;
        }
        private static ClientTransaction transactionWithCallback(@NonNull IApplicationThread client,
                IBinder activityToken, @NonNull ClientTransactionItem callback) {
            final ClientTransaction clientTransaction = ClientTransaction.obtain(client, activityToken);
            clientTransaction.addCallback(callback);
            return clientTransaction;
        }
    }
    

    可以看到,ClientLifecycleManager对外暴露了三种事务调度方法:一是 直接调度一个事务集(ClientTransaction);二是调度一个 Lifecycle事务; 三是调用一个Callback事务(ps:除LifeCycle以外的事务,都属于Callback事务)。实际上,无论是Lifecycle事务还是Callback事务,它们都被封装成了事务集的形式,并通过ClientTransaction中的schedule方法去进一步处理。

    ClientTransaction

    ClientTransaction里的schedule方法非常简单,代码如下所示:

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

    上述代码片段中的mClient到底指的是什么?

    从源码的角度来看,mClient 是 ApplicationThread的一个实例。而 ApplicationThread 是ActivityThread的一个内部类,作为ActivityThread 与外部沟通的桥梁。所有的事务集最终都会被派发到ActivityThread中统一处理。

    ActivityThread.java
       void scheduleTransaction(ClientTransaction transaction) {
            transaction.preExecute(this);
            sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
        }
    

    ActivityThread里首先调用了ClientTransaction中的preExecute方法,代码片段如下:

        public void preExecute(android.app.ClientTransactionHandler clientTransactionHandler) {
            if (mActivityCallbacks != null) {
                final int size = mActivityCallbacks.size();
                for (int i = 0; i < size; ++i) {
                    mActivityCallbacks.get(i).preExecute(clientTransactionHandler, mActivityToken);
                }
            }
            if (mLifecycleStateRequest != null) {
                mLifecycleStateRequest.preExecute(clientTransactionHandler, mActivityToken);
            }
        }
    

    可以看到,ClientTransaction先调用了 所有注册的Callback事务的preExecute方法,然后调用了唯一的LifeCycle事务的preExecute方法。

    在完成所有事务的preExecute逻辑后,ActivityThread发送了一条ActivityThread.H.EXECUTE_TRANSACTION的message,内容如下:

       mTransactionExecutor.execute(transaction);
       if (isSystem()) {
          transaction.recycle();
       }
    

    接下来由TransactionExecutor负责后续的逻辑处理。

    TransactionExecutor

     public void execute(ClientTransaction transaction) {
            final IBinder token = transaction.getActivityToken();
            if (token != null) {
                final Map<IBinder, ClientTransactionItem> activitiesToBeDestroyed =
                        mTransactionHandler.getActivitiesToBeDestroyed();
                final ClientTransactionItem destroyItem = activitiesToBeDestroyed.get(token);
                if (destroyItem != null) {
                    if (transaction.getLifecycleStateRequest() == destroyItem) {
                        // It is going to execute the transaction that will destroy activity with the
                        // token, so the corresponding to-be-destroyed record can be removed.
                        activitiesToBeDestroyed.remove(token);
                    }
                    if (mTransactionHandler.getActivityClient(token) == null) {
                        // The activity has not been created but has been requested to destroy, so all
                        // transactions for the token are just like being cancelled.
                        Slog.w(TAG, tId(transaction) + "Skip pre-destroyed transaction:\n"
                                + transactionToString(transaction, mTransactionHandler));
                        return;
                    }
                }
            }
            executeCallbacks(transaction);
            executeLifecycleState(transaction);
            mPendingActions.clear();
        }
    

    execute中有一段对DestroyActivityItem特殊处理的逻辑,不太重要,我们忽略它。

    我们分别来看一下executeCallbacksexecuteLifecycleState两个方法。

     public void executeCallbacks(ClientTransaction transaction) {
            final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
            if (callbacks == null || callbacks.isEmpty()) {
                return;
            }
            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);
                if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Resolving callback: " + item);
                final int postExecutionState = item.getPostExecutionState();
                final int closestPreExecutionState = mHelper.getClosestPreExecutionState(r,
                        item.getPostExecutionState());
                if (closestPreExecutionState != UNDEFINED) {
                    cycleToPath(r, closestPreExecutionState, transaction);
                }
                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, transaction);
                }
            }
        }
    

    上述代码主要做了以下几件事:

      获取事务集的target lifecycle。获取事务集中最后一次Activity生命周期转换的Callback索引。遍历所有的Callback事务。获取Callback事务的结束状态值,如结束状态值为onResume,检查Activity当前状态,判断当前的就近状态(onStart/onPause),并将activity转换到就近状态。执行Callback事务的execute和postExecute逻辑。跳过最后一个状态转换,改为通过显式状态变换去执行。

      google这段逻辑写的极为繁杂啰嗦,让人吐槽的点实在太多了,但还是要在此讲一下它是怎么设计的,源码中又哪里糟点。

      首先是事务集的target lifecycle,它指的是事务集中唯一的Lifecycle事务(如果存在的话)的状态,表示事务集执行完毕后,Activity最终的生命周期状态。

      第二点,事务集中最后一次Activity生命周期转换的Callback索引,这句话是什么含义呢?

      Callback事务中有这么一个方法,getPostExecutionState,它表示在当前Callback事务执行完毕后Activity所需处于的生命周期状态,为方便叙述,下文称其为结束状态。将Callback事务列表从后向前遍历,如果当前事务存在结束状态(即getPostExecutionState的值不为UNDEFINED),且与上一个结束状态相同,记录下此时事务在列表中的索引值,直到当前结束状态与上一个状态不同为止。此时,上一个事务的索引值即为事务集中最后一次Activity生命周期转换的Callback索引。

      假如某事务集有这样一组Callback事务——ConfigurationChangeItem、NewIntentItem、ConfigurationChangeItem、NewIntentItem。其中ConfigurationChangeItem的结束状态为UNDEFINED,NewIntentItem的结束状态为ON_RESUME。

      我们从后向前开始遍历:

        最后一个事务为 NewIntentItem,结束状态为ON_RESUME,记录下此时的索引值 3。倒数第二个事务为 ConfigurationChangeItem,不存在结束状态,跳过。倒数第三个事务为 NewIntentItem,结束状态为ON_RESUME,上一个结束状态同样也是 ON_RESUME,更新索引值 为 1。倒数第四个事务为 ConfigurationChangeItem,不存在结束状态,跳过。

        因此,此事务集中最后一次Activity生命周期转换的Callback索引 为1。至于这个索引值有什么意义呢,待会再解释。

        然而,这段设计中还是有几点需要吐槽一下:

          google官方在注释中举例的 事务是 Configuration - ActivityResult - Configuration - ActivityResult , 并且说明ActivityResult 的结束状态为RESUMED。让我们看看ActivityResultItem的源码:
          public class ActivityResultItem extends ClientTransactionItem {
              @UnsupportedAppUsage
              private List<ResultInfo> mResultInfoList;
              /* TODO(b/78294732)
              @Override
              public int getPostExecutionState() {
                  return ON_RESUME;
              }*/
          }
          

          Excuse me? TODO state!! 实际上,这个TODO 一直拖到android 13 才被加上,en~~~~。

            设计归设计,到android13 为止,framework里从来没有过一个事务集里绑定多个Callback事务的用法,所以 这段逻辑设计的并没有什么用。

            第四点,如果Callback事务的结束状态为ON_RESUME,则判断当前Activity状态是更靠近ON_START状态还是ON_PAUSE状态,并将activity状态转换到就近状态(ON_START or ON_PAUSE)。

            这里判断当前Activity状态更靠近ON_START还是ON_PAUSE,采用的是路径长度比较法。framework中为Activity定义了九种状态,具体如下:

                public static final int UNDEFINED = -1;
                public static final int PRE_ON_CREATE = 0;
                public static final int ON_CREATE = 1;
                public static final int ON_START = 2;
                public static final int ON_RESUME = 3;
                public static final int ON_PAUSE = 4;
                public static final int ON_STOP = 5;
                public static final int ON_DESTROY = 6;
            

            状态之间的转换路径如下表所示:

            上表中置灰的单元格,表示不存在或禁止的状态转换,而单元格中A ~ B 这种写法 表示 从 A到 B状态之间的中间所有状态,如: start 状态为 PRE_CREATE , finish 状态为 DESTROY ,在上表中状态转换路径为 create ~ destroy,表示 activity从 PRE_CREATE 状态转换到 DESTROY 状态,需要经历 create、start 、 resume 、pause 、stop 、 detroy ,即create到destroy之间所有的生命周期变换的过程。同时,我们也称 create~destroy 是 PRE_CREATE到DESTROY状态路径,它的路径长度为6。

            如何判断当前生命周期是更靠近ON_START还是ON_PAUSE?我们举个例子来看一下,假如当前的生命周期为ON_STOP,由上述状态路径表可知,从ON_STOP状态转换到ON_START状态的路径为restart、start,长度为2;而由ON_STOP状态转换到ON_PAUSE状态的路径为restart、start~pause,长度为4。因此,当前activity的状态更靠近ON_START。

            在路径长度算法的代码里,google给凡是路径中含有destroy状态的长度,赋予了一段惩罚长度,让它的长度增加了10,具体代码如下:

              public int getClosestOfStates(ActivityClientRecord r, int[] finalStates) {
                    if (finalStates == null || finalStates.length == 0) {
                        return UNDEFINED;
                    }
                    final int currentState = r.getLifecycleState();
                    int closestState = UNDEFINED;
                    for (int i = 0, shortestPath = Integer.MAX_VALUE, pathLength; i < finalStates.length; i++) {
                        getLifecyclePath(currentState, finalStates[i], false /* excludeLastState */);
                        pathLength = mLifecycleSequence.size();
                        if (pathInvolvesDestruction(mLifecycleSequence)) {
            		//路径中含有destroy状态,增加惩罚长度
                            pathLength += DESTRUCTION_PENALTY;
                        }
                        if (shortestPath > pathLength) {
                            shortestPath = pathLength;
                            closestState = finalStates[i];
                        }
                    }
                    return closestState;
                }
            

            然而我们可以看一下表格中finish state为 START 和 PAUSE的两列,所有的路径中都不包含 destroy 状态,所以这个惩罚长度的意义何在?

            第五步开始,正式执行 事务的execute和postExecute逻辑。这里要谈一下,为什么执行结束状态为 ON_RESUME的事务时,先要在第四步将 状态切换到 ON_START 或 ON_RESUME后,然后才开始去执行事务的逻辑呢?

            在Android 10中,结束状态为 ON_RESUME 的事务只有 NewIntentItem,其 excute 方法代码片段如下:

            NewIntentItem.java
                public void execute(ClientTransactionHandler client, ActivityClientRecord r,
                        PendingTransactionActions pendingActions) {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityNewIntent");
                    client.handleNewIntent(r, mIntents);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                }
            

            它最终会调用到 activity的performNewIntent方法。

            可以看到在这个过程中并没有涉及到生命周期状态的转换。因此,google这段逻辑的意图是:在执行最终状态为ON_RESUME的事务时,先将activity生命周期状态转换到ON_RESUME的临近状态,即ON_START或ON_PAUSE状态,然后再去执行事务,最后在事务执行完毕后,将activity的状态真正地切换到ON_RESUME。

            第六步,跳过最后一个状态转换,改为通过显式状态变换去执行。

            这里做了一个判断,如果事务组最后一次最终状态与事务集的生命周期状态相同,跳过此事务的最终状态的转换,改由 LifeCycle事务去执行状态转换。

            然而,我们来看这样一组事务,ConfigurationChangeItem、NewIntentItem、ConfigurationChangeItem、NewIntentItem,虽然实际编码中并不会写出这样一组事务,但仍可以用来吐槽一下google的这段代码逻辑:

            由第二步可知,上述的的事务组最后一次activity状态转换的Callback索引为 1。

            final boolean shouldExcludeLastTransition =
                                    i == lastCallbackRequestingState && finalState == postExecutionState;
            cycleToPath(r, postExecutionState, shouldExcludeLastTransition, transaction);
            

            可以看到,在第二个事务,activity并不会切换到ON_RESUME状态。

            然而这段代码最大的问题是,这个判断并不能达成显式状态变换的目标,因为在第四个事务时 activity会被切换到ON_REUSME的目标状态。

            有读者可能会提出异议了,作者你举的这个例子是属于特例,代码中不可能这么写。 然而,如果不需要考虑这种特殊情况的话,第二步的索引值计算又有什么作用呢?

            executeLifecycleState

            这个方法是对事务集中的LifeCycle事务的处理,其代码具体如下:

              private void executeLifecycleState(ClientTransaction transaction) {
                  ...
                    // Cycle to the state right before the final requested state.
                    cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */, transaction);
                    // Execute the final transition with proper parameters.
                    lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
                    lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
                }
            

            可以看到,cycleToPath是将activity切换到目标生命周期状态的关键方法:

              private void cycleToPath(ActivityClientRecord r, int finish, boolean excludeLastState,
                        ClientTransaction transaction) {
                    final int start = r.getLifecycleState();
                    final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState);
                    performLifecycleSequence(r, path, transaction);
                }
            

            getLifecyclePath是获取状态路径的方法,关于状态路径在上文中已经有所介绍。

              private void performLifecycleSequence(ActivityClientRecord r, IntArray path,
                        ClientTransaction transaction) {
                    final int size = path.size();
                    for (int i = 0, state; i < size; i++) {
                        state = path.get(i);
                        switch (state) {
                            case ON_CREATE:
                                mTransactionHandler.handleLaunchActivity(r, mPendingActions,
                                        null /* customIntent */);
                                break;
                            case ON_START:
                                mTransactionHandler.handleStartActivity(r, mPendingActions,
                                        null /* activityOptions */);
                                break;
                            case ON_RESUME:
                                mTransactionHandler.handleResumeActivity(r, false /* finalStateRequest */,
                                        r.isForward, "LIFECYCLER_RESUME_ACTIVITY");
                                break;
                            case ON_PAUSE:
                                mTransactionHandler.handlePauseActivity(r, false /* finished */,
                                        false /* userLeaving */, 0 /* configChanges */, mPendingActions,
                                        "LIFECYCLER_PAUSE_ACTIVITY");
                                break;
                            case ON_STOP:
                                mTransactionHandler.handleStopActivity(r, 0 /* configChanges */,
                                        mPendingActions, false /* finalStateRequest */,
                                        "LIFECYCLER_STOP_ACTIVITY");
                                break;
                            case ON_DESTROY:
                                mTransactionHandler.handleDestroyActivity(r, false /* finishing */,
                                        0 /* configChanges */, false /* getNonConfigInstance */,
                                        "performLifecycleSequence. cycling to:" + path.get(size - 1));
                                break;
                            case ON_RESTART:
                                mTransactionHandler.performRestartActivity(r, false /* start */);
                                break;
                            default:
                                throw new IllegalArgumentException("Unexpected lifecycle state: " + state);
                        }
                    }
                }
            }
            

            获取到状态路径后,开始遍历路径,按顺序依次切换路径中的activity生命周期状态,直到到达目标状态为止。

            在达到目标路径后,会调用Lifecycle事务的excute方法。这里会再一次调用切换到目标状态的逻辑,不过实际状态切换时,源码里做了状态判重的操作,并不会造成任何不良的影响。

            以上就是Android10 客户端事务管理ClientLifecycleManager源码解析的详细内容,更多关于Android10 客户端事务管理的资料请关注易采站长站其它相关文章!