Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f0cf18d3 authored by Siarhei Vishniakou's avatar Siarhei Vishniakou
Browse files

Pass actual present time to ViewRootImpl

To measure end-to-end touch latency, we need to report the actual
present time to ViewRootImpl. ViewRootImpl, in turn, will report this
information to InputDispatcher. Finally, InputDispatcher will combine
all known information for a specific input event, and will report this
data to westworld.

In another patch, we will add a new call, 'reportLatencyInfo', to
InputPublisher. This call will allow the app to send this latency data
to InputDispatcher.

Bug: 169866723
Test: printed the input event present times inside ViewRootImpl
Change-Id: Ibd3a2cfeb1a340eb15cd2165071df1f8589634af
parent 7102d06f
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -45,7 +45,8 @@ public class FrameMetricsObserver
        mWindow = new WeakReference<>(window);
        mListener = listener;
        mFrameMetrics = new FrameMetrics();
        mObserver = new HardwareRendererObserver(this,  mFrameMetrics.mTimingData, handler);
        mObserver = new HardwareRendererObserver(this,  mFrameMetrics.mTimingData, handler,
                false /*waitForPresentTime*/);
    }

    /**
+10 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.os.Build;
import android.os.IBinder;
import android.os.Looper;
import android.os.MessageQueue;
import android.os.Trace;
import android.util.Log;
import android.util.SparseIntArray;

@@ -197,6 +198,15 @@ public abstract class InputEventReceiver {
        event.recycleIfNeededAfterDispatch();
    }

    /**
     * Report the latency information for a specific input event.
     */
    public final void reportLatencyInfo(int inputEventId, long gpuCompletedTime, long presentTime) {
        Trace.traceBegin(Trace.TRACE_TAG_INPUT, "reportLatencyInfo");
        // TODO(b/169866723) : send this data to InputDispatcher via InputChannel
        Trace.traceEnd(Trace.TRACE_TAG_INPUT);
    }

    /**
     * Consumes all pending batched input events.
     * Must be called on the same Looper thread to which the receiver is attached.
+38 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.view;

import static android.os.IInputConstants.INVALID_INPUT_EVENT_ID;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.InputDevice.SOURCE_CLASS_NONE;
@@ -105,6 +106,7 @@ import android.graphics.Color;
import android.graphics.FrameInfo;
import android.graphics.HardwareRenderer;
import android.graphics.HardwareRenderer.FrameDrawingCallback;
import android.graphics.HardwareRendererObserver;
import android.graphics.Insets;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
@@ -1191,6 +1193,14 @@ public final class ViewRootImpl implements ViewParent,
                    }
                    mInputEventReceiver = new WindowInputEventReceiver(inputChannel,
                            Looper.myLooper());

                    if (mAttachInfo.mThreadedRenderer != null) {
                        InputMetricsListener listener =
                                new InputMetricsListener(mInputEventReceiver);
                        mHardwareRendererObserver = new HardwareRendererObserver(
                                listener, listener.data, mHandler, true /*waitForPresentTime*/);
                        mAttachInfo.mThreadedRenderer.addObserver(mHardwareRendererObserver);
                    }
                }

                view.assignParent(this);
@@ -8569,6 +8579,34 @@ public final class ViewRootImpl implements ViewParent,
    }
    WindowInputEventReceiver mInputEventReceiver;

    final class InputMetricsListener
            implements HardwareRendererObserver.OnFrameMetricsAvailableListener {
        public long[] data = new long[FrameMetrics.Index.FRAME_STATS_COUNT];

        private InputEventReceiver mReceiver;

        InputMetricsListener(InputEventReceiver receiver) {
            mReceiver = receiver;
        }

        @Override
        public void onFrameMetricsAvailable(int dropCountSinceLastInvocation) {
            final int inputEventId = (int) data[FrameMetrics.Index.INPUT_EVENT_ID];
            if (inputEventId == INVALID_INPUT_EVENT_ID) {
                return;
            }
            final long presentTime = data[FrameMetrics.Index.DISPLAY_PRESENT_TIME];
            if (presentTime <= 0) {
                // Present time is not available for this frame. If the present time is not
                // available, we cannot compute end-to-end input latency metrics.
                return;
            }
            final long gpuCompletedTime = data[FrameMetrics.Index.GPU_COMPLETED];
            mReceiver.reportLatencyInfo(inputEventId, gpuCompletedTime, presentTime);
        }
    }
    HardwareRendererObserver mHardwareRendererObserver;

    final class ConsumeBatchedInputRunnable implements Runnable {
        @Override
        public void run() {
+2 −1
Original line number Diff line number Diff line
@@ -121,7 +121,8 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener
        mChoreographer = choreographer;
        mSurfaceControlWrapper = surfaceControlWrapper;
        mHandler = handler;
        mObserver = new HardwareRendererObserver(this, mMetricsWrapper.getTiming(), handler);
        mObserver = new HardwareRendererObserver(
                this, mMetricsWrapper.getTiming(), handler, false /*waitForPresentTime*/);
        mTraceThresholdMissedFrames = traceThresholdMissedFrames;
        mTraceThresholdFrameTimeMillis = traceThresholdFrameTimeMillis;
        mListener = listener;
+3 −3
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@ public class HardwareRendererObserver {
     * @param handler the Handler to use when invoking callbacks
     */
    public HardwareRendererObserver(@NonNull OnFrameMetricsAvailableListener listener,
            @NonNull long[] frameMetrics, @NonNull Handler handler) {
            @NonNull long[] frameMetrics, @NonNull Handler handler, boolean waitForPresentTime) {
        if (handler == null || handler.getLooper() == null) {
            throw new NullPointerException("handler and its looper cannot be null");
        }
@@ -74,7 +74,7 @@ public class HardwareRendererObserver {
        mFrameMetrics = frameMetrics;
        mHandler = handler;
        mListener = listener;
        mNativePtr = new VirtualRefBasePtr(nCreateObserver());
        mNativePtr = new VirtualRefBasePtr(nCreateObserver(waitForPresentTime));
    }

    /*package*/ long getNativeInstance() {
@@ -98,6 +98,6 @@ public class HardwareRendererObserver {
        });
    }

    private native long nCreateObserver();
    private native long nCreateObserver(boolean waitForPresentTime);
    private static native int nGetNextBuffer(long nativePtr, long[] data);
}
Loading