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

Commit 6e728461 authored by Chris Li's avatar Chris Li Committed by Android (Google) Code Review
Browse files

Merge "Synchronize window config updates (13/n)" into main

parents 64a6d862 a19b571c
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -4777,6 +4777,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
        if (DEBUG_ALL && !mWindowManager.mWindowPlacerLocked.isLayoutDeferred()) {
            Slog.i(TAG, "continueWindowLayout reason=" + mLayoutReasons);
        }

        // ClientTransactions is queued during #deferWindowLayout() for performance.
        // Notify to continue.
        mLifecycleManager.onLayoutContinued();
    }

    /**
+39 −14
Original line number Diff line number Diff line
@@ -105,7 +105,7 @@ class ClientLifecycleManager {
            final ClientTransaction clientTransaction = getOrCreatePendingTransaction(client);
            clientTransaction.addTransactionItem(transactionItem);

            onClientTransactionItemScheduledLocked(clientTransaction);
            onClientTransactionItemScheduled(clientTransaction);
        } else {
            // TODO(b/260873529): cleanup after launch.
            final ClientTransaction clientTransaction = ClientTransaction.obtain(client);
@@ -134,7 +134,7 @@ class ClientLifecycleManager {
            clientTransaction.addTransactionItem(transactionItem);
            clientTransaction.addTransactionItem(lifecycleItem);

            onClientTransactionItemScheduledLocked(clientTransaction);
            onClientTransactionItemScheduled(clientTransaction);
        } else {
            // TODO(b/260873529): cleanup after launch.
            final ClientTransaction clientTransaction = ClientTransaction.obtain(client);
@@ -146,6 +146,9 @@ class ClientLifecycleManager {

    /** Executes all the pending transactions. */
    void dispatchPendingTransactions() {
        if (!Flags.bundleClientTransactionFlag()) {
            return;
        }
        final int size = mPendingTransactions.size();
        for (int i = 0; i < size; i++) {
            final ClientTransaction transaction = mPendingTransactions.valueAt(i);
@@ -158,6 +161,20 @@ class ClientLifecycleManager {
        mPendingTransactions.clear();
    }

    /**
     * Called to when {@link WindowSurfacePlacer#continueLayout}.
     * Dispatches all pending transactions unless there is an ongoing/scheduled layout, in which
     * case the pending transactions will be dispatched in
     * {@link RootWindowContainer#performSurfacePlacementNoTrace}.
     */
    void onLayoutContinued() {
        if (shouldDispatchPendingTransactionsImmediately()) {
            // Dispatch the pending transactions immediately if there is no ongoing/scheduled layout
            dispatchPendingTransactions();
        }
    }

    /** Must only be called with WM lock. */
    @NonNull
    private ClientTransaction getOrCreatePendingTransaction(@NonNull IApplicationThread client) {
        final IBinder clientBinder = client.asBinder();
@@ -173,20 +190,28 @@ class ClientLifecycleManager {
    }

    /** Must only be called with WM lock. */
    private void onClientTransactionItemScheduledLocked(
    private void onClientTransactionItemScheduled(
            @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;
        }

        if (shouldDispatchPendingTransactionsImmediately()) {
            // Dispatch the pending transaction immediately.
            mPendingTransactions.remove(clientTransaction.getClient().asBinder());
            scheduleTransaction(clientTransaction);
        }
    }

    /** Must only be called with WM lock. */
    private boolean shouldDispatchPendingTransactionsImmediately() {
        if (mWms == null) {
            return true;
        }
        // Do not dispatch when
        // 1. Layout deferred.
        // 2. Layout requested.
        // 3. Layout in process.
        // The pending transactions will be dispatched during layout in
        // RootWindowContainer#performSurfacePlacementNoTrace.
        return !mWms.mWindowPlacerLocked.isLayoutDeferred()
                && !mWms.mWindowPlacerLocked.isTraversalScheduled()
                && !mWms.mWindowPlacerLocked.isInLayout();
    }
}
+12 −0
Original line number Diff line number Diff line
@@ -1087,4 +1087,16 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase {
        assertTrue(homeActivity.getTask().isFocused());
        assertFalse(pinnedTask.isFocused());
    }

    @Test
    public void testContinueWindowLayout_notifyClientLifecycleManager() {
        clearInvocations(mClientLifecycleManager);
        mAtm.deferWindowLayout();

        verify(mClientLifecycleManager, never()).onLayoutContinued();

        mAtm.continueWindowLayout();

        verify(mClientLifecycleManager).onLayoutContinued();
    }
}
+29 −3
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server.wm;

import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
@@ -52,14 +54,12 @@ import org.mockito.MockitoAnnotations;
 * Build/Install/Run:
 *  atest WmTests:ClientLifecycleManagerTests
 */
// Suppress GuardedBy warning on unit tests
@SuppressWarnings("GuardedBy")
@SmallTest
@Presubmit
public class ClientLifecycleManagerTests {

    @Rule(order = 0)
    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT);

    @Rule(order = 1)
    public final SystemServicesTestRule mSystemServices = new SystemServicesTestRule();
@@ -225,4 +225,30 @@ public class ClientLifecycleManagerTests {
        verify(mTransaction).schedule();
        verify(mTransaction).recycle();
    }

    @Test
    public void testLayoutDeferred() throws RemoteException {
        mSetFlagsRule.enableFlags(FLAG_BUNDLE_CLIENT_TRANSACTION_FLAG);
        spyOn(mWms.mWindowPlacerLocked);
        doReturn(false).when(mWms.mWindowPlacerLocked).isInLayout();
        doReturn(false).when(mWms.mWindowPlacerLocked).isTraversalScheduled();
        doReturn(true).when(mWms.mWindowPlacerLocked).isLayoutDeferred();

        // Queue transactions during layout deferred.
        mLifecycleManager.scheduleTransactionItem(mNonBinderClient, mLifecycleItem);

        verify(mLifecycleManager, never()).scheduleTransaction(any());

        // Continue queueing when there are multi-level defer.
        mLifecycleManager.onLayoutContinued();

        verify(mLifecycleManager, never()).scheduleTransaction(any());

        // Immediately dispatch when layout continue without ongoing/scheduled layout.
        doReturn(false).when(mWms.mWindowPlacerLocked).isLayoutDeferred();

        mLifecycleManager.onLayoutContinued();

        verify(mLifecycleManager).scheduleTransaction(any());
    }
}