summaryrefslogtreecommitdiffstats
path: root/mojo/android
diff options
context:
space:
mode:
authorqsr@chromium.org <qsr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-23 16:02:32 +0000
committerqsr@chromium.org <qsr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-23 16:02:32 +0000
commit70c0364a44341bf10c5157c11d3689a3cf7c6054 (patch)
tree201dff677afe4bb771b89f370a4c93ee5e276305 /mojo/android
parent76b34ffc13b9d895f60e20a752f5d09317d00db0 (diff)
downloadchromium_src-70c0364a44341bf10c5157c11d3689a3cf7c6054.zip
chromium_src-70c0364a44341bf10c5157c11d3689a3cf7c6054.tar.gz
chromium_src-70c0364a44341bf10c5157c11d3689a3cf7c6054.tar.bz2
Java API for mojo system.
This CL introduce the java API for mojo system. It also introduces the android implementation of this API. Review URL: https://codereview.chromium.org/228723002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@265658 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'mojo/android')
-rw-r--r--mojo/android/DEPS3
-rw-r--r--mojo/android/javatests/AndroidManifest.xml21
-rw-r--r--mojo/android/javatests/apk/EMPTY0
-rw-r--r--mojo/android/javatests/core_test.cc26
-rw-r--r--mojo/android/javatests/core_test.h20
-rw-r--r--mojo/android/javatests/init_library.cc40
-rw-r--r--mojo/android/javatests/src/org/chromium/mojo/system/CoreTest.java471
-rw-r--r--mojo/android/system/core_impl.cc293
-rw-r--r--mojo/android/system/core_impl.h20
-rw-r--r--mojo/android/system/src/org/chromium/mojo/system/CoreImpl.java584
-rw-r--r--mojo/android/system/src/org/chromium/mojo/system/CoreSingleton.java18
-rw-r--r--mojo/android/system/src/org/chromium/mojo/system/DataPipeConsumerHandleImpl.java63
-rw-r--r--mojo/android/system/src/org/chromium/mojo/system/DataPipeProducerHandleImpl.java55
-rw-r--r--mojo/android/system/src/org/chromium/mojo/system/HandleImpl.java112
-rw-r--r--mojo/android/system/src/org/chromium/mojo/system/MessagePipeHandleImpl.java47
-rw-r--r--mojo/android/system/src/org/chromium/mojo/system/SharedBufferHandleImpl.java52
-rw-r--r--mojo/android/system/src/org/chromium/mojo/system/UntypedHandleImpl.java54
17 files changed, 1879 insertions, 0 deletions
diff --git a/mojo/android/DEPS b/mojo/android/DEPS
new file mode 100644
index 0000000..c80012b5
--- /dev/null
+++ b/mojo/android/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+jni",
+]
diff --git a/mojo/android/javatests/AndroidManifest.xml b/mojo/android/javatests/AndroidManifest.xml
new file mode 100644
index 0000000..8968941
--- /dev/null
+++ b/mojo/android/javatests/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <!-- Copyright (c) 2012 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. -->
+ <!-- package name must be unique so suffix with "tests" so package loader
+ doesn't ignore this. -->
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.chromium.mojo.tests">
+ <!-- We add an application tag here just so that we can indicate that this
+ package needs to link against the android.test library, which is
+ needed when building test cases. -->
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+ <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" />
+ <instrumentation android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="org.chromium.mojo.tests"
+ android:label="Tests for org.chromium.mojo"/>
+ <uses-permission android:name="android.permission.RUN_INSTRUMENTATION" />
+ <uses-permission android:name="android.permission.INJECT_EVENTS" />
+</manifest>
diff --git a/mojo/android/javatests/apk/EMPTY b/mojo/android/javatests/apk/EMPTY
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/mojo/android/javatests/apk/EMPTY
diff --git a/mojo/android/javatests/core_test.cc b/mojo/android/javatests/core_test.cc
new file mode 100644
index 0000000..3d4032f
--- /dev/null
+++ b/mojo/android/javatests/core_test.cc
@@ -0,0 +1,26 @@
+// Copyright 2014 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 "mojo/android/javatests/core_test.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/scoped_java_ref.h"
+#include "jni/CoreTest_jni.h"
+
+namespace mojo {
+namespace android {
+
+static void InitApplicationContext(JNIEnv* env,
+ jobject jcaller,
+ jobject context) {
+ base::android::ScopedJavaLocalRef<jobject> scoped_context(env, context);
+ base::android::InitApplicationContext(env, scoped_context);
+}
+
+bool RegisterCoreTest(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+} // namespace android
+} // namespace mojo
diff --git a/mojo/android/javatests/core_test.h b/mojo/android/javatests/core_test.h
new file mode 100644
index 0000000..96c8878
--- /dev/null
+++ b/mojo/android/javatests/core_test.h
@@ -0,0 +1,20 @@
+// Copyright 2014 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 MOJO_ANDROID_JAVATESTS_CORE_TEST_H_
+#define MOJO_ANDROID_JAVATESTS_CORE_TEST_H_
+
+#include <jni.h>
+
+#include "base/android/jni_android.h"
+
+namespace mojo {
+namespace android {
+
+JNI_EXPORT bool RegisterCoreTest(JNIEnv* env);
+
+} // namespace android
+} // namespace mojo
+
+#endif // MOJO_SYSTEM_ANDROID_JAVATESTS_CORE_TEST_H_
diff --git a/mojo/android/javatests/init_library.cc b/mojo/android/javatests/init_library.cc
new file mode 100644
index 0000000..7b4cbe3
--- /dev/null
+++ b/mojo/android/javatests/init_library.cc
@@ -0,0 +1,40 @@
+// Copyright 2014 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 "base/android/base_jni_registrar.h"
+#include "base/android/jni_android.h"
+#include "base/android/jni_registrar.h"
+#include "base/android/library_loader/library_loader_hooks.h"
+#include "mojo/android/javatests/core_test.h"
+#include "mojo/android/system/core_impl.h"
+
+namespace {
+
+base::android::RegistrationMethod kMojoRegisteredMethods[] = {
+ { "CoreImpl", mojo::android::RegisterCoreImpl },
+ { "CoreTest", mojo::android::RegisterCoreTest },
+};
+
+bool RegisterMojoJni(JNIEnv* env) {
+ return RegisterNativeMethods(env, kMojoRegisteredMethods,
+ arraysize(kMojoRegisteredMethods));
+}
+
+} // namespace
+
+JNI_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
+ base::android::InitVM(vm);
+ JNIEnv* env = base::android::AttachCurrentThread();
+
+ if (!base::android::RegisterLibraryLoaderEntryHook(env))
+ return -1;
+
+ if (!base::android::RegisterJni(env))
+ return -1;
+
+ if (!RegisterMojoJni(env))
+ return -1;
+
+ return JNI_VERSION_1_4;
+}
diff --git a/mojo/android/javatests/src/org/chromium/mojo/system/CoreTest.java b/mojo/android/javatests/src/org/chromium/mojo/system/CoreTest.java
new file mode 100644
index 0000000..97f0912
--- /dev/null
+++ b/mojo/android/javatests/src/org/chromium/mojo/system/CoreTest.java
@@ -0,0 +1,471 @@
+// Copyright 2014 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.
+
+package org.chromium.mojo.system;
+
+import android.content.Context;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.chromium.base.JNINamespace;
+import org.chromium.base.library_loader.LibraryLoader;
+import org.chromium.mojo.system.Core.WaitFlags;
+import org.chromium.mojo.system.Core.WaitManyResult;
+import org.chromium.mojo.system.MessagePipeHandle.ReadFlags;
+import org.chromium.mojo.system.MessagePipeHandle.ReadMessageResult;
+import org.chromium.mojo.system.MessagePipeHandle.WriteFlags;
+import org.chromium.mojo.system.SharedBufferHandle.MapFlags;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Testing the core API.
+ */
+@JNINamespace("mojo::android")
+public class CoreTest extends InstrumentationTestCase {
+
+ private static final ScheduledExecutorService WORKER =
+ Executors.newSingleThreadScheduledExecutor();
+
+ /**
+ * @see junit.framework.TestCase#setUp()
+ */
+ @Override
+ protected void setUp() throws Exception {
+ LibraryLoader.ensureInitialized();
+ nativeInitApplicationContext(getInstrumentation().getTargetContext());
+ }
+
+ /**
+ * Runnable that will close the given handle.
+ */
+ private static class CloseHandle implements Runnable {
+ private Handle mHandle;
+
+ CloseHandle(Handle handle) {
+ mHandle = handle;
+ }
+
+ @Override
+ public void run() {
+ mHandle.close();
+ }
+ }
+
+ private static void checkSendingMessage(MessagePipeHandle in, MessagePipeHandle out) {
+ Random random = new Random();
+
+ // Writing a random 8 bytes message.
+ byte[] bytes = new byte[8];
+ random.nextBytes(bytes);
+ ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.length);
+ buffer.put(bytes);
+ in.writeMessage(buffer, null, MessagePipeHandle.WriteFlags.none());
+
+ // Try to read into a small buffer.
+ ByteBuffer receiveBuffer = ByteBuffer.allocateDirect(bytes.length / 2);
+ MessagePipeHandle.ReadMessageResult result = out.readMessage(receiveBuffer, 0,
+ MessagePipeHandle.ReadFlags.none());
+ assertFalse(result.getWasMessageRead());
+ assertEquals(bytes.length, result.getMessageSize());
+ assertEquals(0, result.getHandlesCount());
+
+ // Read into a correct buffer.
+ receiveBuffer = ByteBuffer.allocateDirect(bytes.length);
+ result = out.readMessage(receiveBuffer, 0,
+ MessagePipeHandle.ReadFlags.none());
+ assertTrue(result.getWasMessageRead());
+ assertEquals(bytes.length, result.getMessageSize());
+ assertEquals(0, result.getHandlesCount());
+ assertEquals(0, receiveBuffer.position());
+ assertEquals(result.getMessageSize(), receiveBuffer.limit());
+ byte[] receivedBytes = new byte[result.getMessageSize()];
+ receiveBuffer.get(receivedBytes);
+ assertTrue(Arrays.equals(bytes, receivedBytes));
+
+ }
+
+ /**
+ * Testing {@link Core#waitMany(List, long)}.
+ */
+ @SmallTest
+ public void testWaitMany() {
+ Core core = CoreSingleton.getInstance();
+ Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe();
+
+ try {
+ List<Pair<Handle, WaitFlags>> handlesToWaitOn = new ArrayList<
+ Pair<Handle, WaitFlags>>();
+
+ handlesToWaitOn.add(
+ new Pair<Handle, WaitFlags>(handles.second,
+ WaitFlags.none().setReadable(true)));
+ handlesToWaitOn.add(
+ new Pair<Handle, WaitFlags>(handles.first, WaitFlags.none().setWritable(true)));
+ WaitManyResult result = core.waitMany(handlesToWaitOn, 0);
+ assertEquals(MojoResult.OK, result.getMojoResult());
+ assertEquals(1, result.getHandleIndex());
+
+ handlesToWaitOn.clear();
+ handlesToWaitOn.add(
+ new Pair<Handle, WaitFlags>(handles.first, WaitFlags.none().setWritable(true)));
+ handlesToWaitOn.add(
+ new Pair<Handle, WaitFlags>(handles.second,
+ WaitFlags.none().setReadable(true)));
+ result = core.waitMany(handlesToWaitOn, 0);
+ assertEquals(MojoResult.OK, result.getMojoResult());
+ assertEquals(0, result.getHandleIndex());
+ } finally {
+ handles.first.close();
+ handles.second.close();
+ }
+ }
+
+ /**
+ * Testing {@link MessagePipeHandle}.
+ */
+ @SmallTest
+ public void testMessagePipeEmpty() {
+ Core core = CoreSingleton.getInstance();
+ Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe();
+
+ try {
+ // Testing wait.
+ assertEquals(MojoResult.OK, handles.first.wait(WaitFlags.all(), 0));
+ assertEquals(MojoResult.OK, handles.first.wait(WaitFlags.none().setWritable(true), 0));
+ assertEquals(MojoResult.DEADLINE_EXCEEDED,
+ handles.first.wait(WaitFlags.none().setReadable(true), 0));
+
+ // Testing read on an empty pipe.
+ boolean exception = false;
+ try {
+ handles.first.readMessage(null, 0, MessagePipeHandle.ReadFlags.none());
+ } catch (MojoException e) {
+ assertEquals(MojoResult.SHOULD_WAIT, e.getMojoResult());
+ exception = true;
+ }
+ assertTrue(exception);
+
+ // Closing a pipe while waiting.
+ WORKER.schedule(new CloseHandle(handles.first), 10, TimeUnit.MILLISECONDS);
+ assertEquals(MojoResult.CANCELLED,
+ handles.first.wait(WaitFlags.none().setReadable(true), 1000000L));
+ } finally {
+ handles.first.close();
+ handles.second.close();
+ }
+
+ handles = core.createMessagePipe();
+
+ try {
+ // Closing the other pipe while waiting.
+ WORKER.schedule(new CloseHandle(handles.first), 10, TimeUnit.MILLISECONDS);
+ assertEquals(MojoResult.FAILED_PRECONDITION,
+ handles.second.wait(WaitFlags.none().setReadable(true), 1000000L));
+
+ // Waiting on a closed pipe.
+ assertEquals(MojoResult.FAILED_PRECONDITION,
+ handles.second.wait(WaitFlags.none().setReadable(true), 0));
+ assertEquals(MojoResult.FAILED_PRECONDITION,
+ handles.second.wait(WaitFlags.none().setWritable(true), 0));
+ } finally {
+ handles.first.close();
+ handles.second.close();
+ }
+
+ }
+
+ /**
+ * Testing {@link MessagePipeHandle}.
+ */
+ @SmallTest
+ public void testMessagePipeSend() {
+ Core core = CoreSingleton.getInstance();
+ Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe();
+
+ try {
+ checkSendingMessage(handles.first, handles.second);
+ checkSendingMessage(handles.second, handles.first);
+ } finally {
+ handles.first.close();
+ handles.second.close();
+ }
+ }
+
+ /**
+ * Testing {@link MessagePipeHandle}.
+ */
+ @SmallTest
+ public void testMessagePipeReceiveOnSmallBuffer() {
+ Random random = new Random();
+ Core core = CoreSingleton.getInstance();
+ Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe();
+
+ try {
+ // Writing a random 8 bytes message.
+ byte[] bytes = new byte[8];
+ random.nextBytes(bytes);
+ ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.length);
+ buffer.put(bytes);
+ handles.first.writeMessage(buffer, null, MessagePipeHandle.WriteFlags.none());
+
+ ByteBuffer receiveBuffer = ByteBuffer.allocateDirect(1);
+ MessagePipeHandle.ReadMessageResult result = handles.second.readMessage(receiveBuffer,
+ 0,
+ MessagePipeHandle.ReadFlags.none());
+ assertFalse(result.getWasMessageRead());
+ assertEquals(bytes.length, result.getMessageSize());
+ assertEquals(0, result.getHandlesCount());
+ } finally {
+ handles.first.close();
+ handles.second.close();
+ }
+ }
+
+ /**
+ * Testing {@link MessagePipeHandle}.
+ */
+ @SmallTest
+ public void testMessagePipeSendHandles() {
+ Core core = CoreSingleton.getInstance();
+ Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMessagePipe();
+ Pair<MessagePipeHandle, MessagePipeHandle> handlesToShare = core.createMessagePipe();
+
+ try {
+ handles.first.writeMessage(null,
+ Collections.<Handle> singletonList(handlesToShare.second),
+ WriteFlags.none());
+ assertFalse(handlesToShare.second.isValid());
+ ReadMessageResult readMessageResult = handles.second.readMessage(null, 1,
+ ReadFlags.none());
+ assertEquals(1, readMessageResult.getHandlesCount());
+ MessagePipeHandle newHandle = readMessageResult.getHandles().get(0)
+ .toMessagePipeHandle();
+ try {
+ assertTrue(newHandle.isValid());
+ checkSendingMessage(handlesToShare.first, newHandle);
+ checkSendingMessage(newHandle, handlesToShare.first);
+ } finally {
+ newHandle.close();
+ }
+ } finally {
+ handles.first.close();
+ handles.second.close();
+ handlesToShare.first.close();
+ handlesToShare.second.close();
+ }
+ }
+
+ private static void createAndCloseDataPipe(DataPipe.CreateOptions options) {
+ Core core = CoreSingleton.getInstance();
+ Pair<DataPipe.ProducerHandle, DataPipe.ConsumerHandle> handles = core.createDataPipe(
+ options);
+ handles.first.close();
+ handles.second.close();
+ }
+
+ /**
+ * Testing {@link DataPipe}.
+ */
+ @SmallTest
+ public void testDataPipeCreation() {
+ // Create datapipe with null options.
+ createAndCloseDataPipe(null);
+ DataPipe.CreateOptions options = new DataPipe.CreateOptions();
+ // Create datapipe with element size set.
+ options.setElementNumBytes(24);
+ createAndCloseDataPipe(options);
+ // Create datapipe with a flag set.
+ options.getFlags().setMayDiscard(true);
+ createAndCloseDataPipe(options);
+ // Create datapipe with capacity set.
+ options.setCapacityNumBytes(1024 * options.getElementNumBytes());
+ createAndCloseDataPipe(options);
+ }
+
+ /**
+ * Testing {@link DataPipe}.
+ */
+ @SmallTest
+ public void testDataPipeSend() {
+ Core core = CoreSingleton.getInstance();
+ Random random = new Random();
+
+ Pair<DataPipe.ProducerHandle, DataPipe.ConsumerHandle> handles = core.createDataPipe(null);
+ try {
+ // Writing a random 8 bytes message.
+ byte[] bytes = new byte[8];
+ random.nextBytes(bytes);
+ ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.length);
+ buffer.put(bytes);
+ int result = handles.first.writeData(buffer, DataPipe.WriteFlags.none());
+ assertEquals(bytes.length, result);
+
+ // Query number of bytes available.
+ result = handles.second.readData(null,
+ DataPipe.ReadFlags.none().query(true));
+ assertEquals(bytes.length, result);
+
+ // Read into a buffer.
+ ByteBuffer receiveBuffer = ByteBuffer.allocateDirect(bytes.length);
+ result = handles.second.readData(receiveBuffer,
+ DataPipe.ReadFlags.none());
+ assertEquals(bytes.length, result);
+ assertEquals(0, receiveBuffer.position());
+ assertEquals(bytes.length, receiveBuffer.limit());
+ byte[] receivedBytes = new byte[bytes.length];
+ receiveBuffer.get(receivedBytes);
+ assertTrue(Arrays.equals(bytes, receivedBytes));
+ } finally {
+ handles.first.close();
+ handles.second.close();
+ }
+ }
+
+ /**
+ * Testing {@link DataPipe}.
+ */
+ @SmallTest
+ public void testDataPipeTwoPhaseSend() {
+ Random random = new Random();
+ Core core = CoreSingleton.getInstance();
+ Pair<DataPipe.ProducerHandle, DataPipe.ConsumerHandle> handles = core.createDataPipe(null);
+
+ try {
+ // Writing a random 8 bytes message.
+ byte[] bytes = new byte[8];
+ random.nextBytes(bytes);
+ ByteBuffer buffer = handles.first.beginWriteData(bytes.length,
+ DataPipe.WriteFlags.none());
+ assertTrue(buffer.capacity() >= bytes.length);
+ buffer.put(bytes);
+ handles.first.endWriteData(bytes.length);
+
+ // Read into a buffer.
+ ByteBuffer receiveBuffer = handles.second.beginReadData(bytes.length,
+ DataPipe.ReadFlags.none());
+ assertEquals(0, receiveBuffer.position());
+ assertEquals(bytes.length, receiveBuffer.limit());
+ byte[] receivedBytes = new byte[bytes.length];
+ receiveBuffer.get(receivedBytes);
+ assertTrue(Arrays.equals(bytes, receivedBytes));
+ handles.second.endReadData(bytes.length);
+ } finally {
+ handles.first.close();
+ handles.second.close();
+ }
+ }
+
+ /**
+ * Testing {@link DataPipe}.
+ */
+ @SmallTest
+ public void testDataPipeDiscard() {
+ Random random = new Random();
+ Core core = CoreSingleton.getInstance();
+ Pair<DataPipe.ProducerHandle, DataPipe.ConsumerHandle> handles = core.createDataPipe(null);
+
+ try {
+ // Writing a random 8 bytes message.
+ byte[] bytes = new byte[8];
+ random.nextBytes(bytes);
+ ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.length);
+ buffer.put(bytes);
+ int result = handles.first.writeData(buffer, DataPipe.WriteFlags.none());
+ assertEquals(bytes.length, result);
+
+ // Discard bytes.
+ final int nbBytesToDiscard = 4;
+ assertEquals(nbBytesToDiscard,
+ handles.second.discardData(nbBytesToDiscard, DataPipe.ReadFlags.none()));
+
+ // Read into a buffer.
+ ByteBuffer receiveBuffer = ByteBuffer.allocateDirect(bytes.length - nbBytesToDiscard);
+ result = handles.second.readData(receiveBuffer,
+ DataPipe.ReadFlags.none());
+ assertEquals(bytes.length - nbBytesToDiscard, result);
+ assertEquals(0, receiveBuffer.position());
+ assertEquals(bytes.length - nbBytesToDiscard, receiveBuffer.limit());
+ byte[] receivedBytes = new byte[bytes.length - nbBytesToDiscard];
+ receiveBuffer.get(receivedBytes);
+ assertTrue(Arrays.equals(Arrays.copyOfRange(bytes, nbBytesToDiscard, bytes.length),
+ receivedBytes));
+ } finally {
+ handles.first.close();
+ handles.second.close();
+ }
+ }
+
+ /**
+ * Testing {@link SharedBufferHandle}.
+ */
+ @SmallTest
+ public void testSharedBufferCreation() {
+ Core core = CoreSingleton.getInstance();
+ // Test creation with empty options.
+ core.createSharedBuffer(null, 8).close();
+ // Test creation with default options.
+ core.createSharedBuffer(new SharedBufferHandle.CreateOptions(), 8);
+ }
+
+ /**
+ * Testing {@link SharedBufferHandle}.
+ */
+ @SmallTest
+ public void testSharedBufferDuplication() {
+ Core core = CoreSingleton.getInstance();
+ SharedBufferHandle handle = core.createSharedBuffer(null, 8);
+ try {
+ // Test duplication with empty options.
+ handle.duplicate(null).close();
+ // Test creation with default options.
+ handle.duplicate(new SharedBufferHandle.DuplicateOptions()).close();
+ } finally {
+ handle.close();
+ }
+ }
+
+ /**
+ * Testing {@link SharedBufferHandle}.
+ */
+ @SmallTest
+ public void testSharedBufferSending() {
+ Random random = new Random();
+ Core core = CoreSingleton.getInstance();
+ SharedBufferHandle handle = core.createSharedBuffer(null, 8);
+ SharedBufferHandle newHandle = handle.duplicate(null);
+
+ try {
+ ByteBuffer buffer1 = handle.map(0, 8, MapFlags.none());
+ assertEquals(8, buffer1.capacity());
+ ByteBuffer buffer2 = newHandle.map(0, 8, MapFlags.none());
+ assertEquals(8, buffer2.capacity());
+
+ byte[] bytes = new byte[8];
+ random.nextBytes(bytes);
+ buffer1.put(bytes);
+
+ byte[] receivedBytes = new byte[bytes.length];
+ buffer2.get(receivedBytes);
+
+ assertTrue(Arrays.equals(bytes, receivedBytes));
+
+ handle.unmap(buffer1);
+ newHandle.unmap(buffer2);
+ } finally {
+ handle.close();
+ newHandle.close();
+ }
+ }
+
+ private native void nativeInitApplicationContext(Context context);
+}
diff --git a/mojo/android/system/core_impl.cc b/mojo/android/system/core_impl.cc
new file mode 100644
index 0000000..d7552c1
--- /dev/null
+++ b/mojo/android/system/core_impl.cc
@@ -0,0 +1,293 @@
+// Copyright 2014 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 "mojo/android/system/core_impl.h"
+
+#include "base/android/base_jni_registrar.h"
+#include "base/android/jni_android.h"
+#include "base/android/jni_registrar.h"
+#include "base/android/library_loader/library_loader_hooks.h"
+#include "base/logging.h"
+#include "jni/CoreImpl_jni.h"
+#include "mojo/embedder/embedder.h"
+#include "mojo/public/c/system/core.h"
+
+namespace mojo {
+namespace android {
+
+static void Constructor(JNIEnv* env, jobject jcaller) {
+ mojo::embedder::Init();
+}
+
+static jlong GetTimeTicksNow(JNIEnv* env, jobject jcaller) {
+ return MojoGetTimeTicksNow();
+}
+
+static jint WaitMany(JNIEnv* env,
+ jobject jcaller,
+ jobject buffer,
+ jlong deadline) {
+ // Buffer contains first the list of handles, then the list of flags.
+ const void* buffer_start = env->GetDirectBufferAddress(buffer);
+ DCHECK(buffer_start);
+ const size_t record_size = 8;
+ const size_t buffer_size = env->GetDirectBufferCapacity(buffer);
+ DCHECK_EQ(buffer_size % record_size, 0u);
+
+ const size_t nb_handles = buffer_size / record_size;
+ const MojoHandle* handle_start = static_cast<const MojoHandle*>(buffer_start);
+ const MojoWaitFlags* flags_start =
+ static_cast<const MojoWaitFlags*>(handle_start + nb_handles);
+ return MojoWaitMany(handle_start, flags_start, nb_handles, deadline);
+}
+
+static jobject CreateMessagePipe(JNIEnv* env, jobject jcaller) {
+ MojoHandle handle1;
+ MojoHandle handle2;
+ MojoResult result = MojoCreateMessagePipe(&handle1, &handle2);
+ return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2)
+ .Release();
+}
+
+static jobject CreateDataPipe(JNIEnv* env,
+ jobject jcaller,
+ jobject options_buffer) {
+ const MojoCreateDataPipeOptions* options = NULL;
+ if (options_buffer) {
+ const void* buffer_start = env->GetDirectBufferAddress(options_buffer);
+ DCHECK(buffer_start);
+ const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer);
+ DCHECK_EQ(buffer_size, sizeof(MojoCreateDataPipeOptions));
+ options = static_cast<const MojoCreateDataPipeOptions*>(buffer_start);
+ DCHECK_EQ(options->struct_size, buffer_size);
+ }
+ MojoHandle handle1;
+ MojoHandle handle2;
+ MojoResult result = MojoCreateDataPipe(options, &handle1, &handle2);
+ return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2)
+ .Release();
+}
+
+static jobject CreateSharedBuffer(JNIEnv* env,
+ jobject jcaller,
+ jobject options_buffer,
+ jlong num_bytes) {
+ const MojoCreateSharedBufferOptions* options = 0;
+ if (options_buffer) {
+ const void* buffer_start = env->GetDirectBufferAddress(options_buffer);
+ DCHECK(buffer_start);
+ const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer);
+ DCHECK_EQ(buffer_size, sizeof(MojoCreateSharedBufferOptions));
+ options = static_cast<const MojoCreateSharedBufferOptions*>(buffer_start);
+ DCHECK_EQ(options->struct_size, buffer_size);
+ }
+ MojoHandle handle;
+ MojoResult result = MojoCreateSharedBuffer(options, num_bytes, &handle);
+ return Java_CoreImpl_newNativeCreationResult(env, result, handle, 0)
+ .Release();
+}
+
+static jint Close(JNIEnv* env, jobject jcaller, jint mojo_handle) {
+ return MojoClose(mojo_handle);
+}
+
+static jint Wait(JNIEnv* env,
+ jobject jcaller,
+ jint mojo_handle,
+ jint flags,
+ jlong deadline) {
+ return MojoWait(mojo_handle, flags, deadline);
+}
+
+static jint WriteMessage(JNIEnv* env,
+ jobject jcaller,
+ jint mojo_handle,
+ jobject bytes,
+ jint num_bytes,
+ jobject handles_buffer,
+ jint flags) {
+ const void* buffer_start = 0;
+ uint32_t buffer_size = 0;
+ if (bytes) {
+ buffer_start = env->GetDirectBufferAddress(bytes);
+ DCHECK(buffer_start);
+ DCHECK(env->GetDirectBufferCapacity(bytes) >= num_bytes);
+ buffer_size = num_bytes;
+ }
+ const MojoHandle* handles = 0;
+ uint32_t num_handles = 0;
+ if (handles_buffer) {
+ handles =
+ static_cast<MojoHandle*>(env->GetDirectBufferAddress(handles_buffer));
+ num_handles = env->GetDirectBufferCapacity(handles_buffer) / 4;
+ }
+ // Java code will handle invalidating handles if the write succeeded.
+ return MojoWriteMessage(
+ mojo_handle, buffer_start, buffer_size, handles, num_handles, flags);
+}
+
+static jobject ReadMessage(JNIEnv* env,
+ jobject jcaller,
+ jint mojo_handle,
+ jobject bytes,
+ jobject handles_buffer,
+ jint flags) {
+ void* buffer_start = 0;
+ uint32_t buffer_size = 0;
+ if (bytes) {
+ buffer_start = env->GetDirectBufferAddress(bytes);
+ DCHECK(buffer_start);
+ buffer_size = env->GetDirectBufferCapacity(bytes);
+ }
+ MojoHandle* handles = 0;
+ uint32_t num_handles = 0;
+ if (handles_buffer) {
+ handles =
+ static_cast<MojoHandle*>(env->GetDirectBufferAddress(handles_buffer));
+ num_handles = env->GetDirectBufferCapacity(handles_buffer) / 4;
+ }
+ MojoResult result = MojoReadMessage(
+ mojo_handle, buffer_start, &buffer_size, handles, &num_handles, flags);
+ // Jave code will handle taking ownership of any received handle.
+ return Java_CoreImpl_newNativeReadMessageResult(
+ env, result, buffer_size, num_handles).Release();
+}
+
+static jint ReadData(JNIEnv* env,
+ jobject jcaller,
+ jint mojo_handle,
+ jobject elements,
+ jint elements_capacity,
+ jint flags) {
+ void* buffer_start = 0;
+ uint32_t buffer_size = elements_capacity;
+ if (elements) {
+ buffer_start = env->GetDirectBufferAddress(elements);
+ DCHECK(buffer_start);
+ DCHECK(elements_capacity <= env->GetDirectBufferCapacity(elements));
+ }
+ MojoResult result =
+ MojoReadData(mojo_handle, buffer_start, &buffer_size, flags);
+ if (result < 0) {
+ return result;
+ }
+ return buffer_size;
+}
+
+static jobject BeginReadData(JNIEnv* env,
+ jobject jcaller,
+ jint mojo_handle,
+ jint num_bytes,
+ jint flags) {
+ void const* buffer = 0;
+ uint32_t buffer_size = num_bytes;
+ MojoResult result =
+ MojoBeginReadData(mojo_handle, &buffer, &buffer_size, flags);
+ jobject byte_buffer = 0;
+ if (result == MOJO_RESULT_OK) {
+ byte_buffer =
+ env->NewDirectByteBuffer(const_cast<void*>(buffer), buffer_size);
+ }
+ return Java_CoreImpl_newNativeCodeAndBufferResult(env, result, byte_buffer)
+ .Release();
+}
+
+static jint EndReadData(JNIEnv* env,
+ jobject jcaller,
+ jint mojo_handle,
+ jint num_bytes_read) {
+ return MojoEndReadData(mojo_handle, num_bytes_read);
+}
+
+static jint WriteData(JNIEnv* env,
+ jobject jcaller,
+ jint mojo_handle,
+ jobject elements,
+ jint limit,
+ jint flags) {
+ void* buffer_start = env->GetDirectBufferAddress(elements);
+ DCHECK(buffer_start);
+ DCHECK(limit <= env->GetDirectBufferCapacity(elements));
+ uint32_t buffer_size = limit;
+ MojoResult result =
+ MojoWriteData(mojo_handle, buffer_start, &buffer_size, flags);
+ if (result < 0) {
+ return result;
+ }
+ return buffer_size;
+}
+
+static jobject BeginWriteData(JNIEnv* env,
+ jobject jcaller,
+ jint mojo_handle,
+ jint num_bytes,
+ jint flags) {
+ void* buffer = 0;
+ uint32_t buffer_size = num_bytes;
+ MojoResult result =
+ MojoBeginWriteData(mojo_handle, &buffer, &buffer_size, flags);
+ jobject byte_buffer = 0;
+ if (result == MOJO_RESULT_OK) {
+ byte_buffer = env->NewDirectByteBuffer(buffer, buffer_size);
+ }
+ return Java_CoreImpl_newNativeCodeAndBufferResult(env, result, byte_buffer)
+ .Release();
+}
+
+static jint EndWriteData(JNIEnv* env,
+ jobject jcaller,
+ jint mojo_handle,
+ jint num_bytes_written) {
+ return MojoEndWriteData(mojo_handle, num_bytes_written);
+}
+
+static jobject Duplicate(JNIEnv* env,
+ jobject jcaller,
+ jint mojo_handle,
+ jobject options_buffer) {
+ const MojoDuplicateBufferHandleOptions* options = 0;
+ if (options_buffer) {
+ const void* buffer_start = env->GetDirectBufferAddress(options_buffer);
+ DCHECK(buffer_start);
+ const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer);
+ DCHECK_EQ(buffer_size, sizeof(MojoDuplicateBufferHandleOptions));
+ options =
+ static_cast<const MojoDuplicateBufferHandleOptions*>(buffer_start);
+ DCHECK_EQ(options->struct_size, buffer_size);
+ }
+ MojoHandle handle;
+ MojoResult result = MojoDuplicateBufferHandle(mojo_handle, options, &handle);
+ return Java_CoreImpl_newNativeCreationResult(env, result, handle, 0)
+ .Release();
+}
+
+static jobject Map(JNIEnv* env,
+ jobject jcaller,
+ jint mojo_handle,
+ jlong offset,
+ jlong num_bytes,
+ jint flags) {
+ void* buffer = 0;
+ MojoResult result =
+ MojoMapBuffer(mojo_handle, offset, num_bytes, &buffer, flags);
+ jobject byte_buffer = 0;
+ if (result == MOJO_RESULT_OK) {
+ byte_buffer = env->NewDirectByteBuffer(buffer, num_bytes);
+ }
+ return Java_CoreImpl_newNativeCodeAndBufferResult(env, result, byte_buffer)
+ .Release();
+}
+
+static int Unmap(JNIEnv* env, jobject jcaller, jobject buffer) {
+ void* buffer_start = env->GetDirectBufferAddress(buffer);
+ DCHECK(buffer_start);
+ return MojoUnmapBuffer(buffer_start);
+}
+
+bool RegisterCoreImpl(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+} // namespace android
+} // namespace mojo
diff --git a/mojo/android/system/core_impl.h b/mojo/android/system/core_impl.h
new file mode 100644
index 0000000..c624999
--- /dev/null
+++ b/mojo/android/system/core_impl.h
@@ -0,0 +1,20 @@
+// Copyright 2014 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 MOJO_ANDROID_SYSTEM_CORE_IMPL_H_
+#define MOJO_ANDROID_SYSTEM_CORE_IMPL_H_
+
+#include <jni.h>
+
+#include "base/android/jni_android.h"
+
+namespace mojo {
+namespace android {
+
+JNI_EXPORT bool RegisterCoreImpl(JNIEnv* env);
+
+} // namespace android
+} // namespace mojo
+
+#endif // MOJO_ANDROID_SYSTEM_CORE_IMPL_H_
diff --git a/mojo/android/system/src/org/chromium/mojo/system/CoreImpl.java b/mojo/android/system/src/org/chromium/mojo/system/CoreImpl.java
new file mode 100644
index 0000000..1d8e56b
--- /dev/null
+++ b/mojo/android/system/src/org/chromium/mojo/system/CoreImpl.java
@@ -0,0 +1,584 @@
+// Copyright 2014 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.
+
+package org.chromium.mojo.system;
+
+import org.chromium.base.CalledByNative;
+import org.chromium.base.JNINamespace;
+import org.chromium.mojo.system.DataPipe.ConsumerHandle;
+import org.chromium.mojo.system.DataPipe.ProducerHandle;
+import org.chromium.mojo.system.SharedBufferHandle.DuplicateOptions;
+import org.chromium.mojo.system.SharedBufferHandle.MapFlags;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Implementation of {@link Core}.
+ */
+@JNINamespace("mojo::android")
+class CoreImpl implements Core {
+
+ /**
+ * Discard flag for the |MojoReadData| operation.
+ */
+ private static final int MOJO_READ_DATA_FLAG_DISCARD = 1 << 1;
+
+ /**
+ * the size of a handle, in bytes.
+ */
+ private static final int HANDLE_SIZE = 4;
+
+ /**
+ * the size of a flag, in bytes.
+ */
+ private static final int FLAG_SIZE = 4;
+
+ /**
+ * The singleton instance.
+ */
+ private static Core sINSTANCE = null;
+
+ /**
+ * @return the instance.
+ */
+ static synchronized Core getInstance() {
+ if (sINSTANCE == null) {
+ sINSTANCE = new CoreImpl();
+ }
+ return sINSTANCE;
+ }
+
+ private CoreImpl() {
+ nativeConstructor();
+ }
+
+ /**
+ * @see Core#getTimeTicksNow()
+ */
+ @Override
+ public long getTimeTicksNow() {
+ return nativeGetTimeTicksNow();
+ }
+
+ /**
+ * @see Core#waitMany(List, long)
+ */
+ @Override
+ public WaitManyResult waitMany(List<Pair<Handle, WaitFlags>> handles, long deadline) {
+ // Allocate a direct buffer to allow native code not to reach back to java. Buffer will
+ // contain all mojo handles, followed by all flags values.
+ ByteBuffer buffer = allocateDirectBuffer(handles.size() * 8);
+ int index = 0;
+ for (Pair<Handle, WaitFlags> handle : handles) {
+ HandleImpl realHandler = (HandleImpl) handle.first;
+ buffer.putInt(HANDLE_SIZE * index, realHandler.getMojoHandle());
+ buffer.putInt(HANDLE_SIZE * handles.size() + FLAG_SIZE * index,
+ handle.second.getFlags());
+ index++;
+ }
+ int code = nativeWaitMany(buffer, deadline);
+ WaitManyResult result = new WaitManyResult();
+ // If result is greater than 0, result is the indexed of the available handle. To make sure
+ // it cannot be misinterpreted, set handleIndex to a negative number in case of error.
+ result.setHandleIndex(code);
+ result.setMojoResult(filterMojoResultForWait(code));
+ return result;
+ }
+
+ /**
+ * @see Core#wait(Handle, WaitFlags, long)
+ */
+ @Override
+ public int wait(Handle handle, WaitFlags flags, long deadline) {
+ return filterMojoResultForWait(nativeWait(((HandleImpl) handle).getMojoHandle(),
+ flags.getFlags(), deadline));
+ }
+
+ /**
+ * @see Core#createMessagePipe()
+ */
+ @Override
+ public Pair<MessagePipeHandle, MessagePipeHandle> createMessagePipe() {
+ NativeCreationResult result = nativeCreateMessagePipe();
+ if (result.getMojoResult() != MojoResult.OK) {
+ throw new MojoException(result.getMojoResult());
+ }
+ return Pair.create(
+ new MessagePipeHandleImpl(this, result.getMojoHandle1()),
+ new MessagePipeHandleImpl(this, result.getMojoHandle2()));
+ }
+
+ /**
+ * @see Core#createDataPipe(DataPipe.CreateOptions)
+ */
+ @Override
+ public Pair<ProducerHandle, ConsumerHandle> createDataPipe(DataPipe.CreateOptions options) {
+ ByteBuffer optionsBuffer = null;
+ if (options != null) {
+ optionsBuffer = allocateDirectBuffer(16);
+ optionsBuffer.putInt(0, 16);
+ optionsBuffer.putInt(4, options.getFlags().getFlags());
+ optionsBuffer.putInt(8, options.getElementNumBytes());
+ optionsBuffer.putInt(12, options.getCapacityNumBytes());
+ }
+ NativeCreationResult result = nativeCreateDataPipe(optionsBuffer);
+ if (result.getMojoResult() != MojoResult.OK) {
+ throw new MojoException(result.getMojoResult());
+ }
+ return Pair.create(
+ new DataPipeProducerHandleImpl(this, result.getMojoHandle1()),
+ new DataPipeConsumerHandleImpl(this, result.getMojoHandle2()));
+ }
+
+ /**
+ * @see Core#createSharedBuffer(SharedBufferHandle.CreateOptions, long)
+ */
+ @Override
+ public SharedBufferHandle createSharedBuffer(
+ SharedBufferHandle.CreateOptions options, long numBytes) {
+ ByteBuffer optionsBuffer = null;
+ if (options != null) {
+ optionsBuffer = allocateDirectBuffer(8);
+ optionsBuffer.putInt(0, 8);
+ optionsBuffer.putInt(4, options.getFlags().getFlags());
+ }
+ NativeCreationResult result = nativeCreateSharedBuffer(optionsBuffer, numBytes);
+ if (result.getMojoResult() != MojoResult.OK) {
+ throw new MojoException(result.getMojoResult());
+ }
+ assert result.getMojoHandle2() == 0;
+ return new SharedBufferHandleImpl(this, result.getMojoHandle1());
+ }
+
+ int closeWithResult(int mojoHandle) {
+ return nativeClose(mojoHandle);
+ }
+
+ void close(int mojoHandle) {
+ int mojoResult = nativeClose(mojoHandle);
+ if (mojoResult != MojoResult.OK) {
+ throw new MojoException(mojoResult);
+ }
+ }
+
+ /**
+ * @see MessagePipeHandle#writeMessage(ByteBuffer, List, MessagePipeHandle.WriteFlags)
+ */
+ void writeMessage(MessagePipeHandleImpl pipeHandle, ByteBuffer bytes,
+ List<Handle> handles, MessagePipeHandle.WriteFlags flags) {
+ ByteBuffer handlesBuffer = null;
+ if (handles != null && !handles.isEmpty()) {
+ handlesBuffer = allocateDirectBuffer(handles.size() * HANDLE_SIZE);
+ for (Handle handle : handles) {
+ HandleImpl realHandle = (HandleImpl) handle;
+ handlesBuffer.putInt(realHandle.getMojoHandle());
+ }
+ handlesBuffer.position(0);
+ }
+ int mojoResult = nativeWriteMessage(pipeHandle.getMojoHandle(), bytes,
+ bytes == null ? 0 : bytes.limit(), handlesBuffer,
+ flags.getFlags());
+ if (mojoResult != MojoResult.OK) {
+ throw new MojoException(mojoResult);
+ }
+ // Success means the handles have been invalidated.
+ if (handles != null) {
+ for (Handle handle : handles) {
+ ((HandleImpl) handle).invalidateHandle();
+ }
+ }
+ }
+
+ /**
+ * @see MessagePipeHandle#readMessage(ByteBuffer, int, MessagePipeHandle.ReadFlags)
+ */
+ MessagePipeHandle.ReadMessageResult readMessage(MessagePipeHandleImpl handle,
+ ByteBuffer bytes, int maxNumberOfHandles,
+ MessagePipeHandle.ReadFlags flags) {
+ ByteBuffer handlesBuffer = null;
+ if (maxNumberOfHandles > 0) {
+ handlesBuffer = allocateDirectBuffer(maxNumberOfHandles * HANDLE_SIZE);
+ }
+ NativeReadMessageResult result = nativeReadMessage(
+ handle.getMojoHandle(), bytes, handlesBuffer, flags.getFlags());
+ if (result.getMojoResult() != MojoResult.OK &&
+ result.getMojoResult() != MojoResult.RESOURCE_EXHAUSTED) {
+ throw new MojoException(result.getMojoResult());
+ }
+
+ if (result.getMojoResult() == MojoResult.OK) {
+ if (bytes != null) {
+ bytes.position(0);
+ bytes.limit(result.getReadMessageResult().getMessageSize());
+ }
+
+ List<UntypedHandle> handles = new ArrayList<UntypedHandle>(
+ result.getReadMessageResult().getHandlesCount());
+ for (int i = 0; i < result.getReadMessageResult().getHandlesCount(); ++i) {
+ int mojoHandle = handlesBuffer.getInt(HANDLE_SIZE * i);
+ handles.add(new UntypedHandleImpl(this, mojoHandle));
+ }
+ result.getReadMessageResult().setHandles(handles);
+ }
+ return result.getReadMessageResult();
+ }
+
+ /**
+ * @see DataPipe.ConsumerHandle#discardData(int, DataPipe.ReadFlags)
+ */
+ int discardData(DataPipeConsumerHandleImpl handle, int numBytes,
+ DataPipe.ReadFlags flags) {
+ int result = nativeReadData(handle.getMojoHandle(), null, numBytes,
+ flags.getFlags() | MOJO_READ_DATA_FLAG_DISCARD);
+ if (result < 0) {
+ throw new MojoException(result);
+ }
+ return result;
+ }
+
+ /**
+ * @see DataPipe.ConsumerHandle#readData(ByteBuffer, DataPipe.ReadFlags)
+ */
+ int readData(DataPipeConsumerHandleImpl handle, ByteBuffer elements,
+ DataPipe.ReadFlags flags) {
+ int result = nativeReadData(handle.getMojoHandle(), elements,
+ elements == null ? 0 : elements.capacity(),
+ flags.getFlags());
+ if (result < 0) {
+ throw new MojoException(result);
+ }
+ if (elements != null) {
+ elements.limit(result);
+ }
+ return result;
+ }
+
+ /**
+ * @see DataPipe.ConsumerHandle#beginReadData(int, DataPipe.ReadFlags)
+ */
+ ByteBuffer beginReadData(DataPipeConsumerHandleImpl handle,
+ int numBytes, DataPipe.ReadFlags flags) {
+ NativeCodeAndBufferResult result = nativeBeginReadData(
+ handle.getMojoHandle(),
+ numBytes,
+ flags.getFlags());
+ if (result.getMojoResult() != MojoResult.OK) {
+ throw new MojoException(result.getMojoResult());
+ }
+ return result.getBuffer().asReadOnlyBuffer();
+ }
+
+ /**
+ * @see DataPipe.ConsumerHandle#endReadData(int)
+ */
+ void endReadData(DataPipeConsumerHandleImpl handle,
+ int numBytesRead) {
+ int result = nativeEndReadData(handle.getMojoHandle(), numBytesRead);
+ if (result != MojoResult.OK) {
+ throw new MojoException(result);
+ }
+ }
+
+ /**
+ * @see DataPipe.ProducerHandle#writeData(ByteBuffer, DataPipe.WriteFlags)
+ */
+ int writeData(DataPipeProducerHandleImpl handle, ByteBuffer elements,
+ DataPipe.WriteFlags flags) {
+ return nativeWriteData(handle.getMojoHandle(), elements, elements.limit(),
+ flags.getFlags());
+ }
+
+ /**
+ * @see DataPipe.ProducerHandle#beginWriteData(int, DataPipe.WriteFlags)
+ */
+ ByteBuffer beginWriteData(DataPipeProducerHandleImpl handle,
+ int numBytes, DataPipe.WriteFlags flags) {
+ NativeCodeAndBufferResult result = nativeBeginWriteData(
+ handle.getMojoHandle(),
+ numBytes,
+ flags.getFlags());
+ if (result.getMojoResult() != MojoResult.OK) {
+ throw new MojoException(result.getMojoResult());
+ }
+ return result.getBuffer();
+ }
+
+ /**
+ * @see DataPipe.ProducerHandle#endWriteData(int)
+ */
+ void endWriteData(DataPipeProducerHandleImpl handle,
+ int numBytesWritten) {
+ int result = nativeEndWriteData(handle.getMojoHandle(), numBytesWritten);
+ if (result != MojoResult.OK) {
+ throw new MojoException(result);
+ }
+ }
+
+ /**
+ * @see SharedBufferHandle#duplicate(DuplicateOptions)
+ */
+ SharedBufferHandle duplicate(SharedBufferHandleImpl handle,
+ DuplicateOptions options) {
+ ByteBuffer optionsBuffer = null;
+ if (options != null) {
+ optionsBuffer = allocateDirectBuffer(8);
+ optionsBuffer.putInt(0, 8);
+ optionsBuffer.putInt(4, options.getFlags().getFlags());
+ }
+ NativeCreationResult result = nativeDuplicate(handle.getMojoHandle(),
+ optionsBuffer);
+ if (result.getMojoResult() != MojoResult.OK) {
+ throw new MojoException(result.getMojoResult());
+ }
+ assert result.getMojoHandle2() == 0;
+ return new SharedBufferHandleImpl(this, result.getMojoHandle1());
+ }
+
+ /**
+ * @see SharedBufferHandle#map(long, long, MapFlags)
+ */
+ ByteBuffer map(SharedBufferHandleImpl handle, long offset, long numBytes,
+ MapFlags flags) {
+ NativeCodeAndBufferResult result = nativeMap(handle.getMojoHandle(), offset, numBytes,
+ flags.getFlags());
+ if (result.getMojoResult() != MojoResult.OK) {
+ throw new MojoException(result.getMojoResult());
+ }
+ return result.getBuffer();
+ }
+
+ /**
+ * @see SharedBufferHandle#unmap(ByteBuffer)
+ */
+ void unmap(ByteBuffer buffer) {
+ int result = nativeUnmap(buffer);
+ if (result != MojoResult.OK) {
+ throw new MojoException(result);
+ }
+ }
+
+ private static int filterMojoResultForWait(int code) {
+ if (code >= 0) {
+ return MojoResult.OK;
+ }
+ switch (code) {
+ case MojoResult.DEADLINE_EXCEEDED:
+ case MojoResult.CANCELLED:
+ case MojoResult.FAILED_PRECONDITION:
+ return code;
+ default:
+ throw new MojoException(code);
+ }
+
+ }
+
+ private static ByteBuffer allocateDirectBuffer(int capacity) {
+ ByteBuffer buffer = ByteBuffer.allocateDirect(capacity);
+ buffer.order(ByteOrder.nativeOrder());
+ return buffer;
+ }
+
+ private static class NativeCodeAndBufferResult {
+ private int mMojoResult;
+ private ByteBuffer mBuffer;
+
+ /**
+ * @return the mojoResult
+ */
+ public int getMojoResult() {
+ return mMojoResult;
+ }
+
+ /**
+ * @param mojoResult the mojoResult to set
+ */
+ public void setMojoResult(int mojoResult) {
+ mMojoResult = mojoResult;
+ }
+
+ /**
+ * @return the buffer
+ */
+ public ByteBuffer getBuffer() {
+ return mBuffer;
+ }
+
+ /**
+ * @param buffer the buffer to set
+ */
+ public void setBuffer(ByteBuffer buffer) {
+ mBuffer = buffer;
+ }
+
+ }
+
+ @CalledByNative
+ private static NativeCodeAndBufferResult newNativeCodeAndBufferResult(int mojoResult,
+ ByteBuffer buffer) {
+ NativeCodeAndBufferResult result = new NativeCodeAndBufferResult();
+ result.setMojoResult(mojoResult);
+ result.setBuffer(buffer);
+ return result;
+ }
+
+ private static class NativeReadMessageResult {
+ public int mMojoResult;
+ public MessagePipeHandle.ReadMessageResult mReadMessageResult;
+
+ /**
+ * @return the mojoResult
+ */
+ public int getMojoResult() {
+ return mMojoResult;
+ }
+
+ /**
+ * @param mojoResult the mojoResult to set
+ */
+ public void setMojoResult(int mojoResult) {
+ this.mMojoResult = mojoResult;
+ }
+
+ /**
+ * @return the readMessageResult
+ */
+ public MessagePipeHandle.ReadMessageResult getReadMessageResult() {
+ return mReadMessageResult;
+ }
+
+ /**
+ * @param readMessageResult the readMessageResult to set
+ */
+ public void setReadMessageResult(MessagePipeHandle.ReadMessageResult readMessageResult) {
+ this.mReadMessageResult = readMessageResult;
+ }
+ }
+
+ @CalledByNative
+ private static NativeReadMessageResult newNativeReadMessageResult(int mojoResult,
+ int messageSize,
+ int handlesCount) {
+ NativeReadMessageResult result = new NativeReadMessageResult();
+ if (mojoResult >= 0) {
+ result.setMojoResult(MojoResult.OK);
+ } else {
+ result.setMojoResult(mojoResult);
+ }
+ MessagePipeHandle.ReadMessageResult readMessageResult =
+ new MessagePipeHandle.ReadMessageResult();
+ readMessageResult.setWasMessageRead(result.getMojoResult() == MojoResult.OK);
+ readMessageResult.setMessageSize(messageSize);
+ readMessageResult.setHandlesCount(handlesCount);
+ result.setReadMessageResult(readMessageResult);
+ return result;
+ }
+
+ private static class NativeCreationResult {
+ private int mMojoResult;
+ private int mMojoHandle1;
+ private int mMojoHandle2;
+
+ /**
+ * @return the mojoResult
+ */
+ public int getMojoResult() {
+ return mMojoResult;
+ }
+
+ /**
+ * @param mojoResult the mojoResult to set
+ */
+ public void setMojoResult(int mojoResult) {
+ mMojoResult = mojoResult;
+ }
+
+ /**
+ * @return the mojoHandle1
+ */
+ public int getMojoHandle1() {
+ return mMojoHandle1;
+ }
+
+ /**
+ * @param mojoHandle1 the mojoHandle1 to set
+ */
+ public void setMojoHandle1(int mojoHandle1) {
+ mMojoHandle1 = mojoHandle1;
+ }
+
+ /**
+ * @return the mojoHandle2
+ */
+ public int getMojoHandle2() {
+ return mMojoHandle2;
+ }
+
+ /**
+ * @param mojoHandle2 the mojoHandle2 to set
+ */
+ public void setMojoHandle2(int mojoHandle2) {
+ mMojoHandle2 = mojoHandle2;
+ }
+ }
+
+ @CalledByNative
+ private static NativeCreationResult newNativeCreationResult(int mojoResult,
+ int mojoHandle1, int mojoHandle2) {
+ NativeCreationResult result = new NativeCreationResult();
+ result.setMojoResult(mojoResult);
+ result.setMojoHandle1(mojoHandle1);
+ result.setMojoHandle2(mojoHandle2);
+ return result;
+ }
+
+ private native void nativeConstructor();
+
+ private native long nativeGetTimeTicksNow();
+
+ private native int nativeWaitMany(ByteBuffer buffer, long deadline);
+
+ private native NativeCreationResult nativeCreateMessagePipe();
+
+ private native NativeCreationResult nativeCreateDataPipe(ByteBuffer optionsBuffer);
+
+ private native NativeCreationResult nativeCreateSharedBuffer(ByteBuffer optionsBuffer,
+ long numBytes);
+
+ private native int nativeClose(int mojoHandle);
+
+ private native int nativeWait(int mojoHandle, int flags, long deadline);
+
+ private native int nativeWriteMessage(int mojoHandle, ByteBuffer bytes, int numBytes,
+ ByteBuffer handlesBuffer, int flags);
+
+ private native NativeReadMessageResult nativeReadMessage(int mojoHandle, ByteBuffer bytes,
+ ByteBuffer handlesBuffer,
+ int flags);
+
+ private native int nativeReadData(int mojoHandle, ByteBuffer elements, int elementsSize,
+ int flags);
+
+ private native NativeCodeAndBufferResult nativeBeginReadData(int mojoHandle, int numBytes,
+ int flags);
+
+ private native int nativeEndReadData(int mojoHandle, int numBytesRead);
+
+ private native int nativeWriteData(int mojoHandle, ByteBuffer elements, int limit, int flags);
+
+ private native NativeCodeAndBufferResult nativeBeginWriteData(int mojoHandle, int numBytes,
+ int flags);
+
+ private native int nativeEndWriteData(int mojoHandle, int numBytesWritten);
+
+ private native NativeCreationResult nativeDuplicate(int mojoHandle, ByteBuffer optionsBuffer);
+
+ private native NativeCodeAndBufferResult nativeMap(int mojoHandle, long offset, long numBytes,
+ int flags);
+
+ private native int nativeUnmap(ByteBuffer buffer);
+
+}
diff --git a/mojo/android/system/src/org/chromium/mojo/system/CoreSingleton.java b/mojo/android/system/src/org/chromium/mojo/system/CoreSingleton.java
new file mode 100644
index 0000000..3cdbf96
--- /dev/null
+++ b/mojo/android/system/src/org/chromium/mojo/system/CoreSingleton.java
@@ -0,0 +1,18 @@
+// Copyright 2014 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.
+
+package org.chromium.mojo.system;
+
+/**
+ * Access to the core singleton.
+ */
+public class CoreSingleton {
+
+ /**
+ * Access to the {@link Core} singleton.
+ */
+ public static Core getInstance() {
+ return CoreImpl.getInstance();
+ }
+}
diff --git a/mojo/android/system/src/org/chromium/mojo/system/DataPipeConsumerHandleImpl.java b/mojo/android/system/src/org/chromium/mojo/system/DataPipeConsumerHandleImpl.java
new file mode 100644
index 0000000..84985bf
--- /dev/null
+++ b/mojo/android/system/src/org/chromium/mojo/system/DataPipeConsumerHandleImpl.java
@@ -0,0 +1,63 @@
+// Copyright 2014 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.
+
+package org.chromium.mojo.system;
+
+import org.chromium.mojo.system.DataPipe.ConsumerHandle;
+import org.chromium.mojo.system.DataPipe.ReadFlags;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Implementation of {@link ConsumerHandle}.
+ */
+class DataPipeConsumerHandleImpl extends HandleImpl implements ConsumerHandle {
+
+ /**
+ * @see HandleImpl#HandleImpl(CoreImpl, int)
+ */
+ DataPipeConsumerHandleImpl(CoreImpl core, int mojoHandle) {
+ super(core, mojoHandle);
+ }
+
+ /**
+ * @see HandleImpl#HandleImpl(UntypedHandleImpl)
+ */
+ DataPipeConsumerHandleImpl(UntypedHandleImpl other) {
+ super(other);
+ }
+
+ /**
+ * @see ConsumerHandle#discardData(int, ReadFlags)
+ */
+ @Override
+ public int discardData(int numBytes, ReadFlags flags) {
+ return mCore.discardData(this, numBytes, flags);
+ }
+
+ /**
+ * @see ConsumerHandle#readData(ByteBuffer, ReadFlags)
+ */
+ @Override
+ public int readData(ByteBuffer elements, ReadFlags flags) {
+ return mCore.readData(this, elements, flags);
+ }
+
+ /**
+ * @see ConsumerHandle#beginReadData(int, ReadFlags)
+ */
+ @Override
+ public ByteBuffer beginReadData(int numBytes, ReadFlags flags) {
+ return mCore.beginReadData(this, numBytes, flags);
+ }
+
+ /**
+ * @see ConsumerHandle#endReadData(int)
+ */
+ @Override
+ public void endReadData(int numBytesRead) {
+ mCore.endReadData(this, numBytesRead);
+ }
+
+}
diff --git a/mojo/android/system/src/org/chromium/mojo/system/DataPipeProducerHandleImpl.java b/mojo/android/system/src/org/chromium/mojo/system/DataPipeProducerHandleImpl.java
new file mode 100644
index 0000000..d6e00df
--- /dev/null
+++ b/mojo/android/system/src/org/chromium/mojo/system/DataPipeProducerHandleImpl.java
@@ -0,0 +1,55 @@
+// Copyright 2014 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.
+
+package org.chromium.mojo.system;
+
+import org.chromium.mojo.system.DataPipe.ProducerHandle;
+import org.chromium.mojo.system.DataPipe.WriteFlags;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Implementation of {@link ProducerHandle}.
+ */
+class DataPipeProducerHandleImpl extends HandleImpl implements ProducerHandle {
+
+ /**
+ * @see HandleImpl#HandleImpl(CoreImpl, int)
+ */
+ DataPipeProducerHandleImpl(CoreImpl core, int mojoHandle) {
+ super(core, mojoHandle);
+ }
+
+ /**
+ * @see HandleImpl#HandleImpl(UntypedHandleImpl)
+ */
+ DataPipeProducerHandleImpl(UntypedHandleImpl handle) {
+ super(handle);
+ }
+
+ /**
+ * @see DataPipe.ProducerHandle#writeData(ByteBuffer, WriteFlags)
+ */
+ @Override
+ public int writeData(ByteBuffer elements, WriteFlags flags) {
+ return mCore.writeData(this, elements, flags);
+ }
+
+ /**
+ * @see DataPipe.ProducerHandle#beginWriteData(int, WriteFlags)
+ */
+ @Override
+ public ByteBuffer beginWriteData(int numBytes, WriteFlags flags) {
+ return mCore.beginWriteData(this, numBytes, flags);
+ }
+
+ /**
+ * @see DataPipe.ProducerHandle#endWriteData(int)
+ */
+ @Override
+ public void endWriteData(int numBytesWritten) {
+ mCore.endWriteData(this, numBytesWritten);
+ }
+
+}
diff --git a/mojo/android/system/src/org/chromium/mojo/system/HandleImpl.java b/mojo/android/system/src/org/chromium/mojo/system/HandleImpl.java
new file mode 100644
index 0000000..00cb9cd
--- /dev/null
+++ b/mojo/android/system/src/org/chromium/mojo/system/HandleImpl.java
@@ -0,0 +1,112 @@
+// Copyright 2014 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.
+
+package org.chromium.mojo.system;
+
+import android.util.Log;
+
+import org.chromium.mojo.system.Core.WaitFlags;
+
+/**
+ * Implementation of {@link Handle}.
+ */
+class HandleImpl implements Handle {
+
+ private static final String TAG = "HandleImpl";
+
+ private static final int INVALID_HANDLE = 0;
+
+ /**
+ * The pointer to the scoped handle owned by this object.
+ */
+ private int mMojoHandle;
+
+ /**
+ * the core implementation. Will be used to delegate all behavior.
+ */
+ protected CoreImpl mCore;
+
+ /**
+ * Base constructor. Takes ownership of the passed handle.
+ */
+ HandleImpl(CoreImpl core, int mojoHandle) {
+ mCore = core;
+ mMojoHandle = mojoHandle;
+ }
+
+ /**
+ * Constructor for transforming an {@link UntypedHandle} into a specific one.
+ */
+ HandleImpl(UntypedHandleImpl other) {
+ mCore = other.mCore;
+ HandleImpl otherAsHandleImpl = other;
+ int mojoHandle = otherAsHandleImpl.mMojoHandle;
+ otherAsHandleImpl.mMojoHandle = INVALID_HANDLE;
+ mMojoHandle = mojoHandle;
+ }
+
+ /**
+ * @see org.chromium.mojo.system.Handle#close()
+ */
+ @Override
+ public void close() {
+ if (mMojoHandle != INVALID_HANDLE) {
+ // After a close, the handle is invalid whether the close succeed or not.
+ int handle = mMojoHandle;
+ mMojoHandle = INVALID_HANDLE;
+ mCore.close(handle);
+ }
+ }
+
+ /**
+ * @see org.chromium.mojo.system.Handle#wait(WaitFlags, long)
+ */
+ @Override
+ public int wait(WaitFlags flags, long deadline) {
+ return mCore.wait(this, flags, deadline);
+ }
+
+ /**
+ * @see org.chromium.mojo.system.Handle#isValid()
+ */
+ @Override
+ public boolean isValid() {
+ return mMojoHandle != INVALID_HANDLE;
+ }
+
+ /**
+ * Getter for the native scoped handle.
+ *
+ * @return the native scoped handle.
+ */
+ int getMojoHandle() {
+ return mMojoHandle;
+ }
+
+ /**
+ * invalidate the handle. The caller must ensures that the handle does not leak.
+ */
+ void invalidateHandle() {
+ mMojoHandle = INVALID_HANDLE;
+ }
+
+ /**
+ * Close the handle if it is valid. Necessary because we cannot let handle leak, and we cannot
+ * ensure that every handle will be manually closed.
+ *
+ * @see java.lang.Object#finalize()
+ */
+ @Override
+ protected final void finalize() throws Throwable {
+ if (isValid()) {
+ // This should not happen, as the user of this class should close the handle. Adding a
+ // warning.
+ Log.w(TAG, "Handle was not closed.");
+ // Ignore result at this point.
+ mCore.closeWithResult(mMojoHandle);
+ }
+ super.finalize();
+ }
+
+}
diff --git a/mojo/android/system/src/org/chromium/mojo/system/MessagePipeHandleImpl.java b/mojo/android/system/src/org/chromium/mojo/system/MessagePipeHandleImpl.java
new file mode 100644
index 0000000..6441b1c
--- /dev/null
+++ b/mojo/android/system/src/org/chromium/mojo/system/MessagePipeHandleImpl.java
@@ -0,0 +1,47 @@
+// Copyright 2014 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.
+
+package org.chromium.mojo.system;
+
+import java.nio.ByteBuffer;
+import java.util.List;
+
+/**
+ * Implementation of {@link MessagePipeHandle}.
+ */
+class MessagePipeHandleImpl extends HandleImpl implements MessagePipeHandle {
+
+ /**
+ * @see HandleImpl#HandleImpl(CoreImpl, int)
+ */
+ MessagePipeHandleImpl(CoreImpl core, int mojoHandle) {
+ super(core, mojoHandle);
+ }
+
+ /**
+ * @see HandleImpl#HandleImpl(UntypedHandleImpl)
+ */
+ MessagePipeHandleImpl(UntypedHandleImpl handle) {
+ super(handle);
+ }
+
+ /**
+ * @see MessagePipeHandle#writeMessage(ByteBuffer, List, WriteFlags)
+ */
+ @Override
+ public void writeMessage(ByteBuffer bytes, List<Handle> handles, WriteFlags flags) {
+ mCore.writeMessage(this, bytes, handles, flags);
+ }
+
+ /**
+ * @see MessagePipeHandle#readMessage(ByteBuffer, int, ReadFlags)
+ */
+ @Override
+ public ReadMessageResult readMessage(ByteBuffer bytes,
+ int maxNumberOfHandles,
+ ReadFlags flags) {
+ return mCore.readMessage(this, bytes, maxNumberOfHandles, flags);
+ }
+
+}
diff --git a/mojo/android/system/src/org/chromium/mojo/system/SharedBufferHandleImpl.java b/mojo/android/system/src/org/chromium/mojo/system/SharedBufferHandleImpl.java
new file mode 100644
index 0000000..4679bd0
--- /dev/null
+++ b/mojo/android/system/src/org/chromium/mojo/system/SharedBufferHandleImpl.java
@@ -0,0 +1,52 @@
+// Copyright 2014 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.
+
+package org.chromium.mojo.system;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Implementation of {@link SharedBufferHandle}.
+ */
+class SharedBufferHandleImpl extends HandleImpl implements SharedBufferHandle {
+
+ /**
+ * @see HandleImpl#HandleImpl(CoreImpl, int)
+ */
+ SharedBufferHandleImpl(CoreImpl core, int mojoHandle) {
+ super(core, mojoHandle);
+ }
+
+ /**
+ * @see HandleImpl#HandleImpl(UntypedHandleImpl)
+ */
+ SharedBufferHandleImpl(UntypedHandleImpl handle) {
+ super(handle);
+ }
+
+ /**
+ * @see SharedBufferHandle#duplicate(DuplicateOptions)
+ */
+ @Override
+ public SharedBufferHandle duplicate(DuplicateOptions options) {
+ return mCore.duplicate(this, options);
+ }
+
+ /**
+ * @see SharedBufferHandle#map(long, long, MapFlags)
+ */
+ @Override
+ public ByteBuffer map(long offset, long numBytes, MapFlags flags) {
+ return mCore.map(this, offset, numBytes, flags);
+ }
+
+ /**
+ * @see SharedBufferHandle#unmap(ByteBuffer)
+ */
+ @Override
+ public void unmap(ByteBuffer buffer) {
+ mCore.unmap(buffer);
+ }
+
+}
diff --git a/mojo/android/system/src/org/chromium/mojo/system/UntypedHandleImpl.java b/mojo/android/system/src/org/chromium/mojo/system/UntypedHandleImpl.java
new file mode 100644
index 0000000..85c7691
--- /dev/null
+++ b/mojo/android/system/src/org/chromium/mojo/system/UntypedHandleImpl.java
@@ -0,0 +1,54 @@
+// Copyright 2014 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.
+
+package org.chromium.mojo.system;
+
+import org.chromium.mojo.system.DataPipe.ConsumerHandle;
+import org.chromium.mojo.system.DataPipe.ProducerHandle;
+
+/**
+ * Implementation of {@link UntypedHandle}.
+ */
+class UntypedHandleImpl extends HandleImpl implements UntypedHandle {
+
+ /**
+ * @see HandleImpl#HandleImpl(CoreImpl, int)
+ */
+ UntypedHandleImpl(CoreImpl core, int mojoHandle) {
+ super(core, mojoHandle);
+ }
+
+ /**
+ * @see org.chromium.mojo.system.UntypedHandle#toMessagePipeHandle()
+ */
+ @Override
+ public MessagePipeHandle toMessagePipeHandle() {
+ return new MessagePipeHandleImpl(this);
+ }
+
+ /**
+ * @see org.chromium.mojo.system.UntypedHandle#toDataPipeConsumerHandle()
+ */
+ @Override
+ public ConsumerHandle toDataPipeConsumerHandle() {
+ return new DataPipeConsumerHandleImpl(this);
+ }
+
+ /**
+ * @see org.chromium.mojo.system.UntypedHandle#toDataPipeProducerHandle()
+ */
+ @Override
+ public ProducerHandle toDataPipeProducerHandle() {
+ return new DataPipeProducerHandleImpl(this);
+ }
+
+ /**
+ * @see org.chromium.mojo.system.UntypedHandle#toSharedBufferHandle()
+ */
+ @Override
+ public SharedBufferHandle toSharedBufferHandle() {
+ return new SharedBufferHandleImpl(this);
+ }
+
+}