blob: 623d9092eedaea86e571c560d773f80b7f319d27 [file] [log] [blame]
/*
* Copyright 2019 The Chromium OS 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 "hal/usb_v1/arc_camera_dbus_daemon.h"
#include <signal.h>
#include <memory>
#include <string>
#include <vector>
#include <base/command_line.h>
#include <base/logging.h>
#include <chromeos/dbus/service_constants.h>
#include "dbus_adaptors/org.chromium.ArcCamera.h"
#include "hal/usb_v1/arc_camera_service.h"
namespace arc {
// DBusAdaptor handles incoming D-Bus method calls.
class ArcCameraDBusDaemon::DBusAdaptor
: public org::chromium::ArcCameraAdaptor,
public org::chromium::ArcCameraInterface {
public:
explicit DBusAdaptor(scoped_refptr<dbus::Bus> bus)
: org::chromium::ArcCameraAdaptor(this),
dbus_object_(
nullptr, bus, dbus::ObjectPath(arc_camera::kArcCameraServicePath)) {
}
DBusAdaptor(const DBusAdaptor&) = delete;
DBusAdaptor& operator=(const DBusAdaptor&) = delete;
~DBusAdaptor() override = default;
void RegisterAsync(
const brillo::dbus_utils::AsyncEventSequencer::CompletionAction& cb) {
RegisterWithDBusObject(&dbus_object_);
dbus_object_.RegisterAsync(cb);
}
// org::chromium::ArcCameraInterface overrides:
bool StartService(brillo::ErrorPtr* error,
const base::ScopedFD& fd,
const std::string& token) override {
VLOG(1) << "Accepted a client, fd: " << fd.get();
// Fork and exec this executable in child mode.
// Note: We don't use brillo::ProcessImpl here as we are ignoring SIGCHLD
// and there is no need to track child processes.
base::CommandLine new_cl(*base::CommandLine::ForCurrentProcess());
new_cl.AppendSwitchASCII("child", token);
std::vector<std::string> argv = new_cl.argv();
std::vector<const char*> argv_cstr;
for (auto& arg : argv)
argv_cstr.push_back(arg.c_str());
argv_cstr.push_back(nullptr);
pid_t child_pid = fork();
if (child_pid < 0) {
PLOG(ERROR) << "Fork failed";
return false;
}
if (child_pid == 0) { // child
// Pass the FD to the child.
dup2(fd.get(), kMojoChannelFD);
close(fd.get());
execv(argv_cstr[0], const_cast<char**>(argv_cstr.data()));
_exit(EXIT_FAILURE);
}
return true;
}
private:
brillo::dbus_utils::DBusObject dbus_object_;
};
ArcCameraDBusDaemon::ArcCameraDBusDaemon()
: DBusServiceDaemon(arc_camera::kArcCameraServiceName) {
// Reap zombie processes when child process exited.
signal(SIGCHLD, SIG_IGN);
}
ArcCameraDBusDaemon::~ArcCameraDBusDaemon() = default;
void ArcCameraDBusDaemon::RegisterDBusObjectsAsync(
brillo::dbus_utils::AsyncEventSequencer* sequencer) {
adaptor_ = std::make_unique<DBusAdaptor>(bus_);
adaptor_->RegisterAsync(
sequencer->GetHandler("RegisterAsync() failed.", true));
}
} // namespace arc