Merge "Check mInputEventReceiver before sending timeline -- 2" into sc-dev am: 234adf7cb2 am: 12318a45bd

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14350504

Change-Id: I55ef308fcebb9323496916fffa8d7b8af24ff3ae
This commit is contained in:
Siarhei Vishniakou
2021-05-19 23:20:43 +00:00
committed by Automerger Merge Worker
3 changed files with 51 additions and 21 deletions

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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)
}
}