From db7b35a070d558c83959fc9f280dd2126f4f35a8 Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Tue, 26 Jul 2022 23:17:17 +0800 Subject: [PATCH] Make a copy for draw transaction of local window Because local window means that ViewRootImpl lives in the same process. The transaction sent from ViewRootImpl#reportDrawFinished is the same instance as WindowState#finishDrawing receives. Then if the transaction is cleared before applying, the blast sync will be broken and block render thread. Bug: 234585256 Test: adb shell setprop persist.wm.debug.shell_transit 1; reboot Enable "Pointer location" in developer options. Rotate display many times and no any timeout. Change-Id: I111c44b9100771b38fe60f07735e93778458c502 --- .../server/wm/AsyncRotationController.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/services/core/java/com/android/server/wm/AsyncRotationController.java b/services/core/java/com/android/server/wm/AsyncRotationController.java index 1898cc65b1078..219092baface2 100644 --- a/services/core/java/com/android/server/wm/AsyncRotationController.java +++ b/services/core/java/com/android/server/wm/AsyncRotationController.java @@ -204,11 +204,8 @@ class AsyncRotationController extends FadeAnimationController implements Consume for (int i = mTargetWindowTokens.size() - 1; i >= 0; i--) { final WindowToken token = mTargetWindowTokens.keyAt(i); for (int j = token.getChildCount() - 1; j >= 0; j--) { - // TODO(b/234585256): The consumer should be handleFinishDrawing(). And check why - // the local window might easily time out. - final WindowState w = token.getChildAt(j); - if (w.isClientLocal()) continue; - w.applyWithNextDraw(t -> {}); + // TODO(b/234585256): The consumer should be handleFinishDrawing(). + token.getChildAt(j).applyWithNextDraw(t -> {}); } } mIsSyncDrawRequested = true; @@ -484,7 +481,16 @@ class AsyncRotationController extends FadeAnimationController implements Consume if (op == null) return false; if (DEBUG) Slog.d(TAG, "handleFinishDrawing " + w); if (op.mDrawTransaction == null) { - op.mDrawTransaction = postDrawTransaction; + if (w.isClientLocal()) { + // Use a new transaction to merge the draw transaction of local window because the + // same instance will be cleared (Transaction#clear()) after reporting draw. + op.mDrawTransaction = mService.mTransactionFactory.get(); + op.mDrawTransaction.merge(postDrawTransaction); + } else { + // The transaction read from parcel (the client is in a different process) is + // already a copy, so just reference it directly. + op.mDrawTransaction = postDrawTransaction; + } } else { op.mDrawTransaction.merge(postDrawTransaction); }