blob: 8975c61a30d334e0b310aea35039e131e4ddb62d [file] [log] [blame] [edit]
// Copyright 2013 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "lorgnette/daemon.h"
#include <sysexits.h>
#include <string>
#include <utility>
#include <base/functional/bind.h>
#include <base/logging.h>
#include <base/run_loop.h>
#include <base/task/single_thread_task_runner.h>
#include <base/time/time.h>
#include <chromeos/dbus/service_constants.h>
#include "lorgnette/dbus_service_adaptor.h"
#include "lorgnette/libsane_wrapper_impl.h"
#include "lorgnette/sane_client.h"
#include "lorgnette/sane_client_impl.h"
#include "lorgnette/usb/libusb_wrapper.h"
#include "lorgnette/usb/libusb_wrapper_impl.h"
using std::string;
namespace lorgnette {
// static
const char Daemon::kScanGroupName[] = "scanner";
const char Daemon::kScanUserName[] = "saned";
namespace {
constexpr base::TimeDelta kMaxDiscoverySessionTime = base::Minutes(60);
constexpr base::TimeDelta kMaxScannerHandleIdleTime = base::Minutes(60);
constexpr base::TimeDelta kTimeoutCheckInterval = base::Seconds(2);
} // namespace
Daemon::Daemon() : DBusServiceDaemon(kManagerServiceName, "/ObjectManager") {}
Daemon::~Daemon() {}
int Daemon::OnInit() {
int return_code = brillo::DBusServiceDaemon::OnInit();
if (return_code != EX_OK) {
return return_code;
}
PostponeShutdown(kNormalShutdownTimeout);
return EX_OK;
}
void Daemon::RegisterDBusObjectsAsync(
brillo::dbus_utils::AsyncEventSequencer* sequencer) {
libsane_ = LibsaneWrapperImpl::Create();
sane_client_ = SaneClientImpl::Create(libsane_.get());
libusb_ = LibusbWrapperImpl::Create();
auto manager =
std::make_unique<Manager>(base::BindRepeating(&Daemon::PostponeShutdown,
weak_factory_.GetWeakPtr()),
sane_client_.get());
device_tracker_.reset(new DeviceTracker(sane_client_.get(), libusb_.get()));
dbus_service_.reset(
new DBusServiceAdaptor(std::move(manager), device_tracker_.get(),
base::BindRepeating(&Daemon::OnDebugChanged,
weak_factory_.GetWeakPtr())));
dbus_service_->RegisterAsync(object_manager_.get(), sequencer);
}
void Daemon::OnShutdown(int* return_code) {
LOG(INFO) << "Shutting down";
dbus_service_.reset();
brillo::DBusServiceDaemon::OnShutdown(return_code);
}
void Daemon::OnTimeout() {
// While there are active discovery sessions, they get a long timeout. Once
// there are no active sessions, the normal short timeout from the last
// discovery session activity applies.
base::TimeDelta idle_time =
base::Time::Now() - device_tracker_->LastDiscoverySessionActivity();
base::TimeDelta discovery_timeout =
device_tracker_->NumActiveDiscoverySessions() > 0
? kMaxDiscoverySessionTime
: kTimeoutCheckInterval;
if (idle_time < discovery_timeout) {
PostponeShutdown(kTimeoutCheckInterval);
return;
}
// TODO(b/276909624): Change this logic to match the discovery session logic
// above.
if (device_tracker_->NumOpenScanners() > 0) {
base::TimeDelta idle_time =
base::Time::Now() - device_tracker_->LastOpenScannerActivity();
if (idle_time < kMaxScannerHandleIdleTime) {
PostponeShutdown(kTimeoutCheckInterval);
return;
}
}
LOG(INFO) << "Exiting after timeout";
Quit();
}
void Daemon::OnDebugChanged() {
LOG(INFO) << "Exiting after debug config changed.";
Quit();
}
void Daemon::PostponeShutdown(base::TimeDelta delay) {
shutdown_callback_.Reset(
base::BindOnce(&Daemon::OnTimeout, weak_factory_.GetWeakPtr()));
base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
FROM_HERE, shutdown_callback_.callback(), delay);
}
} // namespace lorgnette