summaryrefslogtreecommitdiffstats
path: root/chromeos
diff options
context:
space:
mode:
authorhashimoto <hashimoto@chromium.org>2015-12-14 22:48:12 -0800
committerCommit bot <commit-bot@chromium.org>2015-12-15 06:49:02 +0000
commit9aaf636094c82ae2b9707394b661b8db4637fd25 (patch)
tree0472e89179aa6bbb2c3e7d93c49319dbfbdbe769 /chromeos
parent0d735b3ac72c85222599617a0aae571eb8f9170e (diff)
downloadchromium_src-9aaf636094c82ae2b9707394b661b8db4637fd25.zip
chromium_src-9aaf636094c82ae2b9707394b661b8db4637fd25.tar.gz
chromium_src-9aaf636094c82ae2b9707394b661b8db4637fd25.tar.bz2
Add binder::CommandStream
CommandStream is responsible to interpret incoming commands read from the driver. It's also responsible to write outgoing commands to the driver. This patch is to add the basic parts of CommandStream, it will be functional after a few more patches. BUG=563282 Review URL: https://codereview.chromium.org/1505353008 Cr-Commit-Position: refs/heads/master@{#365189}
Diffstat (limited to 'chromeos')
-rw-r--r--chromeos/binder/command_stream.cc147
-rw-r--r--chromeos/binder/command_stream.h67
-rw-r--r--chromeos/binder/command_stream_unittest.cc47
-rw-r--r--chromeos/chromeos.gyp3
4 files changed, 264 insertions, 0 deletions
diff --git a/chromeos/binder/command_stream.cc b/chromeos/binder/command_stream.cc
new file mode 100644
index 0000000..3e7705a
--- /dev/null
+++ b/chromeos/binder/command_stream.cc
@@ -0,0 +1,147 @@
+// 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/command_stream.h"
+
+#include <linux/android/binder.h>
+
+#include "chromeos/binder/buffer_reader.h"
+#include "chromeos/binder/driver.h"
+#include "chromeos/binder/util.h"
+
+namespace binder {
+
+CommandStream::CommandStream(Driver* driver,
+ IncomingCommandHandler* incoming_command_handler)
+ : driver_(driver), incoming_command_handler_(incoming_command_handler) {}
+
+CommandStream::~CommandStream() {}
+
+bool CommandStream::Fetch() {
+ DCHECK(!CanProcessIncomingCommand());
+ // Use the same value as libbinder's IPCThreadState.
+ const size_t kIncomingDataSize = 256;
+ incoming_data_.resize(kIncomingDataSize);
+
+ size_t written_bytes = 0, read_bytes = 0;
+ if (!driver_->WriteRead(nullptr, 0, incoming_data_.data(),
+ incoming_data_.size(), &written_bytes, &read_bytes)) {
+ LOG(ERROR) << "WriteRead() failed.";
+ return false;
+ }
+ incoming_data_.resize(read_bytes);
+ incoming_data_reader_.reset(
+ new BufferReader(incoming_data_.data(), incoming_data_.size()));
+ return true;
+}
+
+bool CommandStream::CanProcessIncomingCommand() {
+ return incoming_data_reader_ && incoming_data_reader_->HasMoreData();
+}
+
+bool CommandStream::ProcessIncomingCommand() {
+ DCHECK(CanProcessIncomingCommand());
+ uint32 command = 0;
+ if (!incoming_data_reader_->Read(&command, sizeof(command)) ||
+ !OnIncomingCommand(command, incoming_data_reader_.get())) {
+ LOG(ERROR) << "Error while handling command: " << command;
+ return false;
+ }
+ return true;
+}
+
+void CommandStream::AppendOutgoingCommand(uint32 command,
+ const void* data,
+ size_t size) {
+ VLOG(1) << "Appending " << CommandToString(command) << ", this = " << this;
+
+ DCHECK_EQ(0u, size % 4); // Must be 4-byte aligned.
+ outgoing_data_.insert(
+ outgoing_data_.end(), reinterpret_cast<const char*>(&command),
+ reinterpret_cast<const char*>(&command) + sizeof(command));
+ outgoing_data_.insert(outgoing_data_.end(),
+ reinterpret_cast<const char*>(data),
+ reinterpret_cast<const char*>(data) + size);
+}
+
+bool CommandStream::Flush() {
+ for (size_t pos = 0; pos < outgoing_data_.size();) {
+ size_t written_bytes = 0, read_bytes = 0;
+ if (!driver_->WriteRead(outgoing_data_.data() + pos,
+ outgoing_data_.size() - pos, nullptr, 0,
+ &written_bytes, &read_bytes)) {
+ LOG(ERROR) << "WriteRead() failed: pos = " << pos
+ << ", size = " << outgoing_data_.size();
+ return false;
+ }
+ pos += written_bytes;
+ }
+ outgoing_data_.clear();
+ return true;
+}
+
+bool CommandStream::OnIncomingCommand(uint32 command, BufferReader* reader) {
+ // TODO(hashimoto): Replace all NOTIMPLEMENTED with logic to handle incoming
+ // commands.
+ VLOG(1) << "Processing " << CommandToString(command) << ", this = " << this;
+ switch (command) {
+ case BR_ERROR: {
+ int32 error = 0;
+ if (!reader->Read(&error, sizeof(error))) {
+ LOG(ERROR) << "Failed to read error code.";
+ return false;
+ }
+ break;
+ }
+ case BR_OK:
+ break;
+ case BR_TRANSACTION:
+ NOTIMPLEMENTED();
+ break;
+ case BR_REPLY:
+ NOTIMPLEMENTED();
+ break;
+ case BR_ACQUIRE_RESULT:
+ // Kernel's binder.h says this is not currently supported.
+ NOTREACHED();
+ break;
+ case BR_DEAD_REPLY:
+ NOTIMPLEMENTED();
+ break;
+ case BR_TRANSACTION_COMPLETE:
+ NOTIMPLEMENTED();
+ break;
+ case BR_INCREFS:
+ case BR_ACQUIRE:
+ case BR_RELEASE:
+ case BR_DECREFS:
+ case BR_ATTEMPT_ACQUIRE:
+ NOTIMPLEMENTED();
+ break;
+ case BR_NOOP:
+ break;
+ case BR_SPAWN_LOOPER:
+ NOTIMPLEMENTED();
+ break;
+ case BR_FINISHED:
+ // Kernel's binder.h says this is not currently supported.
+ NOTREACHED();
+ break;
+ case BR_DEAD_BINDER:
+ NOTIMPLEMENTED();
+ break;
+ case BR_CLEAR_DEATH_NOTIFICATION_DONE:
+ NOTIMPLEMENTED();
+ break;
+ case BR_FAILED_REPLY:
+ NOTIMPLEMENTED();
+ break;
+ default:
+ LOG(ERROR) << "Unexpected command: " << command;
+ return false;
+ }
+ return true;
+}
+
+} // namespace binder
diff --git a/chromeos/binder/command_stream.h b/chromeos/binder/command_stream.h
new file mode 100644
index 0000000..823abda5
--- /dev/null
+++ b/chromeos/binder/command_stream.h
@@ -0,0 +1,67 @@
+// 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.
+
+#ifndef BINDER_COMMAND_STREAM_H_
+#define BINDER_COMMAND_STREAM_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+
+namespace binder {
+
+class BufferReader;
+class Driver;
+
+// Stream of incoming (binder driver to user process) BR_* commands and outgoing
+// (user process to binder driver) BC_* commands.
+class CommandStream {
+ public:
+ // IncomingCommandHandler is responsible to handle incoming commands.
+ class IncomingCommandHandler {
+ public:
+ virtual ~IncomingCommandHandler() {}
+ // TODO(hashimoto): Add methods to handle incoming commands.
+ };
+
+ CommandStream(Driver* driver,
+ IncomingCommandHandler* incoming_command_handler);
+ ~CommandStream();
+
+ // Reads incoming commands from the driver to the buffer, and returns true on
+ // success.
+ bool Fetch();
+
+ // Returns true if any incoming commands are in the buffer.
+ bool CanProcessIncomingCommand();
+
+ // Processes an incoming command in the buffer, and returns true on success.
+ bool ProcessIncomingCommand();
+
+ // Appends a command to the outgoing command buffer.
+ void AppendOutgoingCommand(uint32 command, const void* data, size_t size);
+
+ // Writes buffered outgoing commands to the driver, and returns true on
+ // success.
+ bool Flush();
+
+ private:
+ // Calls the appropriate delegate method to handle the incoming command.
+ bool OnIncomingCommand(uint32 command, BufferReader* reader);
+
+ Driver* driver_;
+ IncomingCommandHandler* incoming_command_handler_;
+
+ std::vector<char> outgoing_data_; // Buffer for outgoing commands.
+ std::vector<char> incoming_data_; // Buffer for incoming commands.
+ scoped_ptr<BufferReader> incoming_data_reader_;
+
+ DISALLOW_COPY_AND_ASSIGN(CommandStream);
+};
+
+} // namespace binder
+
+#endif // BINDER_COMMAND_STREAM_H_
diff --git a/chromeos/binder/command_stream_unittest.cc b/chromeos/binder/command_stream_unittest.cc
new file mode 100644
index 0000000..ae67ab3
--- /dev/null
+++ b/chromeos/binder/command_stream_unittest.cc
@@ -0,0 +1,47 @@
+// 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 <unistd.h>
+#include <linux/android/binder.h>
+
+#include "chromeos/binder/command_stream.h"
+#include "chromeos/binder/driver.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace binder {
+
+namespace {
+
+// TODO(hashimoto): Add tests for Fetch() and ProcessCommand().
+class BinderCommandStreamTest : public ::testing::Test,
+ public CommandStream::IncomingCommandHandler {
+ public:
+ BinderCommandStreamTest() : command_stream_(&driver_, this) {}
+ ~BinderCommandStreamTest() override {}
+
+ void SetUp() override { ASSERT_TRUE(driver_.Initialize()); }
+
+ protected:
+ Driver driver_;
+ CommandStream command_stream_;
+};
+
+} // namespace
+
+TEST_F(BinderCommandStreamTest, EnterLooper) {
+ command_stream_.AppendOutgoingCommand(BC_ENTER_LOOPER, nullptr, 0);
+ EXPECT_TRUE(command_stream_.Flush());
+ command_stream_.AppendOutgoingCommand(BC_EXIT_LOOPER, nullptr, 0);
+ EXPECT_TRUE(command_stream_.Flush());
+}
+
+TEST_F(BinderCommandStreamTest, Error) {
+ // Kernel's binder.h says BC_ATTEMPT_ACQUIRE is not currently supported.
+ binder_pri_desc params = {};
+ command_stream_.AppendOutgoingCommand(BC_ATTEMPT_ACQUIRE, &params,
+ sizeof(params));
+ EXPECT_FALSE(command_stream_.Flush());
+}
+
+} // namespace binder
diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp
index f2b405e..28b3957 100644
--- a/chromeos/chromeos.gyp
+++ b/chromeos/chromeos.gyp
@@ -389,6 +389,8 @@
'chromeos_binder_sources': [
'binder/buffer_reader.cc',
'binder/buffer_reader.h',
+ 'binder/command_stream.cc',
+ 'binder/command_stream.h',
'binder/driver.cc',
'binder/driver.h',
'binder/util.cc',
@@ -396,6 +398,7 @@
],
'chromeos_binder_test_sources': [
'binder/buffer_reader_unittest.cc',
+ 'binder/command_stream_unittest.cc',
'binder/driver_unittest.cc',
],
'chromeos_test_sources': [