Telemtry: hooks "chrome.gpuBenchmarking.smoothScrollBy" with java on android.
In order to provide more realistic benchmarks, instead of shortcutting in native via mousewheels, let Telemetry cross all the boundaries and synthesize MotionEvents all the way up in java. BUG= TEST=./tools/perf/run_multipage_benchmarks --browser=system smoothness_benchmark tools/perf/page_sets/key_mobile_sites.json Review URL: https://chromiumcodereview.appspot.com/11415227 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@173457 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
content
browser
android
renderer_host
port
public
android
java
src
org
chromium
content
@ -595,6 +595,17 @@ void ContentViewCoreImpl::ShowDisambiguationPopup(
|
||||
java_bitmap.obj());
|
||||
}
|
||||
|
||||
ScopedJavaLocalRef<jobject> ContentViewCoreImpl::CreateSmoothScroller(
|
||||
bool scroll_down, int mouse_event_x, int mouse_event_y) {
|
||||
JNIEnv* env = AttachCurrentThread();
|
||||
|
||||
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
|
||||
if (obj.is_null())
|
||||
return ScopedJavaLocalRef<jobject>();
|
||||
return Java_ContentViewCore_createSmoothScroller(
|
||||
env, obj.obj(), scroll_down, mouse_event_x, mouse_event_y);
|
||||
}
|
||||
|
||||
gfx::Rect ContentViewCoreImpl::GetBounds() const {
|
||||
JNIEnv* env = AttachCurrentThread();
|
||||
ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "base/android/jni_android.h"
|
||||
#include "base/android/jni_helper.h"
|
||||
#include "base/basictypes.h"
|
||||
#include "base/compiler_specific.h"
|
||||
@ -233,6 +234,11 @@ class ContentViewCoreImpl : public ContentViewCore,
|
||||
void ShowDisambiguationPopup(
|
||||
const gfx::Rect& target_rect, const SkBitmap& zoomed_bitmap);
|
||||
|
||||
// Creates a java-side smooth scroller. Used by
|
||||
// chrome.gpuBenchmarking.smoothScrollBy.
|
||||
base::android::ScopedJavaLocalRef<jobject> CreateSmoothScroller(
|
||||
bool scroll_down, int mouse_event_x, int mouse_event_y);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Methods called from native code
|
||||
// --------------------------------------------------------------------------
|
||||
|
@ -26,21 +26,13 @@ bool BasicMouseWheelSmoothScrollGesture::ForwardInputEvents(
|
||||
if (pixels_scrolled_ >= pixels_to_scroll_)
|
||||
return false;
|
||||
|
||||
double positionDelta = 10;
|
||||
if (!last_tick_time_.is_null()) {
|
||||
RenderWidgetHostImpl* hostImpl = RenderWidgetHostImpl::From(host);
|
||||
double desiredIntervalMs = hostImpl->SyntheticScrollMessageInterval();
|
||||
double velocity = 10 / desiredIntervalMs;
|
||||
double timeDelta = (now - last_tick_time_).InMillisecondsF();
|
||||
positionDelta = velocity * timeDelta;
|
||||
}
|
||||
|
||||
last_tick_time_ = now;
|
||||
double position_delta = Tick(
|
||||
now, RenderWidgetHostImpl::From(host)->SyntheticScrollMessageInterval());
|
||||
|
||||
WebKit::WebMouseWheelEvent event;
|
||||
event.type = WebKit::WebInputEvent::MouseWheel;
|
||||
event.hasPreciseScrollingDeltas = 1;
|
||||
event.deltaY = scroll_down_ ? -positionDelta : positionDelta;
|
||||
event.deltaY = scroll_down_ ? -position_delta : position_delta;
|
||||
// TODO(vollick): find a proper way to access
|
||||
// WebCore::WheelEvent::tickMultiplier.
|
||||
event.wheelTicksY = event.deltaY / 120;
|
||||
|
@ -27,7 +27,6 @@ class BasicMouseWheelSmoothScrollGesture : public SmoothScrollGesture {
|
||||
int pixels_to_scroll_;
|
||||
int mouse_event_x_;
|
||||
int mouse_event_y_;
|
||||
base::TimeTicks last_tick_time_;
|
||||
};
|
||||
|
||||
} // namespace content
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "content/browser/renderer_host/compositor_impl_android.h"
|
||||
#include "content/browser/renderer_host/image_transport_factory_android.h"
|
||||
#include "content/browser/renderer_host/render_widget_host_impl.h"
|
||||
#include "content/browser/renderer_host/smooth_scroll_gesture_android.h"
|
||||
#include "content/browser/renderer_host/surface_texture_transport_client_android.h"
|
||||
#include "content/common/android/device_info.h"
|
||||
#include "content/common/gpu/client/gl_helper.h"
|
||||
@ -383,6 +384,16 @@ void RenderWidgetHostViewAndroid::ShowDisambiguationPopup(
|
||||
content_view_core_->ShowDisambiguationPopup(target_rect, zoomed_bitmap);
|
||||
}
|
||||
|
||||
SmoothScrollGesture* RenderWidgetHostViewAndroid::CreateSmoothScrollGesture(
|
||||
bool scroll_down, int pixels_to_scroll, int mouse_event_x,
|
||||
int mouse_event_y) {
|
||||
return new SmoothScrollGestureAndroid(
|
||||
pixels_to_scroll,
|
||||
GetRenderWidgetHost(),
|
||||
content_view_core_->CreateSmoothScroller(
|
||||
scroll_down, mouse_event_x, mouse_event_y));
|
||||
}
|
||||
|
||||
void RenderWidgetHostViewAndroid::OnAcceleratedCompositingStateChange() {
|
||||
}
|
||||
|
||||
|
@ -139,6 +139,9 @@ class RenderWidgetHostViewAndroid : public RenderWidgetHostViewBase {
|
||||
const gfx::Size& content_size) OVERRIDE;
|
||||
virtual void ShowDisambiguationPopup(const gfx::Rect& target_rect,
|
||||
const SkBitmap& zoomed_bitmap) OVERRIDE;
|
||||
virtual SmoothScrollGesture* CreateSmoothScrollGesture(
|
||||
bool scroll_down, int pixels_to_scroll, int mouse_event_x,
|
||||
int mouse_event_y) OVERRIDE;
|
||||
|
||||
// Non-virtual methods
|
||||
void SetContentViewCore(ContentViewCoreImpl* content_view_core);
|
||||
|
@ -424,7 +424,7 @@ void RenderWidgetHostViewBase::UpdateScreenInfo(gfx::NativeView view) {
|
||||
current_device_scale_factor_ = display.device_scale_factor();
|
||||
if (impl)
|
||||
impl->NotifyScreenInfoChanged();
|
||||
}
|
||||
}
|
||||
|
||||
SmoothScrollGesture* RenderWidgetHostViewBase::CreateSmoothScrollGesture(
|
||||
bool scroll_down, int pixels_to_scroll, int mouse_event_x,
|
||||
|
@ -0,0 +1,68 @@
|
||||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "content/browser/renderer_host/smooth_scroll_gesture_android.h"
|
||||
|
||||
#include "base/debug/trace_event.h"
|
||||
#include "content/browser/renderer_host/render_widget_host_impl.h"
|
||||
#include "jni/SmoothScroller_jni.h"
|
||||
|
||||
namespace {
|
||||
bool g_jni_initialized = false;
|
||||
|
||||
void RegisterNativesIfNeeded(JNIEnv* env) {
|
||||
if (!g_jni_initialized) {
|
||||
content::RegisterNativesImpl(env);
|
||||
g_jni_initialized = true;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace content {
|
||||
|
||||
SmoothScrollGestureAndroid::SmoothScrollGestureAndroid(
|
||||
int pixels_to_scroll,
|
||||
RenderWidgetHost* rwh,
|
||||
base::android::ScopedJavaLocalRef<jobject> java_scroller)
|
||||
: pixels_scrolled_(0),
|
||||
has_started_(false),
|
||||
pixels_to_scroll_(pixels_to_scroll),
|
||||
rwh_(rwh),
|
||||
java_scroller_(java_scroller) {
|
||||
JNIEnv* env = base::android::AttachCurrentThread();
|
||||
RegisterNativesIfNeeded(env);
|
||||
}
|
||||
|
||||
SmoothScrollGestureAndroid::~SmoothScrollGestureAndroid() {
|
||||
}
|
||||
|
||||
bool SmoothScrollGestureAndroid::ForwardInputEvents(
|
||||
base::TimeTicks now, RenderWidgetHost* host) {
|
||||
if (!has_started_) {
|
||||
has_started_ = true;
|
||||
JNIEnv* env = base::android::AttachCurrentThread();
|
||||
Java_SmoothScroller_start(
|
||||
env, java_scroller_.obj(), reinterpret_cast<int>(this));
|
||||
}
|
||||
|
||||
TRACE_COUNTER_ID1(
|
||||
"gpu", "smooth_scroll_by_pixels_scrolled", this, pixels_scrolled_);
|
||||
|
||||
return pixels_scrolled_ < pixels_to_scroll_;
|
||||
}
|
||||
|
||||
double SmoothScrollGestureAndroid::Tick(JNIEnv* env, jobject obj) {
|
||||
double delta = SmoothScrollGesture::Tick(
|
||||
base::TimeTicks::HighResNow(),
|
||||
RenderWidgetHostImpl::From(rwh_)->SyntheticScrollMessageInterval());
|
||||
pixels_scrolled_ += delta;
|
||||
return delta;
|
||||
}
|
||||
|
||||
bool SmoothScrollGestureAndroid::HasFinished(JNIEnv* env, jobject obj) {
|
||||
return pixels_scrolled_ >= pixels_to_scroll_;
|
||||
}
|
||||
|
||||
} // namespace content
|
||||
|
@ -0,0 +1,47 @@
|
||||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef CONTENT_BROWSER_RENDERER_HOST_SMOOTH_GESTURE_ANDROID_H_
|
||||
#define CONTENT_BROWSER_RENDERER_HOST_SMOOTH_GESTURE_ANDROID_H_
|
||||
|
||||
#include "base/android/jni_android.h"
|
||||
#include "base/time.h"
|
||||
#include "content/port/browser/smooth_scroll_gesture.h"
|
||||
|
||||
namespace content {
|
||||
|
||||
class ContentViewCore;
|
||||
class RenderWidgetHost;
|
||||
|
||||
class SmoothScrollGestureAndroid : public SmoothScrollGesture {
|
||||
public:
|
||||
SmoothScrollGestureAndroid(
|
||||
int pixels_to_scroll,
|
||||
RenderWidgetHost* rwh,
|
||||
base::android::ScopedJavaLocalRef<jobject> java_scroller);
|
||||
|
||||
// Called by the java side once the TimeAnimator ticks.
|
||||
double Tick(JNIEnv* env, jobject obj);
|
||||
bool HasFinished(JNIEnv* env, jobject obj);
|
||||
|
||||
// SmoothScrollGesture
|
||||
virtual bool ForwardInputEvents(base::TimeTicks now,
|
||||
RenderWidgetHost* host) OVERRIDE;
|
||||
|
||||
private:
|
||||
virtual ~SmoothScrollGestureAndroid();
|
||||
|
||||
int pixels_scrolled_;
|
||||
bool has_started_;
|
||||
|
||||
int pixels_to_scroll_;
|
||||
RenderWidgetHost* rwh_;
|
||||
base::android::ScopedJavaGlobalRef<jobject> java_scroller_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(SmoothScrollGestureAndroid);
|
||||
};
|
||||
|
||||
} // namespace content
|
||||
|
||||
#endif // CONTENT_BROWSER_RENDERER_HOST_SMOOTH_GESTURE_ANDROID_H_
|
@ -33,6 +33,7 @@
|
||||
'sources': [
|
||||
'port/browser/render_view_host_delegate_view.h',
|
||||
'port/browser/render_widget_host_view_port.h',
|
||||
'port/browser/smooth_scroll_gesture.cc',
|
||||
'port/browser/smooth_scroll_gesture.h',
|
||||
'public/browser/access_token_store.h',
|
||||
'public/browser/android/compositor.h',
|
||||
@ -741,6 +742,8 @@
|
||||
'browser/renderer_host/render_widget_host_view_mac.mm',
|
||||
'browser/renderer_host/render_widget_host_view_win.cc',
|
||||
'browser/renderer_host/render_widget_host_view_win.h',
|
||||
'browser/renderer_host/smooth_scroll_gesture_android.cc',
|
||||
'browser/renderer_host/smooth_scroll_gesture_android.h',
|
||||
'browser/renderer_host/socket_stream_dispatcher_host.cc',
|
||||
'browser/renderer_host/socket_stream_dispatcher_host.h',
|
||||
'browser/renderer_host/socket_stream_host.cc',
|
||||
|
@ -25,6 +25,7 @@
|
||||
'public/android/java/src/org/chromium/content/browser/LoadUrlParams.java',
|
||||
'public/android/java/src/org/chromium/content/browser/LocationProvider.java',
|
||||
'public/android/java/src/org/chromium/content/browser/SandboxedProcessLauncher.java',
|
||||
'public/android/java/src/org/chromium/content/browser/SmoothScroller.java',
|
||||
'public/android/java/src/org/chromium/content/browser/TouchPoint.java',
|
||||
'public/android/java/src/org/chromium/content/browser/WebContentsObserverAndroid.java',
|
||||
'public/android/java/src/org/chromium/content/common/CommandLine.java',
|
||||
|
22
content/port/browser/smooth_scroll_gesture.cc
Normal file
22
content/port/browser/smooth_scroll_gesture.cc
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "content/port/browser/smooth_scroll_gesture.h"
|
||||
|
||||
namespace content {
|
||||
|
||||
double SmoothScrollGesture::Tick(
|
||||
base::TimeTicks now, double desired_interval_ms) {
|
||||
double position_delta = 10;
|
||||
if (!last_tick_time_.is_null()) {
|
||||
double velocity = 10 / desired_interval_ms;
|
||||
double time_delta = (now - last_tick_time_).InMillisecondsF();
|
||||
position_delta = velocity * time_delta;
|
||||
}
|
||||
|
||||
last_tick_time_ = now;
|
||||
return position_delta;
|
||||
}
|
||||
|
||||
} // namespace content
|
@ -14,10 +14,9 @@ class RenderWidgetHost;
|
||||
|
||||
// This is a base class representing a single scroll gesture. These gestures are
|
||||
// paired with the rendering benchmarking system to (automatically) measure how
|
||||
// smoothnly chrome is responding to user input.
|
||||
// smoothly chrome is responding to user input.
|
||||
class SmoothScrollGesture : public base::RefCounted<SmoothScrollGesture> {
|
||||
public:
|
||||
|
||||
// When called, the gesture should compute its state at the provided timestamp
|
||||
// and send the right input events to the provided RenderWidgetHost to
|
||||
// simulate the gesture having run up to that point in time.
|
||||
@ -29,6 +28,11 @@ class SmoothScrollGesture : public base::RefCounted<SmoothScrollGesture> {
|
||||
protected:
|
||||
friend class base::RefCounted<SmoothScrollGesture>;
|
||||
virtual ~SmoothScrollGesture() {}
|
||||
|
||||
double Tick(base::TimeTicks now, double desired_interval_ms);
|
||||
|
||||
private:
|
||||
base::TimeTicks last_tick_time_;
|
||||
};
|
||||
|
||||
} // namespace content
|
||||
|
@ -1936,6 +1936,13 @@ public class ContentViewCore implements MotionEventDelegate {
|
||||
mPopupZoomer.show(targetRect);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@CalledByNative
|
||||
private SmoothScroller createSmoothScroller(boolean scrollDown, int mouseEventX,
|
||||
int mouseEventY) {
|
||||
return new SmoothScroller(this, scrollDown, mouseEventX, mouseEventY);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@CalledByNative
|
||||
private void onSelectionChanged(String text) {
|
||||
|
@ -0,0 +1,120 @@
|
||||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package org.chromium.content.browser;
|
||||
|
||||
import android.animation.TimeAnimator;
|
||||
import android.animation.TimeAnimator.TimeListener;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import org.chromium.base.CalledByNative;
|
||||
import org.chromium.base.JNINamespace;
|
||||
|
||||
/**
|
||||
* Provides a Java-side implementation for chrome.gpuBenchmarking.smoothScrollBy.
|
||||
*/
|
||||
@JNINamespace("content")
|
||||
public class SmoothScroller {
|
||||
final ContentViewCore mContentViewCore;
|
||||
final boolean mScrollDown;
|
||||
final float mMouseEventX;
|
||||
final float mMouseEventY;
|
||||
|
||||
final Handler mHandler = new Handler(Looper.getMainLooper());
|
||||
|
||||
TimeAnimator mTimeAnimator;
|
||||
|
||||
int mNativePtr;
|
||||
long mDownTime;
|
||||
float mCurrentY;
|
||||
|
||||
boolean mHasSentUp = false;
|
||||
|
||||
SmoothScroller(ContentViewCore contentViewCore, boolean scrollDown,
|
||||
int mouseEventX, int mouseEventY) {
|
||||
mContentViewCore = contentViewCore;
|
||||
mScrollDown = scrollDown;
|
||||
float scale = mContentViewCore.getScale();
|
||||
mMouseEventX = mouseEventX * scale;
|
||||
mMouseEventY = mouseEventY * scale;
|
||||
mCurrentY = mMouseEventY;
|
||||
}
|
||||
|
||||
@CalledByNative
|
||||
void start(int nativePtr) {
|
||||
assert mNativePtr == 0;
|
||||
mNativePtr = nativePtr;
|
||||
|
||||
mDownTime = SystemClock.uptimeMillis();
|
||||
MotionEvent event = MotionEvent.obtain(mDownTime, mDownTime,
|
||||
MotionEvent.ACTION_DOWN, mMouseEventX, mCurrentY, 0);
|
||||
mContentViewCore.onTouchEvent(event);
|
||||
event.recycle();
|
||||
|
||||
Runnable runnable = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) ?
|
||||
createJBRunnable() : createPreJBRunnable();
|
||||
mHandler.post(runnable);
|
||||
}
|
||||
|
||||
boolean sendEvent(long time) {
|
||||
float delta = nativeTick(mNativePtr) * mContentViewCore.getScale();
|
||||
if (delta != 0) {
|
||||
mCurrentY += mScrollDown ? -delta : delta;
|
||||
|
||||
MotionEvent event = MotionEvent.obtain(mDownTime, time,
|
||||
MotionEvent.ACTION_MOVE, mMouseEventX, mCurrentY, 0);
|
||||
mContentViewCore.onTouchEvent(event);
|
||||
event.recycle();
|
||||
}
|
||||
boolean hasFinished = nativeHasFinished(mNativePtr);
|
||||
if (hasFinished && !mHasSentUp) {
|
||||
mHasSentUp = true;
|
||||
MotionEvent event = MotionEvent.obtain(mDownTime, time,
|
||||
MotionEvent.ACTION_UP, mMouseEventX, mCurrentY, 0);
|
||||
mContentViewCore.onTouchEvent(event);
|
||||
event.recycle();
|
||||
}
|
||||
return !hasFinished;
|
||||
}
|
||||
|
||||
private Runnable createJBRunnable() {
|
||||
// On JB, we rely on TimeAnimator to send events tied with vsync.
|
||||
return new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mTimeAnimator = new TimeAnimator();
|
||||
mTimeAnimator.setTimeListener(new TimeListener() {
|
||||
@Override
|
||||
public void onTimeUpdate(TimeAnimator animation, long totalTime,
|
||||
long deltaTime) {
|
||||
if (!sendEvent(mDownTime + totalTime)) {
|
||||
mTimeAnimator.end();
|
||||
}
|
||||
}
|
||||
});
|
||||
mTimeAnimator.start();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Runnable createPreJBRunnable() {
|
||||
// Pre-JB there's no TimeAnimator, so we keep posting messages.
|
||||
return new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!sendEvent(SystemClock.uptimeMillis())) {
|
||||
mHandler.post(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private native int nativeTick(int nativeSmoothScrollGestureAndroid);
|
||||
private native boolean nativeHasFinished(int nativeSmoothScrollGestureAndroid);
|
||||
}
|
Reference in New Issue
Block a user