blob: d67f9aa763bebe71422a3865f2a5f354f625c2ac [file] [log] [blame]
// Copyright 2015 The Chromium 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 "chromeos/binder/ipc_thread.h"
#include "chromeos/binder/command_broker.h"
#include "chromeos/binder/driver.h"
namespace binder {
// IpcThreadPoller
IpcThreadPoller::IpcThreadPoller(ThreadType type, Driver* driver)
: type_(type), driver_(driver), command_broker_(driver) {}
IpcThreadPoller::~IpcThreadPoller() {
if (!command_broker_.ExitLooper()) {
LOG(ERROR) << "Failed to exit looper.";
}
if (!driver_->NotifyCurrentThreadExiting()) {
LOG(ERROR) << "Failed to send thread exit.";
}
}
bool IpcThreadPoller::Initialize() {
if (type_ == THREAD_TYPE_MAIN) {
if (!command_broker_.EnterLooper()) {
LOG(ERROR) << "Failed to enter looper.";
return false;
}
} else {
if (!command_broker_.RegisterLooper()) {
LOG(ERROR) << "Failed to register looper.";
return false;
}
}
if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
driver_->GetFD(), true, base::MessageLoopForIO::WATCH_READ, &watcher_,
this)) {
LOG(ERROR) << "Failed to initialize watcher.";
return false;
}
return true;
}
void IpcThreadPoller::OnFileCanReadWithoutBlocking(int fd) {
bool success = command_broker_.PollCommands();
LOG_IF(ERROR, !success) << "PollCommands() failed.";
}
void IpcThreadPoller::OnFileCanWriteWithoutBlocking(int fd) {
NOTREACHED();
}
// MainIpcThread
MainIpcThread::MainIpcThread() : base::Thread("BinderMainThread") {}
MainIpcThread::~MainIpcThread() {
Stop();
}
bool MainIpcThread::Start() {
base::Thread::Options options;
options.message_loop_type = base::MessageLoop::TYPE_IO;
return StartWithOptions(options);
}
void MainIpcThread::Init() {
driver_.reset(new Driver());
if (!driver_->Initialize()) {
LOG(ERROR) << "Failed to initialize driver.";
return;
}
poller_.reset(
new IpcThreadPoller(IpcThreadPoller::THREAD_TYPE_MAIN, driver_.get()));
if (!poller_->Initialize()) {
LOG(ERROR) << "Failed to initialize poller.";
return;
}
initialized_ = true;
}
void MainIpcThread::CleanUp() {
poller_.reset();
driver_.reset();
}
// SubIpcThread
SubIpcThread::SubIpcThread(MainIpcThread* main_thread)
: base::Thread("BinderSubThread"), main_thread_(main_thread) {}
SubIpcThread::~SubIpcThread() {
Stop();
}
bool SubIpcThread::Start() {
base::Thread::Options options;
options.message_loop_type = base::MessageLoop::TYPE_IO;
return StartWithOptions(options);
}
void SubIpcThread::Init() {
// Wait for the main thread to finish initialization.
if (!main_thread_->WaitUntilThreadStarted()) {
LOG(ERROR) << "Failed to wait for the main thread.";
return;
}
poller_.reset(new IpcThreadPoller(IpcThreadPoller::THREAD_TYPE_SUB,
main_thread_->driver()));
if (!poller_->Initialize()) {
LOG(ERROR) << "Failed to initialize poller.";
return;
}
initialized_ = true;
}
void SubIpcThread::CleanUp() {
poller_.reset();
}
} // namespace binder