summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java4
-rw-r--r--services/core/java/com/android/server/wm/BLASTSyncEngine.java31
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java4
-rw-r--r--services/core/java/com/android/server/wm/Transition.java4
-rw-r--r--services/core/java/com/android/server/wm/TransitionController.java11
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java1
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java18
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TransitionTests.java49
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java9
10 files changed, 103 insertions, 32 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index ce7eae39931a..5672ef32c00a 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -3643,6 +3643,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (mPendingRelaunchCount > 0) {
mPendingRelaunchCount--;
+ if (mPendingRelaunchCount == 0 && !isClientVisible()) {
+ // Don't count if the client won't report drawn.
+ mRelaunchStartTime = 0;
+ }
} else {
// Update keyguard flags upon finishing relaunch.
checkKeyguardFlagsChanged();
diff --git a/services/core/java/com/android/server/wm/BLASTSyncEngine.java b/services/core/java/com/android/server/wm/BLASTSyncEngine.java
index 4355b3855bb7..2a8ac39ead8d 100644
--- a/services/core/java/com/android/server/wm/BLASTSyncEngine.java
+++ b/services/core/java/com/android/server/wm/BLASTSyncEngine.java
@@ -20,9 +20,11 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SYNC_ENGINE;
import android.annotation.NonNull;
import android.util.ArraySet;
+import android.util.Slog;
import android.util.SparseArray;
import android.view.SurfaceControl;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
/**
@@ -65,6 +67,7 @@ class BLASTSyncEngine {
class SyncGroup {
final int mSyncId;
final TransactionReadyListener mListener;
+ final Runnable mOnTimeout;
boolean mReady = false;
final ArraySet<WindowContainer> mRootMembers = new ArraySet<>();
private SurfaceControl.Transaction mOrphanTransaction = null;
@@ -72,6 +75,12 @@ class BLASTSyncEngine {
private SyncGroup(TransactionReadyListener listener, int id) {
mSyncId = id;
mListener = listener;
+ mOnTimeout = () -> {
+ Slog.w(TAG, "Sync group " + mSyncId + " timeout");
+ synchronized (mWm.mGlobalLock) {
+ onTimeout();
+ }
+ };
}
/**
@@ -114,6 +123,7 @@ class BLASTSyncEngine {
}
mListener.onTransactionReady(mSyncId, merged);
mActiveSyncs.remove(mSyncId);
+ mWm.mH.removeCallbacks(mOnTimeout);
}
private void setReady(boolean ready) {
@@ -136,6 +146,17 @@ class BLASTSyncEngine {
void onCancelSync(WindowContainer wc) {
mRootMembers.remove(wc);
}
+
+ private void onTimeout() {
+ if (!mActiveSyncs.contains(mSyncId)) return;
+ for (int i = mRootMembers.size() - 1; i >= 0; --i) {
+ final WindowContainer<?> wc = mRootMembers.valueAt(i);
+ if (!wc.isSyncFinished()) {
+ Slog.i(TAG, "Unfinished container: " + wc);
+ }
+ }
+ finishNow();
+ }
}
private final WindowManagerService mWm;
@@ -147,13 +168,23 @@ class BLASTSyncEngine {
}
int startSyncSet(TransactionReadyListener listener) {
+ return startSyncSet(listener, WindowState.BLAST_TIMEOUT_DURATION);
+ }
+
+ int startSyncSet(TransactionReadyListener listener, long timeoutMs) {
final int id = mNextSyncId++;
final SyncGroup s = new SyncGroup(listener, id);
mActiveSyncs.put(id, s);
ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "SyncGroup %d: Started for listener: %s", id, listener);
+ scheduleTimeout(s, timeoutMs);
return id;
}
+ @VisibleForTesting
+ void scheduleTimeout(SyncGroup s, long timeoutMs) {
+ mWm.mH.postDelayed(s.mOnTimeout, timeoutMs);
+ }
+
void addToSyncSet(int id, WindowContainer wc) {
mActiveSyncs.get(id).addToSync(wc);
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 0ecee6641509..0de3fa3ad968 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3449,7 +3449,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
@Override
public String toString() {
- return "Display " + mDisplayId + " info=" + mDisplayInfo + " rootTasks=" + mChildren;
+ return "Display{#" + mDisplayId + " state=" + Display.stateToString(mDisplayInfo.state)
+ + " size=" + mDisplayInfo.logicalWidth + "x" + mDisplayInfo.logicalHeight
+ + " " + Surface.rotationToString(mDisplayInfo.rotation) + "}";
}
String getName() {
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 9fc45b972e91..5d82553ad284 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -165,13 +165,13 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
private boolean mNavBarAttachedToApp = false;
private int mRecentsDisplayId = INVALID_DISPLAY;
- Transition(@TransitionType int type, @TransitionFlags int flags,
+ Transition(@TransitionType int type, @TransitionFlags int flags, long timeoutMs,
TransitionController controller, BLASTSyncEngine syncEngine) {
mType = type;
mFlags = flags;
mController = controller;
mSyncEngine = syncEngine;
- mSyncId = mSyncEngine.startSyncSet(this);
+ mSyncId = mSyncEngine.startSyncSet(this, timeoutMs);
}
void addFlag(int flag) {
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index bf4cf5f75e36..91825ccf98e7 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FLAG_IS_RECENTS;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
@@ -55,6 +56,11 @@ import java.util.function.LongConsumer;
class TransitionController {
private static final String TAG = "TransitionController";
+ /** The same as legacy APP_TRANSITION_TIMEOUT_MS. */
+ private static final int DEFAULT_TIMEOUT_MS = 5000;
+ /** Less duration for CHANGE type because it does not involve app startup. */
+ private static final int CHANGE_TIMEOUT_MS = 2000;
+
// State constants to line-up with legacy app-transition proto expectations.
private static final int LEGACY_STATE_IDLE = 0;
private static final int LEGACY_STATE_READY = 1;
@@ -121,7 +127,10 @@ class TransitionController {
if (mCollectingTransition != null) {
throw new IllegalStateException("Simultaneous transitions not supported yet.");
}
- mCollectingTransition = new Transition(type, flags, this, mAtm.mWindowManager.mSyncEngine);
+ // Distinguish change type because the response time is usually expected to be not too long.
+ final long timeoutMs = type == TRANSIT_CHANGE ? CHANGE_TIMEOUT_MS : DEFAULT_TIMEOUT_MS;
+ mCollectingTransition = new Transition(type, flags, timeoutMs, this,
+ mAtm.mWindowManager.mSyncEngine);
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Creating Transition: %s",
mCollectingTransition);
dispatchLegacyAppTransitionPending();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index fd0f4636ec1f..9b53d3e00a1e 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -5396,6 +5396,7 @@ public class WindowManagerService extends IWindowManager.Stub
case WINDOW_STATE_BLAST_SYNC_TIMEOUT: {
synchronized (mGlobalLock) {
final WindowState ws = (WindowState) msg.obj;
+ Slog.i(TAG, "Blast sync timeout: " + ws);
ws.immediatelyNotifyBlastSync();
}
break;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 2410d7ec13c2..8fafc7d64c29 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -6041,10 +6041,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// in WAITING state rather than READY.
mSyncState = SYNC_STATE_WAITING_FOR_DRAW;
requestRedrawForSync();
-
- mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this);
- mWmService.mH.sendNewMessageDelayed(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this,
- BLAST_TIMEOUT_DURATION);
return true;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java b/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java
index 7bac3e7b8679..420ea8e63562 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java
@@ -62,7 +62,7 @@ public class SyncEngineTests extends WindowTestsBase {
public void testTrivialSyncCallback() {
TestWindowContainer mockWC = new TestWindowContainer(mWm, false /* waiter */);
- BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+ final BLASTSyncEngine bse = createTestBLASTSyncEngine();
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
@@ -90,7 +90,7 @@ public class SyncEngineTests extends WindowTestsBase {
public void testWaitingSyncCallback() {
TestWindowContainer mockWC = new TestWindowContainer(mWm, true /* waiter */);
- BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+ final BLASTSyncEngine bse = createTestBLASTSyncEngine();
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
@@ -114,7 +114,7 @@ public class SyncEngineTests extends WindowTestsBase {
public void testInvisibleSyncCallback() {
TestWindowContainer mockWC = new TestWindowContainer(mWm, true /* waiter */);
- BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+ final BLASTSyncEngine bse = createTestBLASTSyncEngine();
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
@@ -142,7 +142,7 @@ public class SyncEngineTests extends WindowTestsBase {
parentWC.addChild(childWC, POSITION_TOP);
parentWC.addChild(childWC2, POSITION_TOP);
- BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+ final BLASTSyncEngine bse = createTestBLASTSyncEngine();
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
@@ -175,7 +175,7 @@ public class SyncEngineTests extends WindowTestsBase {
TestWindowContainer childWC = new TestWindowContainer(mWm, true /* waiter */);
parentWC.addChild(childWC, POSITION_TOP);
- BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+ final BLASTSyncEngine bse = createTestBLASTSyncEngine();
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
@@ -206,7 +206,7 @@ public class SyncEngineTests extends WindowTestsBase {
parentWC.addChild(topChildWC, POSITION_TOP);
parentWC.addChild(botChildWC, POSITION_BOTTOM);
- BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+ final BLASTSyncEngine bse = createTestBLASTSyncEngine();
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
@@ -238,7 +238,7 @@ public class SyncEngineTests extends WindowTestsBase {
parentWC.addChild(topChildWC, POSITION_TOP);
parentWC.addChild(botChildWC, POSITION_BOTTOM);
- BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+ final BLASTSyncEngine bse = createTestBLASTSyncEngine();
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
@@ -273,7 +273,7 @@ public class SyncEngineTests extends WindowTestsBase {
parentWC.addChild(topChildWC, POSITION_TOP);
nonMemberParentWC.addChild(botChildWC, POSITION_BOTTOM);
- BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+ final BLASTSyncEngine bse = createTestBLASTSyncEngine();
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
@@ -312,7 +312,7 @@ public class SyncEngineTests extends WindowTestsBase {
parentWC.addChild(topChildWC, POSITION_TOP);
parentWC.addChild(botChildWC, POSITION_BOTTOM);
- BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+ final BLASTSyncEngine bse = createTestBLASTSyncEngine();
BLASTSyncEngine.TransactionReadyListener listener = mock(
BLASTSyncEngine.TransactionReadyListener.class);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index a1c24c26af35..4e77fa73fd09 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -21,7 +21,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.TRANSIT_CLOSE;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
@@ -44,6 +43,7 @@ import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.view.SurfaceControl;
import android.window.ITaskOrganizer;
import android.window.ITransitionPlayer;
import android.window.TransitionInfo;
@@ -53,9 +53,12 @@ import androidx.test.filters.SmallTest;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
/**
* Build/Install/Run:
- * atest WmTests:TransitionRecordTests
+ * atest WmTests:TransitionTests
*/
@SmallTest
@Presubmit
@@ -64,13 +67,13 @@ public class TransitionTests extends WindowTestsBase {
private Transition createTestTransition(int transitType) {
TransitionController controller = mock(TransitionController.class);
- BLASTSyncEngine sync = new BLASTSyncEngine(mWm);
- return new Transition(transitType, 0 /* flags */, controller, sync);
+ final BLASTSyncEngine sync = createTestBLASTSyncEngine();
+ return new Transition(transitType, 0 /* flags */, 0 /* timeoutMs */, controller, sync);
}
@Test
public void testCreateInfo_NewTask() {
- final Transition transition = createTestTransition(TRANSIT_OLD_TASK_OPEN);
+ final Transition transition = createTestTransition(TRANSIT_OPEN);
ArrayMap<WindowContainer, Transition.ChangeInfo> changes = transition.mChanges;
ArraySet<WindowContainer> participants = transition.mParticipants;
@@ -88,7 +91,7 @@ public class TransitionTests extends WindowTestsBase {
closing.mVisibleRequested = false;
opening.mVisibleRequested = true;
- int transit = TRANSIT_OLD_TASK_OPEN;
+ final int transit = transition.mType;
int flags = 0;
// Check basic both tasks participating
@@ -127,7 +130,7 @@ public class TransitionTests extends WindowTestsBase {
@Test
public void testCreateInfo_NestedTasks() {
- final Transition transition = createTestTransition(TRANSIT_OLD_TASK_OPEN);
+ final Transition transition = createTestTransition(TRANSIT_OPEN);
ArrayMap<WindowContainer, Transition.ChangeInfo> changes = transition.mChanges;
ArraySet<WindowContainer> participants = transition.mParticipants;
@@ -152,7 +155,7 @@ public class TransitionTests extends WindowTestsBase {
opening.mVisibleRequested = true;
opening2.mVisibleRequested = true;
- int transit = TRANSIT_OLD_TASK_OPEN;
+ final int transit = transition.mType;
int flags = 0;
// Check full promotion from leaf
@@ -177,7 +180,7 @@ public class TransitionTests extends WindowTestsBase {
@Test
public void testCreateInfo_DisplayArea() {
- final Transition transition = createTestTransition(TRANSIT_OLD_TASK_OPEN);
+ final Transition transition = createTestTransition(TRANSIT_OPEN);
ArrayMap<WindowContainer, Transition.ChangeInfo> changes = transition.mChanges;
ArraySet<WindowContainer> participants = transition.mParticipants;
final Task showTask = createTask(mDisplayContent);
@@ -199,7 +202,7 @@ public class TransitionTests extends WindowTestsBase {
showing.mVisibleRequested = true;
showing2.mVisibleRequested = true;
- int transit = TRANSIT_OLD_TASK_OPEN;
+ final int transit = transition.mType;
int flags = 0;
// Check promotion to DisplayArea
@@ -228,7 +231,7 @@ public class TransitionTests extends WindowTestsBase {
@Test
public void testCreateInfo_existenceChange() {
- final Transition transition = createTestTransition(TRANSIT_OLD_TASK_OPEN);
+ final Transition transition = createTestTransition(TRANSIT_OPEN);
final Task openTask = createTask(mDisplayContent);
final ActivityRecord opening = createActivityRecord(openTask);
@@ -258,7 +261,7 @@ public class TransitionTests extends WindowTestsBase {
@Test
public void testCreateInfo_ordering() {
- final Transition transition = createTestTransition(TRANSIT_OLD_TASK_OPEN);
+ final Transition transition = createTestTransition(TRANSIT_OPEN);
// pick some number with a high enough chance of being out-of-order when added to set.
final int taskCount = 6;
@@ -294,7 +297,7 @@ public class TransitionTests extends WindowTestsBase {
@Test
public void testCreateInfo_wallpaper() {
- final Transition transition = createTestTransition(TRANSIT_OLD_TASK_OPEN);
+ final Transition transition = createTestTransition(TRANSIT_OPEN);
// pick some number with a high enough chance of being out-of-order when added to set.
final int taskCount = 4;
final int showWallpaperTask = 2;
@@ -345,7 +348,7 @@ public class TransitionTests extends WindowTestsBase {
@Test
public void testTargets_noIntermediatesToWallpaper() {
- final Transition transition = createTestTransition(TRANSIT_OLD_TASK_OPEN);
+ final Transition transition = createTestTransition(TRANSIT_OPEN);
final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm,
mock(IBinder.class), true, mDisplayContent, true /* ownerCanManageAppTokens */);
@@ -419,7 +422,7 @@ public class TransitionTests extends WindowTestsBase {
openInOpen.mVisibleRequested = true;
openInChange.mVisibleRequested = true;
- int transit = TRANSIT_OLD_TASK_OPEN;
+ final int transit = transition.mType;
int flags = 0;
// Check full promotion from leaf
@@ -450,6 +453,22 @@ public class TransitionTests extends WindowTestsBase {
}
@Test
+ public void testTimeout() {
+ final TransitionController controller = new TransitionController(mAtm,
+ mock(TaskSnapshotController.class));
+ final BLASTSyncEngine sync = new BLASTSyncEngine(mWm);
+ final CountDownLatch latch = new CountDownLatch(1);
+ // When the timeout is reached, it will finish the sync-group and notify transaction ready.
+ new Transition(TRANSIT_OPEN, 0 /* flags */, 10 /* timeoutMs */, controller, sync) {
+ @Override
+ public void onTransactionReady(int syncId, SurfaceControl.Transaction transaction) {
+ latch.countDown();
+ }
+ };
+ assertTrue(awaitInWmLock(() -> latch.await(3, TimeUnit.SECONDS)));
+ }
+
+ @Test
public void testIntermediateVisibility() {
final TaskSnapshotController snapshotController = mock(TaskSnapshotController.class);
final TransitionController controller = new TransitionController(mAtm, snapshotController);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index b2d4eea4feae..ac61bb15ab06 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -789,6 +789,15 @@ class WindowTestsBase extends SystemServiceTestsBase {
};
}
+ BLASTSyncEngine createTestBLASTSyncEngine() {
+ return new BLASTSyncEngine(mWm) {
+ @Override
+ void scheduleTimeout(SyncGroup s, long timeoutMs) {
+ // Disable timeout.
+ }
+ };
+ }
+
/**
* Avoids rotating screen disturbed by some conditions. It is usually used for the default
* display that is not the instance of {@link TestDisplayContent} (it bypasses the conditions).