190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file.
490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/debug/trace_event.h"
64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/json/json_writer.h"
74e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
84e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/strings/stringprintf.h"
968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/events/latency_info.h"
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <algorithm>
1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace {
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)const size_t kMaxLatencyInfoNumber = 100;
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char* GetComponentName(ui::LatencyComponentType type) {
184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#define CASE_TYPE(t) case ui::t:  return #t
194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  switch (type) {
204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT);
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CASE_TYPE(INPUT_EVENT_LATENCY_BEGIN_PLUGIN_COMPONENT);
226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    CASE_TYPE(INPUT_EVENT_LATENCY_BEGIN_SCROLL_UPDATE_MAIN_COMPONENT);
234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(INPUT_EVENT_LATENCY_SCROLL_UPDATE_RWH_COMPONENT);
244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT);
254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT);
264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(INPUT_EVENT_LATENCY_UI_COMPONENT);
274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_COMPONENT);
286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    CASE_TYPE(INPUT_EVENT_LATENCY_FORWARD_SCROLL_UPDATE_TO_MAIN_COMPONENT);
294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(INPUT_EVENT_LATENCY_ACKED_TOUCH_COMPONENT);
30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    CASE_TYPE(WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT);
31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    CASE_TYPE(WINDOW_OLD_SNAPSHOT_FRAME_NUMBER_COMPONENT);
324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(INPUT_EVENT_LATENCY_TERMINATED_MOUSE_COMPONENT);
334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(INPUT_EVENT_LATENCY_TERMINATED_TOUCH_COMPONENT);
344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(INPUT_EVENT_LATENCY_TERMINATED_GESTURE_COMPONENT);
354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CASE_TYPE(INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT);
36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    CASE_TYPE(INPUT_EVENT_LATENCY_TERMINATED_COMMIT_FAILED_COMPONENT);
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    CASE_TYPE(INPUT_EVENT_LATENCY_TERMINATED_COMMIT_NO_UPDATE_COMPONENT);
38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    CASE_TYPE(INPUT_EVENT_LATENCY_TERMINATED_SWAP_FAILED_COMPONENT);
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CASE_TYPE(INPUT_EVENT_LATENCY_TERMINATED_PLUGIN_COMPONENT);
404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    default:
414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      DLOG(WARNING) << "Unhandled LatencyComponentType.\n";
424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      break;
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#undef CASE_TYPE
454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return "unknown";
464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool IsTerminalComponent(ui::LatencyComponentType type) {
494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  switch (type) {
504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    case ui::INPUT_EVENT_LATENCY_TERMINATED_MOUSE_COMPONENT:
514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    case ui::INPUT_EVENT_LATENCY_TERMINATED_TOUCH_COMPONENT:
524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    case ui::INPUT_EVENT_LATENCY_TERMINATED_GESTURE_COMPONENT:
534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    case ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT:
54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    case ui::INPUT_EVENT_LATENCY_TERMINATED_COMMIT_FAILED_COMPONENT:
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case ui::INPUT_EVENT_LATENCY_TERMINATED_COMMIT_NO_UPDATE_COMPONENT:
56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    case ui::INPUT_EVENT_LATENCY_TERMINATED_SWAP_FAILED_COMPONENT:
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case ui::INPUT_EVENT_LATENCY_TERMINATED_PLUGIN_COMPONENT:
584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return true;
594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    default:
604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return false;
614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool IsBeginComponent(ui::LatencyComponentType type) {
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return (type == ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT ||
666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          type == ui::INPUT_EVENT_LATENCY_BEGIN_PLUGIN_COMPONENT ||
676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          type == ui::INPUT_EVENT_LATENCY_BEGIN_SCROLL_UPDATE_MAIN_COMPONENT);
684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// This class is for converting latency info to trace buffer friendly format.
714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class LatencyInfoTracedValue : public base::debug::ConvertableToTraceFormat {
724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public:
734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  static scoped_refptr<ConvertableToTraceFormat> FromValue(
744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      scoped_ptr<base::Value> value);
754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual void AppendAsTraceFormat(std::string* out) const OVERRIDE;
774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private:
794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  explicit LatencyInfoTracedValue(base::Value* value);
804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual ~LatencyInfoTracedValue();
814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  scoped_ptr<base::Value> value_;
834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(LatencyInfoTracedValue);
854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)scoped_refptr<base::debug::ConvertableToTraceFormat>
884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)LatencyInfoTracedValue::FromValue(scoped_ptr<base::Value> value) {
894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return scoped_refptr<base::debug::ConvertableToTraceFormat>(
904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      new LatencyInfoTracedValue(value.release()));
914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)LatencyInfoTracedValue::~LatencyInfoTracedValue() {
944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void LatencyInfoTracedValue::AppendAsTraceFormat(std::string* out) const {
974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  std::string tmp;
984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::JSONWriter::Write(value_.get(), &tmp);
994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  *out += tmp;
1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)LatencyInfoTracedValue::LatencyInfoTracedValue(base::Value* value)
1034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    : value_(value) {
1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Converts latencyinfo into format that can be dumped into trace buffer.
1074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)scoped_refptr<base::debug::ConvertableToTraceFormat> AsTraceableData(
1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const ui::LatencyInfo& latency) {
1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> record_data(new base::DictionaryValue());
1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (ui::LatencyInfo::LatencyMap::const_iterator it =
1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)           latency.latency_components.begin();
1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       it != latency.latency_components.end(); ++it) {
1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::DictionaryValue* component_info = new base::DictionaryValue();
1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    component_info->SetDouble("comp_id", it->first.second);
1154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    component_info->SetDouble("time", it->second.event_time.ToInternalValue());
1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    component_info->SetDouble("count", it->second.event_count);
1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    record_data->Set(GetComponentName(it->first.first), component_info);
1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  record_data->SetDouble("trace_id", latency.trace_id);
1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<base::ListValue> coordinates(new base::ListValue());
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (size_t i = 0; i < latency.input_coordinates_size; i++) {
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<base::DictionaryValue> coordinate_pair(
1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        new base::DictionaryValue());
1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    coordinate_pair->SetDouble("x", latency.input_coordinates[i].x);
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    coordinate_pair->SetDouble("y", latency.input_coordinates[i].y);
1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    coordinates->Append(coordinate_pair.release());
1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  record_data->Set("coordinates", coordinates.release());
1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return LatencyInfoTracedValue::FromValue(record_data.PassAs<base::Value>());
1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}  // namespace
1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace ui {
13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciLatencyInfo::InputCoordinate::InputCoordinate() : x(0), y(0) {
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciLatencyInfo::InputCoordinate::InputCoordinate(float x, float y) : x(x), y(y) {
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciLatencyInfo::LatencyInfo()
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    : input_coordinates_size(0), trace_id(-1), terminated(false) {
14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)LatencyInfo::~LatencyInfo() {
14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool LatencyInfo::Verify(const std::vector<LatencyInfo>& latency_info,
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         const char* referring_msg) {
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (latency_info.size() > kMaxLatencyInfoNumber) {
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LOG(ERROR) << referring_msg << ", LatencyInfo vector size "
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               << latency_info.size() << " is too big.";
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (size_t i = 0; i < latency_info.size(); i++) {
1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (latency_info[i].input_coordinates_size > kMaxInputCoordinates) {
1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      LOG(ERROR) << referring_msg << ", coordinate vector size "
1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 << latency_info[i].input_coordinates_size << " is too big.";
1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return false;
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void LatencyInfo::CopyLatencyFrom(const LatencyInfo& other,
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  LatencyComponentType type) {
17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (LatencyMap::const_iterator it = other.latency_components.begin();
17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       it != other.latency_components.end();
17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       ++it) {
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (it->first.first == type) {
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      AddLatencyNumberWithTimestamp(it->first.first,
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    it->first.second,
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    it->second.sequence_number,
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    it->second.event_time,
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    it->second.event_count);
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1833240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid LatencyInfo::AddNewLatencyFrom(const LatencyInfo& other) {
1843240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    for (LatencyMap::const_iterator it = other.latency_components.begin();
1853240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch         it != other.latency_components.end();
1863240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch         ++it) {
1873240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      if (!FindLatency(it->first.first, it->first.second, NULL)) {
1883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        AddLatencyNumberWithTimestamp(it->first.first,
1893240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                                      it->first.second,
1903240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                                      it->second.sequence_number,
1913240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                                      it->second.event_time,
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      it->second.event_count);
1933240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      }
1943240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    }
1953240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
1963240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void LatencyInfo::AddLatencyNumber(LatencyComponentType component,
19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                   int64 id,
19990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                   int64 component_sequence_number) {
20090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  AddLatencyNumberWithTimestamp(component, id, component_sequence_number,
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                base::TimeTicks::HighResNow(), 1);
20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void LatencyInfo::AddLatencyNumberWithTimestamp(LatencyComponentType component,
20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                                int64 id,
20690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                                int64 component_sequence_number,
20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                                base::TimeTicks time,
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                uint32 event_count) {
2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  static const unsigned char* benchmark_enabled =
2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED("benchmark");
2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (IsBeginComponent(component)) {
2144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Should only ever add begin component once.
215a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    CHECK_EQ(-1, trace_id);
2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    trace_id = component_sequence_number;
2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (*benchmark_enabled) {
2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // The timestamp for ASYNC_BEGIN trace event is used for drawing the
2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // beginning of the trace event in trace viewer. For better visualization,
2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // for an input event, we want to draw the beginning as when the event is
2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // originally created, e.g. the timestamp of its ORIGINAL/UI_COMPONENT,
2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // not when we actually issue the ASYNC_BEGIN trace event.
2245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      LatencyComponent component;
2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      int64 ts = 0;
2265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (FindLatency(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
2275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      0,
2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      &component) ||
2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          FindLatency(INPUT_EVENT_LATENCY_UI_COMPONENT,
2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      0,
2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      &component)) {
2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        // The timestamp stored in ORIGINAL/UI_COMPONENT is using clock
2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        // CLOCK_MONOTONIC while TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP0
2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        // expects timestamp using CLOCK_MONOTONIC or CLOCK_SYSTEM_TRACE (on
2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        // CrOS). So we need to adjust the diff between in CLOCK_MONOTONIC and
2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        // CLOCK_SYSTEM_TRACE. Note that the diff is drifting overtime so we
2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        // can't use a static value.
2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        int64 diff = base::TimeTicks::HighResNow().ToInternalValue() -
2395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            base::TimeTicks::NowFromSystemTraceTime().ToInternalValue();
2405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        ts = component.event_time.ToInternalValue() - diff;
2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      } else {
2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        ts = base::TimeTicks::NowFromSystemTraceTime().ToInternalValue();
2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP0(
2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          "benchmark",
2465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          "InputLatency",
2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          TRACE_ID_DONT_MANGLE(trace_id),
2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          ts);
2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
2505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
251e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    TRACE_EVENT_FLOW_BEGIN0(
252e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        "input", "LatencyInfo.Flow", TRACE_ID_DONT_MANGLE(trace_id));
2534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
25590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  LatencyMap::key_type key = std::make_pair(component, id);
25690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  LatencyMap::iterator it = latency_components.find(key);
25790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (it == latency_components.end()) {
25890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    LatencyComponent info = {component_sequence_number, time, event_count};
25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    latency_components[key] = info;
2604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  } else {
2614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    it->second.sequence_number = std::max(component_sequence_number,
2624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                          it->second.sequence_number);
2634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    uint32 new_count = event_count + it->second.event_count;
2644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (event_count > 0 && new_count != 0) {
2654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // Do a weighted average, so that the new event_time is the average of
2664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // the times of events currently in this structure with the time passed
2674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // into this method.
2684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      it->second.event_time += (time - it->second.event_time) * event_count /
2694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          new_count;
2704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      it->second.event_count = new_count;
2714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
27290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
2734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (IsTerminalComponent(component) && trace_id != -1) {
2754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Should only ever add terminal component once.
2764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CHECK(!terminated);
2774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    terminated = true;
2785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (*benchmark_enabled) {
2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      TRACE_EVENT_ASYNC_END1("benchmark",
2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             "InputLatency",
2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             TRACE_ID_DONT_MANGLE(trace_id),
2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             "data", AsTraceableData(*this));
2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
286e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    TRACE_EVENT_FLOW_END0(
287e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        "input", "LatencyInfo.Flow", TRACE_ID_DONT_MANGLE(trace_id));
28890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
28990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
29090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool LatencyInfo::FindLatency(LatencyComponentType type,
292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              int64 id,
293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              LatencyComponent* output) const {
294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  LatencyMap::const_iterator it = latency_components.find(
295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      std::make_pair(type, id));
296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (it == latency_components.end())
297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return false;
298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (output)
299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    *output = it->second;
300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return true;
301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
303f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void LatencyInfo::RemoveLatency(LatencyComponentType type) {
304f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  LatencyMap::iterator it = latency_components.begin();
305f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  while (it != latency_components.end()) {
306f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (it->first.first == type) {
307f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      LatencyMap::iterator tmp = it;
308f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      ++it;
309f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      latency_components.erase(tmp);
310f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    } else {
311f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      it++;
312f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
313f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
314f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
315f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void LatencyInfo::Clear() {
31790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  latency_components.clear();
31890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
31990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void LatencyInfo::TraceEventType(const char* event_type) {
3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TRACE_EVENT_ASYNC_STEP_INTO0("benchmark",
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               "InputLatency",
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               TRACE_ID_DONT_MANGLE(trace_id),
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               event_type);
3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
32790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace ui
328