From 51aa189a267c265d3abc0786d4a301d27ad55525 Mon Sep 17 00:00:00 2001 From: John Reck Date: Wed, 30 Jan 2019 15:28:44 -0800 Subject: [PATCH] Have position listener only call when interesting Test: it compiled; HwAccelTest looked fine Change-Id: I193028791749811d5709d078f32efdebd7173d13 Fixes: 123656149 --- core/jni/android_view_RenderNode.cpp | 26 +++-- tests/HwAccelerationTest/AndroidManifest.xml | 10 ++ .../test/hwui/PositionListenerActivity.java | 98 +++++++++++++++++++ 3 files changed, 127 insertions(+), 7 deletions(-) create mode 100644 tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp index 0d75de9ee95f9..ce5512ba366a6 100644 --- a/core/jni/android_view_RenderNode.cpp +++ b/core/jni/android_view_RenderNode.cpp @@ -507,15 +507,15 @@ jmethodID gPositionListener_PositionChangedMethod; jmethodID gPositionListener_PositionLostMethod; static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject, - jlong renderNodePtr, jobject surfaceview) { - class SurfaceViewPositionUpdater : public RenderNode::PositionListener { + jlong renderNodePtr, jobject listener) { + class PositionListenerTrampoline : public RenderNode::PositionListener { public: - SurfaceViewPositionUpdater(JNIEnv* env, jobject surfaceview) { + PositionListenerTrampoline(JNIEnv* env, jobject listener) { env->GetJavaVM(&mVm); - mWeakRef = env->NewWeakGlobalRef(surfaceview); + mWeakRef = env->NewWeakGlobalRef(listener); } - virtual ~SurfaceViewPositionUpdater() { + virtual ~PositionListenerTrampoline() { jnienv()->DeleteWeakGlobalRef(mWeakRef); mWeakRef = nullptr; } @@ -539,9 +539,14 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject, bounds.roundOut(); } + if (mPreviousPosition == bounds) { + return; + } + mPreviousPosition = bounds; + incStrong(0); auto functor = std::bind( - std::mem_fn(&SurfaceViewPositionUpdater::doUpdatePositionAsync), this, + std::mem_fn(&PositionListenerTrampoline::doUpdatePositionAsync), this, (jlong) info.canvasContext.getFrameNumber(), (jint) bounds.left, (jint) bounds.top, (jint) bounds.right, (jint) bounds.bottom); @@ -552,6 +557,11 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject, virtual void onPositionLost(RenderNode& node, const TreeInfo* info) override { if (CC_UNLIKELY(!mWeakRef || (info && !info->updateWindowPositions))) return; + if (mPreviousPosition.isEmpty()) { + return; + } + mPreviousPosition.setEmpty(); + ATRACE_NAME("SurfaceView position lost"); JNIEnv* env = jnienv(); jobject localref = env->NewLocalRef(mWeakRef); @@ -561,6 +571,7 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject, return; } + // TODO: Remember why this is synchronous and then make a comment env->CallVoidMethod(localref, gPositionListener_PositionLostMethod, info ? info->canvasContext.getFrameNumber() : 0); env->DeleteLocalRef(localref); @@ -596,10 +607,11 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject, JavaVM* mVm; jobject mWeakRef; + uirenderer::Rect mPreviousPosition; }; RenderNode* renderNode = reinterpret_cast(renderNodePtr); - renderNode->setPositionListener(new SurfaceViewPositionUpdater(env, surfaceview)); + renderNode->setPositionListener(new PositionListenerTrampoline(env, listener)); } // ---------------------------------------------------------------------------- diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml index f330b8353b500..1a4ec94d77b41 100644 --- a/tests/HwAccelerationTest/AndroidManifest.xml +++ b/tests/HwAccelerationTest/AndroidManifest.xml @@ -1027,5 +1027,15 @@ + + + + + + + diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java new file mode 100644 index 0000000000000..316aad343d19b --- /dev/null +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2010 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 com.android.test.hwui; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.RenderNode; +import android.os.Bundle; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.ScrollView; +import android.widget.TextView; + +@SuppressWarnings({"UnusedDeclaration"}) +public class PositionListenerActivity extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + final LinearLayout layout = new LinearLayout(this); + layout.setOrientation(LinearLayout.VERTICAL); + + ProgressBar spinner = new ProgressBar(this, null, android.R.attr.progressBarStyleLarge); + layout.addView(spinner); + + ScrollView scrollingThing = new ScrollView(this); + scrollingThing.addView(new MyPositionReporter(this)); + layout.addView(scrollingThing); + + setContentView(layout); + } + + static class MyPositionReporter extends TextView implements RenderNode.PositionUpdateListener { + RenderNode mNode; + int mCurrentCount = 0; + int mTranslateY = 0; + + MyPositionReporter(Context c) { + super(c); + mNode = new RenderNode("positionListener"); + mNode.requestPositionUpdates(this); + setTextAlignment(TEXT_ALIGNMENT_VIEW_START); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + setMeasuredDimension(getMeasuredWidth(), 10000); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + mNode.setLeftTopRightBottom(left, top, right, bottom); + } + + @Override + protected void onDraw(Canvas canvas) { + ScrollView parent = (ScrollView) getParent(); + canvas.translate(0, parent.getScrollY()); + super.onDraw(canvas); + canvas.translate(0, -parent.getScrollY()); + // Inject our listener proxy + canvas.drawRenderNode(mNode); + } + + @Override + public void positionChanged(long frameNumber, int left, int top, int right, int bottom) { + post(() -> { + mCurrentCount++; + setText(String.format("%d: Position [%d, %d, %d, %d]", mCurrentCount, + left, top, right, bottom)); + }); + } + + @Override + public void positionLost(long frameNumber) { + post(() -> { + mCurrentCount++; + setText(mCurrentCount + " No position"); + }); + } + } +}