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

Commit 234adf7c authored by Siarhei Vishniakou's avatar Siarhei Vishniakou Committed by Android (Google) Code Review
Browse files

Merge "Check mInputEventReceiver before sending timeline -- 2" into sc-dev

parents bc8505c4 b3ea67fa
Loading
Loading
Loading
Loading
+22 −9
Original line number Diff line number Diff line
@@ -1201,8 +1201,7 @@ public final class ViewRootImpl implements ViewParent,
                            Looper.myLooper());

                    if (mAttachInfo.mThreadedRenderer != null) {
                        InputMetricsListener listener =
                                new InputMetricsListener(mInputEventReceiver);
                        InputMetricsListener listener = new InputMetricsListener();
                        mHardwareRendererObserver = new HardwareRendererObserver(
                                listener, listener.data, mHandler, true /*waitForPresentTime*/);
                        mAttachInfo.mThreadedRenderer.addObserver(mHardwareRendererObserver);
@@ -1414,6 +1413,9 @@ public final class ViewRootImpl implements ViewParent,
                if (mAttachInfo.mThreadedRenderer != null) {
                    mAttachInfo.mHardwareAccelerated =
                            mAttachInfo.mHardwareAccelerationRequested = true;
                    if (mHardwareRendererObserver != null) {
                        mAttachInfo.mThreadedRenderer.addObserver(mHardwareRendererObserver);
                    }
                }
            }
        }
@@ -8118,6 +8120,9 @@ public final class ViewRootImpl implements ViewParent,
        ThreadedRenderer hardwareRenderer = mAttachInfo.mThreadedRenderer;

        if (hardwareRenderer != null) {
            if (mHardwareRendererObserver != null) {
                hardwareRenderer.removeObserver(mHardwareRendererObserver);
            }
            if (mView != null) {
                hardwareRenderer.destroyHardwareResources(mView);
            }
@@ -8619,18 +8624,12 @@ public final class ViewRootImpl implements ViewParent,
            super.dispose();
        }
    }
    WindowInputEventReceiver mInputEventReceiver;
    private 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];
@@ -8643,6 +8642,20 @@ public final class ViewRootImpl implements ViewParent,
                // available, we cannot compute end-to-end input latency metrics.
                return;
            }
            final long gpuCompletedTime = data[FrameMetrics.Index.GPU_COMPLETED];
            if (mInputEventReceiver == null) {
                return;
            }
            if (gpuCompletedTime >= presentTime) {
                final double discrepancyMs = (gpuCompletedTime - presentTime) * 1E-6;
                final long vsyncId = data[FrameMetrics.Index.FRAME_TIMELINE_VSYNC_ID];
                Log.w(TAG, "Not reporting timeline because gpuCompletedTime is " + discrepancyMs
                        + "ms ahead of presentTime. FRAME_TIMELINE_VSYNC_ID=" + vsyncId
                        + ", INPUT_EVENT_ID=" + inputEventId);
                // TODO(b/186664409): figure out why this sometimes happens
                return;
            }
            mInputEventReceiver.reportTimeline(inputEventId, gpuCompletedTime, presentTime);
        }
    }
    HardwareRendererObserver mHardwareRendererObserver;
+12 −12
Original line number Diff line number Diff line
@@ -241,13 +241,13 @@ status_t NativeInputEventReceiver::processOutboundEvents() {
        }

        // Some other error. Give up
        ALOGW("Failed to send outbound event on channel '%s'.  status=%d",
              getInputChannelName().c_str(), status);
        ALOGW("Failed to send outbound event on channel '%s'.  status=%s(%d)",
              getInputChannelName().c_str(), statusToString(status).c_str(), status);
        if (status != DEAD_OBJECT) {
            JNIEnv* env = AndroidRuntime::getJNIEnv();
            std::string message =
                    android::base::StringPrintf("Failed to send outbound event.  status=%d",
                                                status);
                    android::base::StringPrintf("Failed to send outbound event.  status=%s(%d)",
                                                statusToString(status).c_str(), status);
            jniThrowRuntimeException(env, message.c_str());
            mMessageQueue->raiseAndClearException(env, "finishInputEvent");
        }
@@ -319,8 +319,8 @@ status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
        status_t status = mInputConsumer.consume(&mInputEventFactory,
                consumeBatches, frameTime, &seq, &inputEvent);
        if (status != OK && status != WOULD_BLOCK) {
            ALOGE("channel '%s' ~ Failed to consume input event.  status=%d",
                  getInputChannelName().c_str(), status);
            ALOGE("channel '%s' ~ Failed to consume input event.  status=%s(%d)",
                  getInputChannelName().c_str(), statusToString(status).c_str(), status);
            return status;
        }

@@ -502,9 +502,9 @@ static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
            receiverWeak, inputChannel, messageQueue);
    status_t status = receiver->initialize();
    if (status) {
        std::string message =
                android::base::StringPrintf("Failed to initialize input event receiver.  status=%d",
                                            status);
        std::string message = android::base::
                StringPrintf("Failed to initialize input event receiver.  status=%s(%d)",
                             statusToString(status).c_str(), status);
        jniThrowRuntimeException(env, message.c_str());
        return 0;
    }
@@ -531,7 +531,7 @@ static void nativeFinishInputEvent(JNIEnv* env, jclass clazz, jlong receiverPtr,
    if (status != DEAD_OBJECT) {
        std::string message =
                android::base::StringPrintf("Failed to finish input event.  status=%s(%d)",
                                            strerror(-status), status);
                                            statusToString(status).c_str(), status);
        jniThrowRuntimeException(env, message.c_str());
    }
}
@@ -564,8 +564,8 @@ static jboolean nativeConsumeBatchedInputEvents(JNIEnv* env, jclass clazz, jlong
            &consumedBatch);
    if (status && status != DEAD_OBJECT && !env->ExceptionCheck()) {
        std::string message =
                android::base::StringPrintf("Failed to consume batched input event.  status=%d",
                                            status);
                android::base::StringPrintf("Failed to consume batched input event.  status=%s(%d)",
                                            statusToString(status).c_str(), status);
        jniThrowRuntimeException(env, message.c_str());
        return JNI_FALSE;
    }
+17 −0
Original line number Diff line number Diff line
@@ -145,4 +145,21 @@ class InputEventSenderAndReceiverTest {
        val received = mSender.getTimeline()
        assertEquals(sent, received)
    }

    // If an invalid timeline is sent, the channel should get closed. This helps surface any
    // app-originating bugs early, and forces the work-around to happen in the early stages of the
    // event processing.
    @Test
    fun testSendAndReceiveInvalidTimeline() {
        val sent = TestInputEventSender.Timeline(
            inputEventId = 1, gpuCompletedTime = 3, presentTime = 2)
        mReceiver.reportTimeline(sent.inputEventId, sent.gpuCompletedTime, sent.presentTime)
        val received = mSender.getTimeline()
        assertEquals(null, received)
        // Sender will no longer receive callbacks for this fd, even if receiver sends a valid
        // timeline later
        mReceiver.reportTimeline(2 /*inputEventId*/, 3 /*gpuCompletedTime*/, 4 /*presentTime*/)
        val receivedSecondTimeline = mSender.getTimeline()
        assertEquals(null, receivedSecondTimeline)
    }
}