Commit 6b3ec837 authored by fsamuel's avatar fsamuel Committed by Commit bot

Implement LatencyInfo StructTraits

This CL implements LatencyInfo mojom types, and associated
StructTraits for serialization and deserialization. This will be used
by cc::CompositorFrameMetadata and ultimately cc::CompositorFrame
serialization/deserialization over mojo.

BUG=611802

Review-Url: https://codereview.chromium.org/2040733002
Cr-Commit-Position: refs/heads/master@{#398211}
parent 535e76ff
......@@ -9,7 +9,7 @@ public_headers = [
"//base/time/time.h",
]
traits_headers = [ "//ipc/ipc_message_utils.h" ]
deps = [
public_deps = [
"//ipc",
]
......
......@@ -379,8 +379,8 @@ test("events_unittests") {
":gesture_detection",
":test_support",
"//base",
"//base/test:run_all_unittests",
"//base/test:test_support",
"//mojo/edk/test:run_all_unittests",
"//skia",
"//testing/gmock",
"//testing/gtest",
......@@ -396,14 +396,18 @@ test("events_unittests") {
"blink/input_scroll_elasticity_controller_unittest.cc",
"gestures/blink/web_gesture_curve_impl_unittest.cc",
"ipc/latency_info_param_traits_unittest.cc",
"mojo/struct_traits_unittest.cc",
]
deps += [
"//cc",
"//ipc:test_support",
"//mojo/edk/system",
"//mojo/public/cpp/bindings",
"//third_party/WebKit/public:blink_headers",
"//ui/events/blink",
"//ui/events/gestures/blink",
"//ui/events/ipc",
"//ui/events/mojo:test_interfaces",
]
}
......
......@@ -2,3 +2,12 @@ include_rules = [
"+ui/display",
"+ui/gfx",
]
specific_include_rules = {
"run_all_unittests\.cc": [
"+mojo/edk/embedder/embedder.h",
],
"latency_info\.h": [
"+mojo/public",
]
}
......@@ -19,10 +19,17 @@
#if !defined(OS_IOS)
#include "ipc/ipc_param_traits.h" // nogncheck
#include "mojo/public/cpp/bindings/struct_traits.h" // nogncheck
#endif
namespace ui {
#if !defined(OS_IOS)
namespace mojom {
class LatencyInfo;
}
#endif
// When adding new components, or new metrics based on LatencyInfo,
// please update latency_info.dot.
enum LatencyComponentType {
......@@ -129,7 +136,7 @@ class EVENTS_BASE_EXPORT LatencyInfo {
// Empirically determined constant based on a typical scroll sequence.
enum { kTypicalMaxComponentsPerLatencyInfo = 10 };
enum { kMaxInputCoordinates = 2 };
enum : size_t { kMaxInputCoordinates = 2 };
// Map a Latency Component (with a component-specific int64_t id) to a
// component info.
......@@ -240,6 +247,7 @@ class EVENTS_BASE_EXPORT LatencyInfo {
#if !defined(OS_IOS)
friend struct IPC::ParamTraits<ui::LatencyInfo>;
friend struct mojo::StructTraits<ui::mojom::LatencyInfo, ui::LatencyInfo>;
#endif
};
......
......@@ -2,6 +2,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//mojo/public/tools/bindings/mojom.gni")
# GYP version: mojo/mojo_converters.gypi:mojo_input_events_lib
component("mojo") {
output_name = "input_events"
......@@ -25,3 +27,24 @@ component("mojo") {
"//ui/gfx/geometry/mojo",
]
}
mojom("interfaces") {
sources = [
"latency_info.mojom",
]
public_deps = [
"//mojo/common:common_custom_types",
]
}
mojom("test_interfaces") {
testonly = true
sources = [
"traits_test_service.mojom",
]
public_deps = [
":interfaces",
]
}
include_rules = [
"+components/mus/public/interfaces",
"+mojo/public",
"+ui/events",
"+ui/gfx/geometry/mojo",
]
// Copyright 2016 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.
module ui.mojom;
import "mojo/common/common_custom_types.mojom";
enum LatencyComponentType {
// ---------------------------BEGIN COMPONENT-------------------------------
// BEGIN COMPONENT is when we show the latency begin in chrome://tracing.
// Timestamp when the input event is sent from RenderWidgetHost to renderer.
INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
// In threaded scrolling, main thread scroll listener update is async to
// scroll processing in impl thread. This is the timestamp when we consider
// the main thread scroll listener update is begun.
LATENCY_BEGIN_SCROLL_LISTENER_UPDATE_MAIN_COMPONENT,
// ---------------------------NORMAL COMPONENT-------------------------------
// The original timestamp of the touch event which converts to scroll update.
INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
// The original timestamp of the touch event which converts to the *first*
// scroll update in a scroll gesture sequence.
INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
// Original timestamp for input event (e.g. timestamp from kernel).
INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
// Timestamp when the UI event is created.
INPUT_EVENT_LATENCY_UI_COMPONENT,
// Timestamp when the event is dispatched on the main thread of the renderer.
INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT,
// This is special component indicating there is rendering scheduled for
// the event associated with this LatencyInfo on main thread.
INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN_COMPONENT,
// This is special component indicating there is rendering scheduled for
// the event associated with this LatencyInfo on impl thread.
INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT,
// Timestamp when a scroll update is forwarded to the main thread.
INPUT_EVENT_LATENCY_FORWARD_SCROLL_UPDATE_TO_MAIN_COMPONENT,
// Timestamp when the event's ack is received by the RWH.
INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT,
// Frame number when a window snapshot was requested. The snapshot
// is taken when the rendering results actually reach the screen.
WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT,
// Timestamp when a tab is requested to be shown.
TAB_SHOW_COMPONENT,
// Timestamp when the frame is swapped in renderer.
INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT,
// Timestamp of when the browser process receives a buffer swap notification
// from the renderer.
INPUT_EVENT_BROWSER_RECEIVED_RENDERER_SWAP_COMPONENT,
// Timestamp of when the gpu service began swap buffers, unlike
// INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT which measures after.
INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT,
// Timestamp of when the gesture scroll update is generated from a mouse wheel
// event.
INPUT_EVENT_LATENCY_GENERATE_SCROLL_UPDATE_FROM_MOUSE_WHEEL,
// ---------------------------TERMINAL COMPONENT-----------------------------
// TERMINAL COMPONENT is when we show the latency end in chrome://tracing.
// Timestamp when the mouse event is acked from renderer and it does not
// cause any rendering scheduled.
INPUT_EVENT_LATENCY_TERMINATED_MOUSE_COMPONENT,
// Timestamp when the mouse wheel event is acked from renderer and it does not
// cause any rendering scheduled.
INPUT_EVENT_LATENCY_TERMINATED_MOUSE_WHEEL_COMPONENT,
// Timestamp when the keyboard event is acked from renderer and it does not
// cause any rendering scheduled.
INPUT_EVENT_LATENCY_TERMINATED_KEYBOARD_COMPONENT,
// Timestamp when the touch event is acked from renderer and it does not
// cause any rendering scheduled and does not generate any gesture event.
INPUT_EVENT_LATENCY_TERMINATED_TOUCH_COMPONENT,
// Timestamp when the gesture event is acked from renderer, and it does not
// cause any rendering scheduled.
INPUT_EVENT_LATENCY_TERMINATED_GESTURE_COMPONENT,
// Timestamp when the frame is swapped (i.e. when the rendering caused by
// input event actually takes effect).
INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT,
// This component indicates that the input causes a commit to be scheduled
// but the commit failed.
INPUT_EVENT_LATENCY_TERMINATED_COMMIT_FAILED_COMPONENT,
// This component indicates that the input causes a commit to be scheduled
// but the commit was aborted since it carried no new information.
INPUT_EVENT_LATENCY_TERMINATED_COMMIT_NO_UPDATE_COMPONENT,
// This component indicates that the input causes a swap to be scheduled
// but the swap failed.
INPUT_EVENT_LATENCY_TERMINATED_SWAP_FAILED_COMPONENT,
LATENCY_COMPONENT_TYPE_LAST =
INPUT_EVENT_LATENCY_TERMINATED_SWAP_FAILED_COMPONENT,
};
struct LatencyComponentId {
LatencyComponentType type;
int64 id;
};
struct LatencyComponent {
// Nondecreasing number that can be used to determine what events happened
// in the component at the time this struct was sent on to the next
// component.
int64 sequence_number;
// Average time of events that happened in this component.
mojo.common.mojom.TimeTicks event_time;
// Count of events that happened in this component
uint32 event_count;
};
struct LatencyComponentPair {
LatencyComponentId key;
LatencyComponent value;
};
// TODO(fsamuel): We should replace this with gfx.mojom.PointF here and in
// ui/events/latency_info.h.
struct InputCoordinate {
float x;
float y;
};
// See ui/events/latency_info.h
struct LatencyInfo {
string trace_name;
array<LatencyComponentPair> latency_components;
array<InputCoordinate> input_coordinates;
int64 trace_id;
bool coalesced;
bool terminated;
};
# Copyright 2016 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.
mojom = "//ui/events/mojo/latency_info.mojom"
public_headers = [
"//ui/events/latency_info.h",
]
traits_headers = [ "//ui/events/mojo/latency_info_struct_traits.h" ]
sources = [ "//ui/events/mojo/latency_info_struct_traits.cc" ]
public_deps = [
"//mojo/common",
"//mojo/public/cpp/bindings",
"//ui/events:events_base",
]
type_mappings = [
"ui.mojom.LatencyComponent=ui::LatencyInfo::LatencyComponent",
"ui.mojom.LatencyComponentId=std::pair<ui::LatencyComponentType, int64_t>",
"ui.mojom.LatencyInfo=ui::LatencyInfo",
"ui.mojom.InputCoordinate=ui::LatencyInfo::InputCoordinate",
]
This diff is collapsed.
// Copyright 2016 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 UI_EVENTS_MOJO_LATENCY_INFO_STRUCT_TRAITS_H_
#define UI_EVENTS_MOJO_LATENCY_INFO_STRUCT_TRAITS_H_
#include "ui/events/latency_info.h"
#include "ui/events/mojo/latency_info.mojom.h"
namespace mojo {
template <>
struct StructTraits<ui::mojom::InputCoordinate,
ui::LatencyInfo::InputCoordinate> {
static float x(const ui::LatencyInfo::InputCoordinate& input) {
return input.x;
}
static float y(const ui::LatencyInfo::InputCoordinate& input) {
return input.y;
}
static bool Read(ui::mojom::InputCoordinateDataView data,
ui::LatencyInfo::InputCoordinate* out) {
out->x = data.x();
out->y = data.y();
return true;
}
};
// A buffer used to read bytes directly from LatencyInfoDataView into
// ui::LatencyInfo's input_coordinates_.
struct InputCoordinateArray {
size_t size;
ui::LatencyInfo::InputCoordinate* data;
};
// TODO(fsamuel): We should add a common ArrayTraits<CArray<T>> utility struct.
template <>
struct ArrayTraits<InputCoordinateArray> {
using Element = ui::LatencyInfo::InputCoordinate;
static size_t GetSize(const InputCoordinateArray& b);
static Element* GetData(InputCoordinateArray& b);
static const Element* GetData(const InputCoordinateArray& b);
static Element& GetAt(InputCoordinateArray& b, size_t i);
static const Element& GetAt(const InputCoordinateArray& b, size_t i);
static void Resize(InputCoordinateArray& b, size_t size);
};
template <>
struct StructTraits<ui::mojom::LatencyComponent,
ui::LatencyInfo::LatencyComponent> {
static int64_t sequence_number(
const ui::LatencyInfo::LatencyComponent& component);
static base::TimeTicks event_time(
const ui::LatencyInfo::LatencyComponent& component);
static uint32_t event_count(
const ui::LatencyInfo::LatencyComponent& component);
static bool Read(ui::mojom::LatencyComponentDataView data,
ui::LatencyInfo::LatencyComponent* out);
};
template <>
struct StructTraits<ui::mojom::LatencyComponentId,
std::pair<ui::LatencyComponentType, int64_t>> {
static ui::mojom::LatencyComponentType type(
const std::pair<ui::LatencyComponentType, int64_t>& id);
static int64_t id(const std::pair<ui::LatencyComponentType, int64_t>& id);
static bool Read(ui::mojom::LatencyComponentIdDataView data,
std::pair<ui::LatencyComponentType, int64_t>* out);
};
template <>
struct StructTraits<ui::mojom::LatencyInfo, ui::LatencyInfo> {
static void* SetUpContext(const ui::LatencyInfo& info);
static void TearDownContext(const ui::LatencyInfo& info, void* context);
static const std::string& trace_name(const ui::LatencyInfo& info);
static mojo::Array<ui::mojom::LatencyComponentPairPtr>& latency_components(
const ui::LatencyInfo& info,
void* context);
static uint32_t input_coordinates_size(const ui::LatencyInfo& info);
static InputCoordinateArray input_coordinates(const ui::LatencyInfo& info);
static int64_t trace_id(const ui::LatencyInfo& info);
static bool coalesced(const ui::LatencyInfo& info);
static bool terminated(const ui::LatencyInfo& info);
static bool Read(ui::mojom::LatencyInfoDataView data, ui::LatencyInfo* out);
};
} // namespace mojo
#endif // UI_EVENTS_MOJO_LATENCY_INFO_STRUCT_TRAITS_H_
// Copyright 2016 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 "base/message_loop/message_loop.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/mojo/traits_test_service.mojom.h"
namespace ui {
namespace {
class StructTraitsTest : public testing::Test, public mojom::TraitsTestService {
public:
StructTraitsTest() {}
protected:
mojom::TraitsTestServicePtr GetTraitsTestProxy() {
return traits_test_bindings_.CreateInterfacePtrAndBind(this);
}
private:
// TraitsTestService:
void EchoInputCoordinate(
const LatencyInfo::InputCoordinate& i,
const EchoInputCoordinateCallback& callback) override {
callback.Run(i);
}
void EchoLatencyComponent(
const LatencyInfo::LatencyComponent& l,
const EchoLatencyComponentCallback& callback) override {
callback.Run(l);
}
void EchoLatencyComponentId(
const std::pair<LatencyComponentType, int64_t>& id,
const EchoLatencyComponentIdCallback& callback) override {
callback.Run(id);
}
void EchoLatencyInfo(const LatencyInfo& info,
const EchoLatencyInfoCallback& callback) override {
callback.Run(info);
}
base::MessageLoop loop_;
mojo::BindingSet<TraitsTestService> traits_test_bindings_;
DISALLOW_COPY_AND_ASSIGN(StructTraitsTest);
};
} // namespace
TEST_F(StructTraitsTest, InputCoordinate) {
const float x = 1337.5f;
const float y = 7331.6f;
LatencyInfo::InputCoordinate input(x, y);
mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy();
LatencyInfo::InputCoordinate output;
proxy->EchoInputCoordinate(input, &output);
EXPECT_EQ(x, output.x);
EXPECT_EQ(y, output.y);
}
TEST_F(StructTraitsTest, LatencyComponent) {
const int64_t sequence_number = 13371337;
const base::TimeTicks event_time = base::TimeTicks::Now();
const uint32_t event_count = 1234;
LatencyInfo::LatencyComponent input;
input.sequence_number = sequence_number;
input.event_time = event_time;
input.event_count = event_count;
mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy();
LatencyInfo::LatencyComponent output;
proxy->EchoLatencyComponent(input, &output);
EXPECT_EQ(sequence_number, output.sequence_number);
EXPECT_EQ(event_time, output.event_time);
EXPECT_EQ(event_count, output.event_count);
}
TEST_F(StructTraitsTest, LatencyComponentId) {
const LatencyComponentType type =
INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT;
const int64_t id = 1337;
std::pair<LatencyComponentType, int64_t> input(type, id);
mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy();
std::pair<LatencyComponentType, int64_t> output;
proxy->EchoLatencyComponentId(input, &output);
EXPECT_EQ(type, output.first);
EXPECT_EQ(id, output.second);
}
TEST_F(StructTraitsTest, LatencyInfo) {
LatencyInfo latency;
ASSERT_FALSE(latency.terminated());
ASSERT_EQ(0u, latency.input_coordinates_size());
latency.AddLatencyNumber(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 1234, 0);
latency.AddLatencyNumber(INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 1234, 100);
latency.AddLatencyNumber(INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT,
1234, 0);
EXPECT_TRUE(
latency.AddInputCoordinate(LatencyInfo::InputCoordinate(100, 200)));
EXPECT_TRUE(
latency.AddInputCoordinate(LatencyInfo::InputCoordinate(101, 201)));
// Up to 2 InputCoordinate is allowed.
EXPECT_FALSE(
latency.AddInputCoordinate(LatencyInfo::InputCoordinate(102, 202)));
EXPECT_EQ(100, latency.trace_id());
EXPECT_TRUE(latency.terminated());
EXPECT_EQ(2u, latency.input_coordinates_size());
mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy();
LatencyInfo output;
proxy->EchoLatencyInfo(latency, &output);
EXPECT_EQ(latency.trace_id(), output.trace_id());
EXPECT_EQ(latency.terminated(), output.terminated());
EXPECT_EQ(latency.input_coordinates_size(), output.input_coordinates_size());
for (size_t i = 0; i < latency.input_coordinates_size(); i++) {
EXPECT_EQ(latency.input_coordinates()[i].x,
output.input_coordinates()[i].x);
EXPECT_EQ(latency.input_coordinates()[i].y,
output.input_coordinates()[i].y);
}
EXPECT_TRUE(output.FindLatency(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 1234,
nullptr));
LatencyInfo::LatencyComponent rwh_comp;
EXPECT_TRUE(output.FindLatency(INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 1234,
&rwh_comp));
EXPECT_EQ(100, rwh_comp.sequence_number);
EXPECT_EQ(1u, rwh_comp.event_count);
EXPECT_TRUE(output.FindLatency(
INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 1234, nullptr));
}
} // namespace ui
// Copyright 2016 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.
module ui.mojom;
import "ui/events/mojo/latency_info.mojom";
interface TraitsTestService {
[Sync]
EchoInputCoordinate(InputCoordinate i) => (InputCoordinate pass);
[Sync]
EchoLatencyComponent(LatencyComponent l) => (LatencyComponent pass);
[Sync]
EchoLatencyComponentId(LatencyComponentId l) => (LatencyComponentId pass);
[Sync]
EchoLatencyInfo(LatencyInfo l) => (LatencyInfo pass);
};
......@@ -2,4 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
typemaps = [ "//ui/events/mojo/event.typemap" ]
typemaps = [
"//ui/events/mojo/event.typemap",
"//ui/events/mojo/latency_info.typemap",
]
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment