blob: d3ac84c73d0e43ba8a80739f0b38de4f3c4cacbe [file] [log] [blame]
// Copyright 2021 The Fuchsia 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 "src/ui/scenic/lib/input/gesture_contender_inspector.h"
#include <lib/async/cpp/time.h>
#include <lib/async/default.h>
namespace scenic_impl::input {
namespace {
uint64_t GetCurrentMinute() {
auto dispatcher = async_get_default_dispatcher();
return dispatcher ? async::Now(dispatcher).get() / zx::min(1).get() : 0;
}
} // namespace
GestureContenderInspector::GestureContenderInspector(inspect::Node node)
: node_(std::move(node)),
history_stats_node_(node_.CreateLazyValues("Injection history", [this] {
inspect::Inspector insp;
ReportStats(insp);
return fpromise::make_ok_promise(std::move(insp));
})) {}
void GestureContenderInspector::OnInjectedEvents(zx_koid_t view_ref_koid, uint64_t num_events) {
GetCurrentInspectHistory()[view_ref_koid].num_injected_events += num_events;
}
void GestureContenderInspector::OnContestDecided(zx_koid_t view_ref_koid, bool won) {
if (won) {
GetCurrentInspectHistory()[view_ref_koid].num_won_streams++;
} else {
GetCurrentInspectHistory()[view_ref_koid].num_lost_streams++;
}
}
std::unordered_map<zx_koid_t, GestureContenderInspector::ViewHistory>&
GestureContenderInspector::GetCurrentInspectHistory() {
const uint64_t current_minute = GetCurrentMinute();
// Add elements to the front and pop from the back so that the newest element will be read out
// first when we later iterate over the deque.
if (history_.empty() || history_.front().minute_key != current_minute) {
history_.push_front({
.minute_key = current_minute,
});
}
// Pop off everything older than |kNumMinutesOfHistory|.
while (history_.size() > 1 &&
history_.back().minute_key + kNumMinutesOfHistory <= current_minute) {
history_.pop_back();
}
return history_.front().per_view_data;
}
void GestureContenderInspector::ReportStats(inspect::Inspector& inspector) const {
inspect::Node node = inspector.GetRoot().CreateChild(
"Last " + std::to_string(kNumMinutesOfHistory) + " minutes of injected events");
ViewHistory sum;
const uint64_t current_minute = GetCurrentMinute();
for (const auto& [minute, per_view_data] : history_) {
if (minute + kNumMinutesOfHistory <= current_minute) {
break;
}
auto minute_node = node.CreateChild("Events at minute " + std::to_string(minute));
for (const auto& [view_ref_koid, view_data] : per_view_data) {
auto view_node = minute_node.CreateChild("View " + std::to_string(view_ref_koid));
view_node.CreateUint("num_injected_events", view_data.num_injected_events, &inspector);
view_node.CreateUint("num_won_streams", view_data.num_won_streams, &inspector);
view_node.CreateUint("num_lost_streams", view_data.num_lost_streams, &inspector);
inspector.emplace(std::move(view_node));
sum.num_injected_events += view_data.num_injected_events;
sum.num_won_streams += view_data.num_won_streams;
sum.num_lost_streams += view_data.num_lost_streams;
}
inspector.emplace(std::move(minute_node));
}
{
auto sum_node = node.CreateChild("Sum");
sum_node.CreateUint("num_injected_events", sum.num_injected_events, &inspector);
sum_node.CreateUint("num_won_streams", sum.num_won_streams, &inspector);
sum_node.CreateUint("num_lost_streams", sum.num_lost_streams, &inspector);
inspector.emplace(std::move(sum_node));
}
inspector.emplace(std::move(node));
}
} // namespace scenic_impl::input