blob: b4c53c736c76df3a5a1826a7545b27dc57ee8523 [file] [log] [blame]
// Copyright 2019 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/sys/activity/activity_tracker_connection.h"
#include <fuchsia/ui/activity/cpp/fidl.h>
#include <lib/async/cpp/time.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/assert.h>
#include <zircon/errors.h>
#include <zircon/status.h>
#include <zircon/types.h>
namespace activity {
ActivityTrackerConnection::ActivityTrackerConnection(
StateMachineDriver* state_machine_driver, async_dispatcher_t* dispatcher,
fidl::InterfaceRequest<fuchsia::ui::activity::Tracker> request)
: state_machine_driver_(state_machine_driver),
dispatcher_(dispatcher),
binding_(this, std::move(request), dispatcher) {}
ActivityTrackerConnection::~ActivityTrackerConnection() { Stop(); }
void ActivityTrackerConnection::Stop() {
for (const auto& id : ongoing_activities_) {
zx_status_t status =
state_machine_driver_->EndOngoingActivity(id, async::Now(dispatcher_), []() {});
// Assert here since failing silently may result in a leaked activity which would stall the
// state machine from timing out.
ZX_ASSERT_MSG(status == ZX_OK, "Failed to clean up activity %d: %s", id,
zx_status_get_string(status));
}
ongoing_activities_.clear();
}
void ActivityTrackerConnection::ReportDiscreteActivity(
fuchsia::ui::activity::DiscreteActivity activity, zx_time_t time,
ReportDiscreteActivityCallback callback) {
if (time < last_activity_time_.get()) {
FX_LOGS(ERROR) << "activity-service: Received out-of-order events from client.";
binding_.Close(ZX_ERR_OUT_OF_RANGE);
return;
}
last_activity_time_ = zx::time(time);
zx_status_t status =
state_machine_driver_->ReceiveDiscreteActivity(activity, zx::time(time), std::move(callback));
if (status != ZX_OK) {
if (status == ZX_ERR_OUT_OF_RANGE) {
FX_LOGS(WARNING) << "activity-service: Ignoring activity due to stale timestamp (" << time
<< ")";
} else {
FX_LOGS(ERROR) << "activity-service: Failed to receive activity: "
<< zx_status_get_string(status);
binding_.Close(status);
}
}
}
void ActivityTrackerConnection::StartOngoingActivity(
OngoingActivityId id, fuchsia::ui::activity::OngoingActivity activity, zx_time_t time,
StartOngoingActivityCallback callback) {
if (ongoing_activities_.find(id) != ongoing_activities_.end()) {
FX_LOGS(ERROR) << "activity-service: activity already started: " << id;
binding_.Close(ZX_ERR_ALREADY_EXISTS);
return;
}
if (time < last_activity_time_.get()) {
FX_LOGS(ERROR) << "activity-service: Received out-of-order events from client.";
binding_.Close(ZX_ERR_OUT_OF_RANGE);
return;
}
last_activity_time_ = zx::time(time);
zx_status_t status =
state_machine_driver_->StartOngoingActivity(id, zx::time(time), std::move(callback));
if (status == ZX_OK) {
ongoing_activities_.insert(id);
} else {
if (status == ZX_ERR_OUT_OF_RANGE) {
FX_LOGS(WARNING) << "activity-service: Ignoring activity due to stale timestamp (" << time
<< ")";
// Ignore the activity (don't close the binding or send an error to the client)
} else {
FX_LOGS(ERROR) << "activity-service: Failed to start activity: "
<< zx_status_get_string(status);
binding_.Close(status);
}
}
}
void ActivityTrackerConnection::EndOngoingActivity(OngoingActivityId id, zx_time_t time,
EndOngoingActivityCallback callback) {
if (time < last_activity_time_.get()) {
FX_LOGS(ERROR) << "activity-service: Received out-of-order events from client.";
binding_.Close(ZX_ERR_OUT_OF_RANGE);
return;
}
last_activity_time_ = zx::time(time);
auto iter = ongoing_activities_.find(id);
if (iter == ongoing_activities_.end()) {
FX_LOGS(ERROR) << "activity-service: Invalid activity ID: " << id;
binding_.Close(ZX_ERR_NOT_FOUND);
return;
}
zx_status_t status =
state_machine_driver_->EndOngoingActivity(id, zx::time(time), std::move(callback));
if (status == ZX_OK) {
ongoing_activities_.erase(iter);
} else {
if (status == ZX_ERR_OUT_OF_RANGE) {
FX_LOGS(WARNING) << "activity-service: Ignoring activity due to stale timestamp (" << time
<< ")";
// Ignore the activity (don't close the binding or send an error to the client)
} else {
FX_LOGS(ERROR) << "activity-service: Failed to end activity: "
<< zx_status_get_string(status);
binding_.Close(status);
}
}
}
} // namespace activity