From 480e230e478ca9efa1c0ce9021cd6525278a7b51 Mon Sep 17 00:00:00 2001 From: Robert Horvath Date: Wed, 27 Apr 2022 17:19:42 +0200 Subject: [PATCH] Rate limit calls from apps to reportKeepClearAreaChanged Only allows keep clear area changes to be reported every 100ms. Helpful to keep IPC from app to WindowManager to SystemUI lower during animations, when Views marked as preferKeepClear change position a lot. Bug: 226583836 Test: atest KeepClearRectsTests Change-Id: I9f6c86c5345218c9ee40f50a74d4357dd4e94dc7 --- core/java/android/view/ViewRootImpl.java | 48 +++++++++++++++++++++--- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index fbb86ff3a55a8..e648d804f4897 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -321,6 +321,11 @@ public final class ViewRootImpl implements ViewParent, private static final int UNSET_SYNC_ID = -1; + /** + * Minimum time to wait before reporting changes to keep clear areas. + */ + private static final int KEEP_CLEAR_AREA_REPORT_RATE_MILLIS = 100; + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) static final ThreadLocal sRunQueues = new ThreadLocal(); @@ -796,6 +801,8 @@ public final class ViewRootImpl implements ViewParent, new ViewRootRectTracker(v -> v.collectPreferKeepClearRects()); private final ViewRootRectTracker mUnrestrictedKeepClearRectsTracker = new ViewRootRectTracker(v -> v.collectUnrestrictedPreferKeepClearRects()); + private List mPendingKeepClearAreas; + private List mPendingUnrestrictedKeepClearAreas; private IAccessibilityEmbeddedConnection mAccessibilityEmbeddedConnection; @@ -4824,15 +4831,42 @@ public final class ViewRootImpl implements ViewParent, unrestrictedKeepClearRects = Collections.emptyList(); } - try { - mWindowSession.reportKeepClearAreasChanged(mWindow, restrictedKeepClearRects, - unrestrictedKeepClearRects); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); + if (mHandler.hasMessages(MSG_REPORT_KEEP_CLEAR_RECTS)) { + // Keep clear areas have been reported recently, wait before reporting new set + // of keep clear areas + mPendingKeepClearAreas = restrictedKeepClearRects; + mPendingUnrestrictedKeepClearAreas = unrestrictedKeepClearRects; + } else { + mHandler.sendEmptyMessageDelayed(MSG_REPORT_KEEP_CLEAR_RECTS, + KEEP_CLEAR_AREA_REPORT_RATE_MILLIS); + try { + mWindowSession.reportKeepClearAreasChanged(mWindow, restrictedKeepClearRects, + unrestrictedKeepClearRects); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } } } + void reportKeepClearAreasChanged() { + final List restrictedKeepClearRects = mPendingKeepClearAreas; + final List unrestrictedKeepClearRects = mPendingUnrestrictedKeepClearAreas; + if (restrictedKeepClearRects == null && unrestrictedKeepClearRects == null) { + return; + } + + mPendingKeepClearAreas = null; + mPendingUnrestrictedKeepClearAreas = null; + + try { + mWindowSession.reportKeepClearAreasChanged(mWindow, restrictedKeepClearRects, + unrestrictedKeepClearRects); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Requests that the root render node is invalidated next time we perform a draw, such that * {@link WindowCallbacks#onPostDraw} gets called. @@ -5325,6 +5359,7 @@ public final class ViewRootImpl implements ViewParent, private static final int MSG_REQUEST_SCROLL_CAPTURE = 33; private static final int MSG_WINDOW_TOUCH_MODE_CHANGED = 34; private static final int MSG_KEEP_CLEAR_RECTS_CHANGED = 35; + private static final int MSG_REPORT_KEEP_CLEAR_RECTS = 36; final class ViewRootHandler extends Handler { @@ -5601,6 +5636,9 @@ public final class ViewRootImpl implements ViewParent, case MSG_KEEP_CLEAR_RECTS_CHANGED: { keepClearRectsChanged(); } break; + case MSG_REPORT_KEEP_CLEAR_RECTS: { + reportKeepClearAreasChanged(); + } break; case MSG_REQUEST_SCROLL_CAPTURE: handleScrollCaptureRequest((IScrollCaptureResponseListener) msg.obj); break;