Synchronize window config updates (13/n)
Queueing ClientTransactions when deferWindowLayout. This should cover most system transition, like WindowOrganizerController#applyTransaction. Bug: 260873529 Test: atest WmTests:ClientLifecycleManagerTests Change-Id: I98a17e11ad77f4f93eb9fc4a580fceaa3dea8e1e
This commit is contained in:
parent
cc024fb28d
commit
a19b571c36
@ -4762,6 +4762,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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user