Index: mojo/edk/system/channel_posix.cc |
diff --git a/mojo/edk/system/channel_posix.cc b/mojo/edk/system/channel_posix.cc |
index a7cf9e3df6cc83645cabcda729bdc1c23e78e471..7e9d171dd81233397f3276bfa02d0e341f0e28a1 100644 |
--- a/mojo/edk/system/channel_posix.cc |
+++ b/mojo/edk/system/channel_posix.cc |
@@ -26,6 +26,11 @@ |
#include <sys/uio.h> |
#endif |
+#if defined(OS_ANDROID) |
+#include "base/android/parcelable_channel_client.h" |
+#include "base/android/scoped_java_ref.h" |
+#endif |
+ |
namespace mojo { |
namespace edk { |
@@ -39,10 +44,13 @@ class MessageView { |
public: |
// Owns |message|. |offset| indexes the first unsent byte in the message. |
MessageView(Channel::MessagePtr message, size_t offset) |
- : message_(std::move(message)), |
- offset_(offset), |
- handles_(message_->TakeHandlesForTransport()) { |
+ : message_(std::move(message)), offset_(offset) { |
DCHECK_GT(message_->data_num_bytes(), offset_); |
+#if defined(OS_ANDROID) |
+ // Parcelables must be retrieved before Handles. |
+ ids_and_parcelables_ = message_->TakeParcelablesForTransport(); |
+#endif |
+ handles_ = message_->TakeHandlesForTransport(); |
} |
MessageView(MessageView&& other) { *this = std::move(other); } |
@@ -70,6 +78,12 @@ class MessageView { |
ScopedPlatformHandleVectorPtr TakeHandles() { return std::move(handles_); } |
Channel::MessagePtr TakeMessage() { return std::move(message_); } |
+#if defined(OS_ANDROID) |
+ Channel::Message::IDAndParcelableVector TakeParcelables() { |
+ return std::move(ids_and_parcelables_); |
+ } |
+ |
+#endif |
void SetHandles(ScopedPlatformHandleVectorPtr handles) { |
handles_ = std::move(handles); |
@@ -79,6 +93,9 @@ class MessageView { |
Channel::MessagePtr message_; |
size_t offset_; |
ScopedPlatformHandleVectorPtr handles_; |
+#if defined(OS_ANDROID) |
+ Channel::Message::IDAndParcelableVector ids_and_parcelables_; |
+#endif |
DISALLOW_COPY_AND_ASSIGN(MessageView); |
}; |
@@ -88,17 +105,28 @@ class ChannelPosix : public Channel, |
public base::MessageLoopForIO::Watcher { |
public: |
ChannelPosix(Delegate* delegate, |
- ScopedPlatformHandle handle, |
+ ConnectionParam connection_param, |
scoped_refptr<base::TaskRunner> io_task_runner) |
: Channel(delegate), |
self_(this), |
- handle_(std::move(handle)), |
+ handle_(connection_param.TakeChannelHandle()), |
+#if defined(OS_ANDROID) |
+ parcelable_channel_client_( |
+ connection_param.TakeParcelableChannelClient()), |
+ parcelable_channel_server_( |
+ connection_param.TakeParcelableChannelServer()), |
+#endif |
io_task_runner_(io_task_runner) |
#if defined(OS_MACOSX) |
, |
handles_to_close_(new PlatformHandleVector) |
#endif |
{ |
+ CHECK(handle_.is_valid()); |
+ // We can't DCHECK because the BrokerHost has a channel used for sync |
+ // messages with not parcelable channels. |
+ // CHECK(parcelable_channel_client_.is_valid()); |
+ // CHECK(parcelable_channel_server_.is_valid()); |
} |
void Start() override { |
@@ -149,6 +177,7 @@ class ChannelPosix : public Channel, |
ScopedPlatformHandleVectorPtr* handles) override { |
if (num_handles > std::numeric_limits<uint16_t>::max()) |
return false; |
+ |
#if defined(OS_MACOSX) && !defined(OS_IOS) |
// On OSX, we can have mach ports which are located in the extra header |
// section. |
@@ -183,6 +212,35 @@ class ChannelPosix : public Channel, |
incoming_platform_handles_.pop_front(); |
} |
} |
+#elif defined(OS_ANDROID) |
+ using ParcelableEntry = Channel::Message::ParcelableEntry; |
+ using ParcelableExtraHeader = Channel::Message::ParcelableExtraHeader; |
+ CHECK(extra_header_size >= sizeof(ParcelableExtraHeader) + |
+ num_handles * sizeof(ParcelableEntry)); |
+ const ParcelableExtraHeader* parcelable_header = |
+ reinterpret_cast<const ParcelableExtraHeader*>(extra_header); |
+ size_t num_parcelables = parcelable_header->num_parcelables; |
+ CHECK(num_parcelables <= num_handles); |
+ if (incoming_platform_handles_.size() + num_parcelables < num_handles) { |
+ handles->reset(); |
+ return true; |
+ } |
+ |
+ handles->reset(new PlatformHandleVector(num_handles)); |
+ const ParcelableEntry* parcelables = parcelable_header->entries; |
+ for (size_t i = 0, parcelable_index = 0; i < num_handles; ++i) { |
+ if (parcelable_index < num_parcelables && |
+ parcelables[parcelable_index].index == i) { |
+ (*handles)->at(i) = |
+ PlatformHandle(parcelable_channel_server_.TakeParcelable( |
+ parcelables[parcelable_index].id)); |
+ parcelable_index++; |
+ } else { |
+ CHECK(!incoming_platform_handles_.empty()); |
+ (*handles)->at(i) = incoming_platform_handles_.front(); |
+ incoming_platform_handles_.pop_front(); |
+ } |
+ } |
#else |
if (incoming_platform_handles_.size() < num_handles) { |
handles->reset(); |
@@ -358,6 +416,17 @@ class ChannelPosix : public Channel, |
message_view.advance_data_offset(bytes_written); |
ssize_t result; |
+#if defined(OS_ANDROID) |
+ Channel::Message::IDAndParcelableVector ids_and_parcelables = |
+ std::move(message_view.TakeParcelables()); |
+ if (!ids_and_parcelables.empty()) { |
+ for (auto iter = ids_and_parcelables.begin(); |
+ iter != ids_and_parcelables.end(); ++iter) { |
+ DCHECK(!iter->second.is_null()); |
+ parcelable_channel_client_.SendParcelable(iter->first, iter->second); |
+ } |
+ } |
+#endif |
ScopedPlatformHandleVectorPtr handles = message_view.TakeHandles(); |
if (handles && handles->size()) { |
iovec iov = { |
@@ -532,6 +601,10 @@ class ChannelPosix : public Channel, |
scoped_refptr<Channel> self_; |
ScopedPlatformHandle handle_; |
+#if defined(OS_ANDROID) |
+ base::android::ParcelableChannelClient parcelable_channel_client_; |
+ base::android::ParcelableChannelServer parcelable_channel_server_; |
+#endif |
scoped_refptr<base::TaskRunner> io_task_runner_; |
// These watchers must only be accessed on the IO thread. |
@@ -561,9 +634,10 @@ class ChannelPosix : public Channel, |
// static |
scoped_refptr<Channel> Channel::Create( |
Delegate* delegate, |
- ScopedPlatformHandle platform_handle, |
+ ConnectionParam connection_param, |
scoped_refptr<base::TaskRunner> io_task_runner) { |
- return new ChannelPosix(delegate, std::move(platform_handle), io_task_runner); |
+ return new ChannelPosix(delegate, std::move(connection_param), |
+ io_task_runner); |
} |
} // namespace edk |