Merge "Check mInputEventReceiver before sending timeline -- 2" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
234adf7cb2
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user