summaryrefslogtreecommitdiff
path: root/core/java/android/view
diff options
context:
space:
mode:
authorSiarhei Vishniakou <svv@google.com>2020-11-30 10:30:52 -1000
committerSiarhei Vishniakou <svv@google.com>2020-12-01 15:07:50 -1000
commitefed16630a8cf71287f04cde5dc59c4e0db1d987 (patch)
tree7d9c798140281a901d8e6ab0607b594fe48e394b /core/java/android/view
parent26ca287da728d88709f7523113637104fb31bf3e (diff)
Track per-window information in ViewFrameInfo
FrameInfo will now be per-window; that is, per-ViewRootImpl. Some of the information should remain “global” (it remain in Choreographer), while some information is going to become ViewRootImpl-specific. Before the information gets passed to the native layer, the ViewRootImpl-specific info will be stitched together with the general Choreographer info. This change is useful in order to correctly correlate frames with a specific input event. In the unlikely scenario of a user touching two windows of the same app simultaneously, this change will allow us to correctly measure the latency of both frames produced by the windows. Design doc: https://docs.google.com/document/d/1KMpMBlOxnl7zkWBCbXZZE6ZlaHEA4efYnN6WYK8n3FE/edit?resourcekey=0-eqooVNP0SskupljlTFvtOQ Test: atest ViewFrameInfoTest Bug: 169866723 Change-Id: Ib0bf9cd51cbcc0b9b70460c929c480eb490ec322
Diffstat (limited to 'core/java/android/view')
-rw-r--r--core/java/android/view/ThreadedRenderer.java8
-rw-r--r--core/java/android/view/ViewFrameInfo.java81
-rw-r--r--core/java/android/view/ViewRootImpl.java24
3 files changed, 107 insertions, 6 deletions
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 57ca71ae4b02..d839e3532b64 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.Context;
import android.content.res.TypedArray;
+import android.graphics.FrameInfo;
import android.graphics.HardwareRenderer;
import android.graphics.Picture;
import android.graphics.Point;
@@ -610,8 +611,7 @@ public final class ThreadedRenderer extends HardwareRenderer {
* @param attachInfo AttachInfo tied to the specified view.
*/
void draw(View view, AttachInfo attachInfo, DrawCallbacks callbacks) {
- final Choreographer choreographer = attachInfo.mViewRootImpl.mChoreographer;
- choreographer.mFrameInfo.markDrawStart();
+ attachInfo.mViewRootImpl.mViewFrameInfo.markDrawStart();
updateRootDisplayList(view, callbacks);
@@ -629,7 +629,9 @@ public final class ThreadedRenderer extends HardwareRenderer {
attachInfo.mPendingAnimatingRenderNodes = null;
}
- int syncResult = syncAndDrawFrame(choreographer.mFrameInfo);
+ final FrameInfo frameInfo = attachInfo.mViewRootImpl.getUpdatedFrameInfo();
+
+ int syncResult = syncAndDrawFrame(frameInfo);
if ((syncResult & SYNC_LOST_SURFACE_REWARD_IF_FOUND) != 0) {
Log.w("OpenGLRenderer", "Surface lost, forcing relayout");
// We lost our surface. For a relayout next frame which should give us a new
diff --git a/core/java/android/view/ViewFrameInfo.java b/core/java/android/view/ViewFrameInfo.java
new file mode 100644
index 000000000000..890d071f8090
--- /dev/null
+++ b/core/java/android/view/ViewFrameInfo.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.graphics.FrameInfo;
+
+/**
+ * The timing information of events taking place in ViewRootImpl
+ * @hide
+ */
+public class ViewFrameInfo {
+ public long drawStart;
+ public long oldestInputEventTime; // the time of the oldest input event consumed for this frame
+ public long newestInputEventTime; // the time of the newest input event consumed for this frame
+ // Various flags set to provide extra metadata about the current frame. See flag definitions
+ // inside FrameInfo.
+ // @see android.graphics.FrameInfo.FLAG_WINDOW_LAYOUT_CHANGED
+ public long flags;
+
+ /**
+ * Update the oldest event time.
+ * @param eventTime the time of the input event
+ */
+ public void updateOldestInputEvent(long eventTime) {
+ if (oldestInputEventTime == 0 || eventTime < oldestInputEventTime) {
+ oldestInputEventTime = eventTime;
+ }
+ }
+
+ /**
+ * Update the newest event time.
+ * @param eventTime the time of the input event
+ */
+ public void updateNewestInputEvent(long eventTime) {
+ if (newestInputEventTime == 0 || eventTime > newestInputEventTime) {
+ newestInputEventTime = eventTime;
+ }
+ }
+
+ /**
+ * Populate the missing fields using the data from ViewFrameInfo
+ * @param frameInfo : the structure FrameInfo object to populate
+ */
+ public void populateFrameInfo(FrameInfo frameInfo) {
+ frameInfo.frameInfo[FrameInfo.FLAGS] |= flags;
+ frameInfo.frameInfo[FrameInfo.DRAW_START] = drawStart;
+ frameInfo.frameInfo[FrameInfo.OLDEST_INPUT_EVENT] = oldestInputEventTime;
+ frameInfo.frameInfo[FrameInfo.NEWEST_INPUT_EVENT] = newestInputEventTime;
+ }
+
+ /**
+ * Reset this data. Should typically be invoked after calling "populateFrameInfo".
+ */
+ public void reset() {
+ drawStart = 0;
+ oldestInputEventTime = 0;
+ newestInputEventTime = 0;
+ flags = 0;
+ }
+
+ /**
+ * Record the current time, and store it in 'drawStart'
+ */
+ public void markDrawStart() {
+ drawStart = System.nanoTime();
+ }
+}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 2bea0d6b4b04..ae162ede2c70 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -423,7 +423,7 @@ public final class ViewRootImpl implements ViewParent,
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
int mHeight;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- Rect mDirty;
+ private Rect mDirty;
public boolean mIsAnimating;
private boolean mUseMTRenderer;
@@ -446,6 +446,23 @@ public final class ViewRootImpl implements ViewParent,
@UnsupportedAppUsage
FallbackEventHandler mFallbackEventHandler;
final Choreographer mChoreographer;
+ protected final ViewFrameInfo mViewFrameInfo = new ViewFrameInfo();
+
+ /**
+ * Update the Choreographer's FrameInfo object with the timing information for the current
+ * ViewRootImpl instance. Erase the data in the current ViewFrameInfo to prepare for the next
+ * frame.
+ * @return the updated FrameInfo object
+ */
+ protected @NonNull FrameInfo getUpdatedFrameInfo() {
+ // Since Choreographer is a thread-local singleton while we can have multiple
+ // ViewRootImpl's, populate the frame information from the current viewRootImpl before
+ // starting the draw
+ FrameInfo frameInfo = mChoreographer.mFrameInfo;
+ mViewFrameInfo.populateFrameInfo(frameInfo);
+ mViewFrameInfo.reset();
+ return frameInfo;
+ }
// used in relayout to get SurfaceControl size
// for BLAST adapter surface setup
@@ -2675,7 +2692,7 @@ public final class ViewRootImpl implements ViewParent,
// to resume them
mDirty.set(0, 0, mWidth, mHeight);
}
- mChoreographer.mFrameInfo.addFlags(FrameInfo.FLAG_WINDOW_LAYOUT_CHANGED);
+ mViewFrameInfo.flags |= FrameInfo.FLAG_WINDOW_LAYOUT_CHANGED;
}
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
@@ -8138,7 +8155,8 @@ public final class ViewRootImpl implements ViewParent,
oldestEventTime = me.getHistoricalEventTimeNano(0);
}
}
- mChoreographer.mFrameInfo.updateInputEventTime(eventTime, oldestEventTime);
+ mViewFrameInfo.updateOldestInputEvent(oldestEventTime);
+ mViewFrameInfo.updateNewestInputEvent(eventTime);
deliverInputEvent(q);
}