Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 078c4e77 authored by Chris Li's avatar Chris Li
Browse files

Synchronize window config updates (12/n)

Bundle multiple ClientTransactionItems to deliver at once.

Before, ClientTransaction is sent for every ClientTransactionItems. Now,
queueing the ClientTransactionItems into one ClienTransaction until
RootWindowContainer#performSurfacePlacementNoTrace to dispatch all at
once.

Bug: 260873529
Test: atest WmTests:ClientLifecycleManagerTests
Change-Id: Ia3deb127ddbc1655e4369416dfc16e944b2dc218
parent 70ce23b0
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1053,6 +1053,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
            mWindowManager = wm;
            mRootWindowContainer = wm.mRoot;
            mWindowOrganizerController.mTransitionController.setWindowManager(wm);
            mLifecycleManager.setWindowManager(wm);
            mTempConfig.setToDefaults();
            mTempConfig.setLocales(LocaleList.getDefault());
            mConfigurationSeq = mTempConfig.seq = 1;
+95 −12
Original line number Diff line number Diff line
@@ -22,7 +22,13 @@ import android.app.servertransaction.ActivityLifecycleItem;
import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.ClientTransactionItem;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.Slog;

import com.android.internal.annotations.VisibleForTesting;
import com.android.window.flags.Flags;

/**
 * Class that is able to combine multiple client lifecycle transition requests and/or callbacks,
@@ -31,8 +37,18 @@ import android.os.RemoteException;
 * @see ClientTransaction
 */
class ClientLifecycleManager {
    // TODO(lifecycler): Implement building transactions or global transaction.
    // TODO(lifecycler): Use object pools for transactions and transaction items.

    private static final String TAG = "ClientLifecycleManager";

    /** Mapping from client process binder to its pending transaction. */
    @VisibleForTesting
    final ArrayMap<IBinder, ClientTransaction> mPendingTransactions = new ArrayMap<>();

    private WindowManagerService mWms;

    void setWindowManager(@NonNull WindowManagerService wms) {
        mWms = wms;
    }

    /**
     * Schedules a transaction, which may consist of multiple callbacks and a lifecycle request.
@@ -82,7 +98,16 @@ class ClientLifecycleManager {
     */
    void scheduleTransactionItem(@NonNull IApplicationThread client,
            @NonNull ClientTransactionItem transactionItem) throws RemoteException {
        // TODO(b/260873529): queue the transaction items.
        // The behavior is different depending on the flag.
        // When flag is on, we wait until RootWindowContainer#performSurfacePlacementNoTrace to
        // dispatch all pending transactions at once.
        if (Flags.bundleClientTransactionFlag()) {
            final ClientTransaction clientTransaction = getOrCreatePendingTransaction(client);
            clientTransaction.addTransactionItem(transactionItem);

            onClientTransactionItemScheduledLocked(clientTransaction);
        } else {
            // TODO(b/260873529): cleanup after launch.
            final ClientTransaction clientTransaction = ClientTransaction.obtain(client);
            if (transactionItem.isActivityLifecycleItem()) {
                clientTransaction.setLifecycleStateRequest((ActivityLifecycleItem) transactionItem);
@@ -91,6 +116,7 @@ class ClientLifecycleManager {
            }
            scheduleTransaction(clientTransaction);
        }
    }

    /**
     * Schedules a single transaction item with a lifecycle request, delivery to client application.
@@ -100,10 +126,67 @@ class ClientLifecycleManager {
    void scheduleTransactionAndLifecycleItems(@NonNull IApplicationThread client,
            @NonNull ClientTransactionItem transactionItem,
            @NonNull ActivityLifecycleItem lifecycleItem) throws RemoteException {
        // TODO(b/260873529): replace with #scheduleTransactionItem after launch for cleanup.
        // The behavior is different depending on the flag.
        // When flag is on, we wait until RootWindowContainer#performSurfacePlacementNoTrace to
        // dispatch all pending transactions at once.
        if (Flags.bundleClientTransactionFlag()) {
            final ClientTransaction clientTransaction = getOrCreatePendingTransaction(client);
            clientTransaction.addTransactionItem(transactionItem);
            clientTransaction.addTransactionItem(lifecycleItem);

            onClientTransactionItemScheduledLocked(clientTransaction);
        } else {
            // TODO(b/260873529): cleanup after launch.
            final ClientTransaction clientTransaction = ClientTransaction.obtain(client);
            clientTransaction.addCallback(transactionItem);
            clientTransaction.setLifecycleStateRequest(lifecycleItem);
            scheduleTransaction(clientTransaction);
        }
    }

    /** Executes all the pending transactions. */
    void dispatchPendingTransactions() {
        final int size = mPendingTransactions.size();
        for (int i = 0; i < size; i++) {
            final ClientTransaction transaction = mPendingTransactions.valueAt(i);
            try {
                scheduleTransaction(transaction);
            } catch (RemoteException e) {
                Slog.e(TAG, "Failed to deliver transaction for " + transaction.getClient());
            }
        }
        mPendingTransactions.clear();
    }

    @NonNull
    private ClientTransaction getOrCreatePendingTransaction(@NonNull IApplicationThread client) {
        final IBinder clientBinder = client.asBinder();
        final ClientTransaction pendingTransaction = mPendingTransactions.get(clientBinder);
        if (pendingTransaction != null) {
            return pendingTransaction;
        }

        // Create new transaction if there is no existing.
        final ClientTransaction transaction = ClientTransaction.obtain(client);
        mPendingTransactions.put(clientBinder, transaction);
        return transaction;
    }

    /** Must only be called with WM lock. */
    private void onClientTransactionItemScheduledLocked(
            @NonNull ClientTransaction clientTransaction) throws RemoteException {
        // TODO(b/260873529): make sure WindowSurfacePlacer#requestTraversal is called before
        // ClientTransaction scheduled when needed.

        if (mWms != null && (mWms.mWindowPlacerLocked.isInLayout()
                || mWms.mWindowPlacerLocked.isTraversalScheduled())) {
            // The pending transactions will be dispatched when
            // RootWindowContainer#performSurfacePlacementNoTrace.
            return;
        }

        // Dispatch the pending transaction immediately.
        mPendingTransactions.remove(clientTransaction.getClient().asBinder());
        scheduleTransaction(clientTransaction);
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -842,6 +842,9 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
        handleResizingWindows();
        clearFrameChangingWindows();

        // Called after #handleResizingWindows to include WindowStateResizeItem if any.
        mWmService.mAtmService.getLifecycleManager().dispatchPendingTransactions();

        if (mWmService.mDisplayFrozen) {
            ProtoLog.v(WM_DEBUG_ORIENTATION,
                    "With display frozen, orientationChangeComplete=%b",
+33 −10
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityOptions;
import android.app.IApplicationThread;
import android.app.ResultInfo;
import android.app.WindowConfiguration;
import android.app.servertransaction.ActivityResultItem;
@@ -103,6 +104,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.server.am.HostingRecord;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.window.flags.Flags;

import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -1509,23 +1511,38 @@ class TaskFragment extends WindowContainer<WindowContainer> {
            }

            try {
                final ClientTransaction transaction = ClientTransaction.obtain(
                        next.app.getThread());
                final IApplicationThread appThread = next.app.getThread();
                final ClientTransaction transaction = Flags.bundleClientTransactionFlag()
                        ? null
                        : ClientTransaction.obtain(appThread);
                // Deliver all pending results.
                ArrayList<ResultInfo> a = next.results;
                final ArrayList<ResultInfo> a = next.results;
                if (a != null) {
                    final int size = a.size();
                    if (!next.finishing && size > 0) {
                        if (DEBUG_RESULTS) {
                            Slog.v(TAG_RESULTS, "Delivering results to " + next + ": " + a);
                        }
                        transaction.addCallback(ActivityResultItem.obtain(next.token, a));
                        final ActivityResultItem activityResultItem = ActivityResultItem.obtain(
                                next.token, a);
                        if (transaction == null) {
                            mAtmService.getLifecycleManager().scheduleTransactionItem(
                                    appThread, activityResultItem);
                        } else {
                            transaction.addCallback(activityResultItem);
                        }
                    }
                }

                if (next.newIntents != null) {
                    transaction.addCallback(
                            NewIntentItem.obtain(next.token, next.newIntents, true /* resume */));
                    final NewIntentItem newIntentItem = NewIntentItem.obtain(
                            next.token, next.newIntents, true /* resume */);
                    if (transaction == null) {
                        mAtmService.getLifecycleManager().scheduleTransactionItem(
                                appThread, newIntentItem);
                    } else {
                        transaction.addCallback(newIntentItem);
                    }
                }

                // Well the app will no longer be stopped.
@@ -1539,10 +1556,16 @@ class TaskFragment extends WindowContainer<WindowContainer> {
                final int topProcessState = mAtmService.mTopProcessState;
                next.app.setPendingUiCleanAndForceProcessStateUpTo(topProcessState);
                next.abortAndClearOptionsAnimation();
                transaction.setLifecycleStateRequest(
                        ResumeActivityItem.obtain(next.token, topProcessState,
                                dc.isNextTransitionForward(), next.shouldSendCompatFakeFocus()));
                final ResumeActivityItem resumeActivityItem = ResumeActivityItem.obtain(
                        next.token, topProcessState, dc.isNextTransitionForward(),
                        next.shouldSendCompatFakeFocus());
                if (transaction == null) {
                    mAtmService.getLifecycleManager().scheduleTransactionItem(
                            appThread, resumeActivityItem);
                } else {
                    transaction.setLifecycleStateRequest(resumeActivityItem);
                    mAtmService.getLifecycleManager().scheduleTransaction(transaction);
                }

                ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Resumed %s", next);
            } catch (Exception e) {
+4 −0
Original line number Diff line number Diff line
@@ -210,6 +210,10 @@ class WindowSurfacePlacer {
        return mInLayout;
    }

    boolean isTraversalScheduled() {
        return mTraversalScheduled;
    }

    void requestTraversal() {
        if (mTraversalScheduled) {
            return;
Loading