summaryrefslogtreecommitdiff
path: root/mojo/android/system/src
diff options
context:
space:
mode:
Diffstat (limited to 'mojo/android/system/src')
-rw-r--r--mojo/android/system/src/org/chromium/mojo/system/impl/BaseRunLoop.java74
-rw-r--r--mojo/android/system/src/org/chromium/mojo/system/impl/CoreImpl.java522
-rw-r--r--mojo/android/system/src/org/chromium/mojo/system/impl/DataPipeConsumerHandleImpl.java72
-rw-r--r--mojo/android/system/src/org/chromium/mojo/system/impl/DataPipeProducerHandleImpl.java64
-rw-r--r--mojo/android/system/src/org/chromium/mojo/system/impl/HandleBase.java140
-rw-r--r--mojo/android/system/src/org/chromium/mojo/system/impl/MessagePipeHandleImpl.java58
-rw-r--r--mojo/android/system/src/org/chromium/mojo/system/impl/SharedBufferHandleImpl.java62
-rw-r--r--mojo/android/system/src/org/chromium/mojo/system/impl/UntypedHandleImpl.java72
-rw-r--r--mojo/android/system/src/org/chromium/mojo/system/impl/WatcherImpl.java63
9 files changed, 1127 insertions, 0 deletions
diff --git a/mojo/android/system/src/org/chromium/mojo/system/impl/BaseRunLoop.java b/mojo/android/system/src/org/chromium/mojo/system/impl/BaseRunLoop.java
new file mode 100644
index 0000000000..3db6670d71
--- /dev/null
+++ b/mojo/android/system/src/org/chromium/mojo/system/impl/BaseRunLoop.java
@@ -0,0 +1,74 @@
+// 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.
+
+package org.chromium.mojo.system.impl;
+
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+import org.chromium.mojo.system.RunLoop;
+
+/**
+ * Implementation of {@link RunLoop} suitable for the base:: message loop implementation.
+ */
+@JNINamespace("mojo::android")
+class BaseRunLoop implements RunLoop {
+ /**
+ * Pointer to the C run loop.
+ */
+ private long mRunLoopID;
+ private final CoreImpl mCore;
+
+ BaseRunLoop(CoreImpl core) {
+ this.mCore = core;
+ this.mRunLoopID = nativeCreateBaseRunLoop();
+ }
+
+ @Override
+ public void run() {
+ assert mRunLoopID != 0 : "The run loop cannot run once closed";
+ nativeRun();
+ }
+
+ @Override
+ public void runUntilIdle() {
+ assert mRunLoopID != 0 : "The run loop cannot run once closed";
+ nativeRunUntilIdle();
+ }
+
+ @Override
+ public void quit() {
+ assert mRunLoopID != 0 : "The run loop cannot be quitted run once closed";
+ nativeQuit(mRunLoopID);
+ }
+
+ @Override
+ public void postDelayedTask(Runnable runnable, long delay) {
+ assert mRunLoopID != 0 : "The run loop cannot run tasks once closed";
+ nativePostDelayedTask(mRunLoopID, runnable, delay);
+ }
+
+ @Override
+ public void close() {
+ if (mRunLoopID == 0) {
+ return;
+ }
+ // We don't want to de-register a different run loop!
+ assert mCore.getCurrentRunLoop() == this : "Only the current run loop can be closed";
+ mCore.clearCurrentRunLoop();
+ nativeDeleteMessageLoop(mRunLoopID);
+ mRunLoopID = 0;
+ }
+
+ @CalledByNative
+ private static void runRunnable(Runnable runnable) {
+ runnable.run();
+ }
+
+ private native long nativeCreateBaseRunLoop();
+ private native void nativeRun();
+ private native void nativeRunUntilIdle();
+ private native void nativeQuit(long runLoopID);
+ private native void nativePostDelayedTask(long runLoopID, Runnable runnable, long delay);
+ private native void nativeDeleteMessageLoop(long runLoopID);
+}
diff --git a/mojo/android/system/src/org/chromium/mojo/system/impl/CoreImpl.java b/mojo/android/system/src/org/chromium/mojo/system/impl/CoreImpl.java
new file mode 100644
index 0000000000..173f80180f
--- /dev/null
+++ b/mojo/android/system/src/org/chromium/mojo/system/impl/CoreImpl.java
@@ -0,0 +1,522 @@
+// 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.impl;
+
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.annotations.MainDex;
+import org.chromium.mojo.system.Core;
+import org.chromium.mojo.system.Core.HandleSignalsState;
+import org.chromium.mojo.system.DataPipe;
+import org.chromium.mojo.system.DataPipe.ConsumerHandle;
+import org.chromium.mojo.system.DataPipe.ProducerHandle;
+import org.chromium.mojo.system.Handle;
+import org.chromium.mojo.system.MessagePipeHandle;
+import org.chromium.mojo.system.MojoException;
+import org.chromium.mojo.system.MojoResult;
+import org.chromium.mojo.system.Pair;
+import org.chromium.mojo.system.ResultAnd;
+import org.chromium.mojo.system.RunLoop;
+import org.chromium.mojo.system.SharedBufferHandle;
+import org.chromium.mojo.system.SharedBufferHandle.DuplicateOptions;
+import org.chromium.mojo.system.SharedBufferHandle.MapFlags;
+import org.chromium.mojo.system.UntypedHandle;
+import org.chromium.mojo.system.Watcher;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Implementation of {@link Core}.
+ */
+@JNINamespace("mojo::android")
+@MainDex
+public 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 mojo handle for an invalid handle.
+ */
+ static final int INVALID_HANDLE = 0;
+
+ private static class LazyHolder { private static final Core INSTANCE = new CoreImpl(); }
+
+ /**
+ * The run loop for the current thread.
+ */
+ private final ThreadLocal<BaseRunLoop> mCurrentRunLoop = new ThreadLocal<BaseRunLoop>();
+
+ /**
+ * The offset needed to get an aligned buffer.
+ */
+ private final int mByteBufferOffset;
+
+ /**
+ * @return the instance.
+ */
+ public static Core getInstance() {
+ return LazyHolder.INSTANCE;
+ }
+
+ private CoreImpl() {
+ // Fix for the ART runtime, before:
+ // https://android.googlesource.com/platform/libcore/+/fb6c80875a8a8d0a9628562f89c250b6a962e824%5E!/
+ // This assumes consistent allocation.
+ mByteBufferOffset = nativeGetNativeBufferOffset(ByteBuffer.allocateDirect(8), 8);
+ }
+
+ /**
+ * @see Core#getTimeTicksNow()
+ */
+ @Override
+ public long getTimeTicksNow() {
+ return nativeGetTimeTicksNow();
+ }
+
+ /**
+ * @see Core#createMessagePipe(MessagePipeHandle.CreateOptions)
+ */
+ @Override
+ public Pair<MessagePipeHandle, MessagePipeHandle> createMessagePipe(
+ MessagePipeHandle.CreateOptions options) {
+ ByteBuffer optionsBuffer = null;
+ if (options != null) {
+ optionsBuffer = allocateDirectBuffer(8);
+ optionsBuffer.putInt(0, 8);
+ optionsBuffer.putInt(4, options.getFlags().getFlags());
+ }
+ ResultAnd<IntegerPair> result = nativeCreateMessagePipe(optionsBuffer);
+ if (result.getMojoResult() != MojoResult.OK) {
+ throw new MojoException(result.getMojoResult());
+ }
+ return Pair.<MessagePipeHandle, MessagePipeHandle>create(
+ new MessagePipeHandleImpl(this, result.getValue().first),
+ new MessagePipeHandleImpl(this, result.getValue().second));
+ }
+
+ /**
+ * @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());
+ }
+ ResultAnd<IntegerPair> result = nativeCreateDataPipe(optionsBuffer);
+ if (result.getMojoResult() != MojoResult.OK) {
+ throw new MojoException(result.getMojoResult());
+ }
+ return Pair.<ProducerHandle, ConsumerHandle>create(
+ new DataPipeProducerHandleImpl(this, result.getValue().first),
+ new DataPipeConsumerHandleImpl(this, result.getValue().second));
+ }
+
+ /**
+ * @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());
+ }
+ ResultAnd<Integer> result = nativeCreateSharedBuffer(optionsBuffer, numBytes);
+ if (result.getMojoResult() != MojoResult.OK) {
+ throw new MojoException(result.getMojoResult());
+ }
+ return new SharedBufferHandleImpl(this, result.getValue());
+ }
+
+ /**
+ * @see org.chromium.mojo.system.Core#acquireNativeHandle(int)
+ */
+ @Override
+ public UntypedHandle acquireNativeHandle(int handle) {
+ return new UntypedHandleImpl(this, handle);
+ }
+
+ /**
+ * @see Core#getWatcher()
+ */
+ @Override
+ public Watcher getWatcher() {
+ return new WatcherImpl();
+ }
+
+ /**
+ * @see Core#createDefaultRunLoop()
+ */
+ @Override
+ public RunLoop createDefaultRunLoop() {
+ if (mCurrentRunLoop.get() != null) {
+ throw new MojoException(MojoResult.FAILED_PRECONDITION);
+ }
+ BaseRunLoop runLoop = new BaseRunLoop(this);
+ mCurrentRunLoop.set(runLoop);
+ return runLoop;
+ }
+
+ /**
+ * @see Core#getCurrentRunLoop()
+ */
+ @Override
+ public RunLoop getCurrentRunLoop() {
+ return mCurrentRunLoop.get();
+ }
+
+ /**
+ * Remove the current run loop.
+ */
+ void clearCurrentRunLoop() {
+ mCurrentRunLoop.remove();
+ }
+
+ int closeWithResult(int mojoHandle) {
+ return nativeClose(mojoHandle);
+ }
+
+ void close(int mojoHandle) {
+ int mojoResult = nativeClose(mojoHandle);
+ if (mojoResult != MojoResult.OK) {
+ throw new MojoException(mojoResult);
+ }
+ }
+
+ HandleSignalsState queryHandleSignalsState(int mojoHandle) {
+ ByteBuffer buffer = allocateDirectBuffer(8);
+ int result = nativeQueryHandleSignalsState(mojoHandle, buffer);
+ if (result != MojoResult.OK) throw new MojoException(result);
+ return new HandleSignalsState(
+ new HandleSignals(buffer.getInt(0)), new HandleSignals(buffer.getInt(4)));
+ }
+
+ /**
+ * @see MessagePipeHandle#writeMessage(ByteBuffer, List, MessagePipeHandle.WriteFlags)
+ */
+ void writeMessage(MessagePipeHandleImpl pipeHandle, ByteBuffer bytes,
+ List<? extends Handle> handles, MessagePipeHandle.WriteFlags flags) {
+ ByteBuffer handlesBuffer = null;
+ if (handles != null && !handles.isEmpty()) {
+ handlesBuffer = allocateDirectBuffer(handles.size() * HANDLE_SIZE);
+ for (Handle handle : handles) {
+ handlesBuffer.putInt(getMojoHandle(handle));
+ }
+ 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) {
+ if (handle.isValid()) {
+ ((HandleBase) handle).invalidateHandle();
+ }
+ }
+ }
+ }
+
+ /**
+ * @see MessagePipeHandle#readMessage(ByteBuffer, int, MessagePipeHandle.ReadFlags)
+ */
+ ResultAnd<MessagePipeHandle.ReadMessageResult> readMessage(MessagePipeHandleImpl handle,
+ ByteBuffer bytes, int maxNumberOfHandles, MessagePipeHandle.ReadFlags flags) {
+ ByteBuffer handlesBuffer = null;
+ if (maxNumberOfHandles > 0) {
+ handlesBuffer = allocateDirectBuffer(maxNumberOfHandles * HANDLE_SIZE);
+ }
+ ResultAnd<MessagePipeHandle.ReadMessageResult> result =
+ nativeReadMessage(handle.getMojoHandle(), bytes, handlesBuffer, flags.getFlags());
+ if (result.getMojoResult() != MojoResult.OK
+ && result.getMojoResult() != MojoResult.RESOURCE_EXHAUSTED
+ && result.getMojoResult() != MojoResult.SHOULD_WAIT) {
+ throw new MojoException(result.getMojoResult());
+ }
+
+ if (result.getMojoResult() == MojoResult.OK) {
+ MessagePipeHandle.ReadMessageResult readResult = result.getValue();
+ if (bytes != null) {
+ bytes.position(0);
+ bytes.limit(readResult.getMessageSize());
+ }
+
+ List<UntypedHandle> handles =
+ new ArrayList<UntypedHandle>(readResult.getHandlesCount());
+ for (int i = 0; i < readResult.getHandlesCount(); ++i) {
+ int mojoHandle = handlesBuffer.getInt(HANDLE_SIZE * i);
+ handles.add(new UntypedHandleImpl(this, mojoHandle));
+ }
+ readResult.setHandles(handles);
+ }
+ return result;
+ }
+
+ /**
+ * @see ConsumerHandle#discardData(int, DataPipe.ReadFlags)
+ */
+ int discardData(DataPipeConsumerHandleImpl handle, int numBytes, DataPipe.ReadFlags flags) {
+ ResultAnd<Integer> result = nativeReadData(handle.getMojoHandle(), null, numBytes,
+ flags.getFlags() | MOJO_READ_DATA_FLAG_DISCARD);
+ if (result.getMojoResult() != MojoResult.OK) {
+ throw new MojoException(result.getMojoResult());
+ }
+ return result.getValue();
+ }
+
+ /**
+ * @see ConsumerHandle#readData(ByteBuffer, DataPipe.ReadFlags)
+ */
+ ResultAnd<Integer> readData(
+ DataPipeConsumerHandleImpl handle, ByteBuffer elements, DataPipe.ReadFlags flags) {
+ ResultAnd<Integer> result = nativeReadData(handle.getMojoHandle(), elements,
+ elements == null ? 0 : elements.capacity(), flags.getFlags());
+ if (result.getMojoResult() != MojoResult.OK
+ && result.getMojoResult() != MojoResult.SHOULD_WAIT) {
+ throw new MojoException(result.getMojoResult());
+ }
+ if (result.getMojoResult() == MojoResult.OK) {
+ if (elements != null) {
+ elements.limit(result.getValue());
+ }
+ }
+ return result;
+ }
+
+ /**
+ * @see ConsumerHandle#beginReadData(int, DataPipe.ReadFlags)
+ */
+ ByteBuffer beginReadData(
+ DataPipeConsumerHandleImpl handle, int numBytes, DataPipe.ReadFlags flags) {
+ ResultAnd<ByteBuffer> result =
+ nativeBeginReadData(handle.getMojoHandle(), numBytes, flags.getFlags());
+ if (result.getMojoResult() != MojoResult.OK) {
+ throw new MojoException(result.getMojoResult());
+ }
+ return result.getValue().asReadOnlyBuffer();
+ }
+
+ /**
+ * @see ConsumerHandle#endReadData(int)
+ */
+ void endReadData(DataPipeConsumerHandleImpl handle, int numBytesRead) {
+ int result = nativeEndReadData(handle.getMojoHandle(), numBytesRead);
+ if (result != MojoResult.OK) {
+ throw new MojoException(result);
+ }
+ }
+
+ /**
+ * @see ProducerHandle#writeData(ByteBuffer, DataPipe.WriteFlags)
+ */
+ ResultAnd<Integer> writeData(
+ DataPipeProducerHandleImpl handle, ByteBuffer elements, DataPipe.WriteFlags flags) {
+ return nativeWriteData(
+ handle.getMojoHandle(), elements, elements.limit(), flags.getFlags());
+ }
+
+ /**
+ * @see ProducerHandle#beginWriteData(int, DataPipe.WriteFlags)
+ */
+ ByteBuffer beginWriteData(
+ DataPipeProducerHandleImpl handle, int numBytes, DataPipe.WriteFlags flags) {
+ ResultAnd<ByteBuffer> result =
+ nativeBeginWriteData(handle.getMojoHandle(), numBytes, flags.getFlags());
+ if (result.getMojoResult() != MojoResult.OK) {
+ throw new MojoException(result.getMojoResult());
+ }
+ return result.getValue();
+ }
+
+ /**
+ * @see 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());
+ }
+ ResultAnd<Integer> result = nativeDuplicate(handle.getMojoHandle(), optionsBuffer);
+ if (result.getMojoResult() != MojoResult.OK) {
+ throw new MojoException(result.getMojoResult());
+ }
+ return new SharedBufferHandleImpl(this, result.getValue());
+ }
+
+ /**
+ * @see SharedBufferHandle#map(long, long, MapFlags)
+ */
+ ByteBuffer map(SharedBufferHandleImpl handle, long offset, long numBytes, MapFlags flags) {
+ ResultAnd<ByteBuffer> result =
+ nativeMap(handle.getMojoHandle(), offset, numBytes, flags.getFlags());
+ if (result.getMojoResult() != MojoResult.OK) {
+ throw new MojoException(result.getMojoResult());
+ }
+ return result.getValue();
+ }
+
+ /**
+ * @see SharedBufferHandle#unmap(ByteBuffer)
+ */
+ void unmap(ByteBuffer buffer) {
+ int result = nativeUnmap(buffer);
+ if (result != MojoResult.OK) {
+ throw new MojoException(result);
+ }
+ }
+
+ /**
+ * @return the mojo handle associated to the given handle, considering invalid handles.
+ */
+ private int getMojoHandle(Handle handle) {
+ if (handle.isValid()) {
+ return ((HandleBase) handle).getMojoHandle();
+ }
+ return 0;
+ }
+
+ private static boolean isUnrecoverableError(int code) {
+ switch (code) {
+ case MojoResult.OK:
+ case MojoResult.DEADLINE_EXCEEDED:
+ case MojoResult.CANCELLED:
+ case MojoResult.FAILED_PRECONDITION:
+ return false;
+ default:
+ return true;
+ }
+ }
+
+ private static int filterMojoResultForWait(int code) {
+ if (isUnrecoverableError(code)) {
+ throw new MojoException(code);
+ }
+ return code;
+ }
+
+ private ByteBuffer allocateDirectBuffer(int capacity) {
+ ByteBuffer buffer = ByteBuffer.allocateDirect(capacity + mByteBufferOffset);
+ if (mByteBufferOffset != 0) {
+ buffer.position(mByteBufferOffset);
+ buffer = buffer.slice();
+ }
+ return buffer.order(ByteOrder.nativeOrder());
+ }
+
+ @CalledByNative
+ private static ResultAnd<ByteBuffer> newResultAndBuffer(int mojoResult, ByteBuffer buffer) {
+ return new ResultAnd<>(mojoResult, buffer);
+ }
+
+ /**
+ * Trivial alias for Pair<Integer, Integer>. This is needed because our jni generator is unable
+ * to handle class that contains space.
+ */
+ private static final class IntegerPair extends Pair<Integer, Integer> {
+ public IntegerPair(Integer first, Integer second) {
+ super(first, second);
+ }
+ }
+
+ @CalledByNative
+ private static ResultAnd<MessagePipeHandle.ReadMessageResult> newReadMessageResult(
+ int mojoResult, int messageSize, int handlesCount) {
+ MessagePipeHandle.ReadMessageResult result = new MessagePipeHandle.ReadMessageResult();
+ result.setMessageSize(messageSize);
+ result.setHandlesCount(handlesCount);
+ return new ResultAnd<>(mojoResult, result);
+ }
+
+ @CalledByNative
+ private static ResultAnd<Integer> newResultAndInteger(int mojoResult, int numBytesRead) {
+ return new ResultAnd<>(mojoResult, numBytesRead);
+ }
+
+ @CalledByNative
+ private static ResultAnd<IntegerPair> newNativeCreationResult(
+ int mojoResult, int mojoHandle1, int mojoHandle2) {
+ return new ResultAnd<>(mojoResult, new IntegerPair(mojoHandle1, mojoHandle2));
+ }
+
+ private native long nativeGetTimeTicksNow();
+
+ private native ResultAnd<IntegerPair> nativeCreateMessagePipe(ByteBuffer optionsBuffer);
+
+ private native ResultAnd<IntegerPair> nativeCreateDataPipe(ByteBuffer optionsBuffer);
+
+ private native ResultAnd<Integer> nativeCreateSharedBuffer(
+ ByteBuffer optionsBuffer, long numBytes);
+
+ private native int nativeClose(int mojoHandle);
+
+ private native int nativeQueryHandleSignalsState(int mojoHandle, ByteBuffer signalsStateBuffer);
+
+ private native int nativeWriteMessage(
+ int mojoHandle, ByteBuffer bytes, int numBytes, ByteBuffer handlesBuffer, int flags);
+
+ private native ResultAnd<MessagePipeHandle.ReadMessageResult> nativeReadMessage(
+ int mojoHandle, ByteBuffer bytes, ByteBuffer handlesBuffer, int flags);
+
+ private native ResultAnd<Integer> nativeReadData(
+ int mojoHandle, ByteBuffer elements, int elementsSize, int flags);
+
+ private native ResultAnd<ByteBuffer> nativeBeginReadData(
+ int mojoHandle, int numBytes, int flags);
+
+ private native int nativeEndReadData(int mojoHandle, int numBytesRead);
+
+ private native ResultAnd<Integer> nativeWriteData(
+ int mojoHandle, ByteBuffer elements, int limit, int flags);
+
+ private native ResultAnd<ByteBuffer> nativeBeginWriteData(
+ int mojoHandle, int numBytes, int flags);
+
+ private native int nativeEndWriteData(int mojoHandle, int numBytesWritten);
+
+ private native ResultAnd<Integer> nativeDuplicate(int mojoHandle, ByteBuffer optionsBuffer);
+
+ private native ResultAnd<ByteBuffer> nativeMap(
+ int mojoHandle, long offset, long numBytes, int flags);
+
+ private native int nativeUnmap(ByteBuffer buffer);
+
+ private native int nativeGetNativeBufferOffset(ByteBuffer buffer, int alignment);
+}
diff --git a/mojo/android/system/src/org/chromium/mojo/system/impl/DataPipeConsumerHandleImpl.java b/mojo/android/system/src/org/chromium/mojo/system/impl/DataPipeConsumerHandleImpl.java
new file mode 100644
index 0000000000..83097d7eb4
--- /dev/null
+++ b/mojo/android/system/src/org/chromium/mojo/system/impl/DataPipeConsumerHandleImpl.java
@@ -0,0 +1,72 @@
+// 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.impl;
+
+import org.chromium.mojo.system.DataPipe.ConsumerHandle;
+import org.chromium.mojo.system.DataPipe.ReadFlags;
+import org.chromium.mojo.system.ResultAnd;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Implementation of {@link ConsumerHandle}.
+ */
+class DataPipeConsumerHandleImpl extends HandleBase implements ConsumerHandle {
+
+ /**
+ * @see HandleBase#HandleBase(CoreImpl, int)
+ */
+ DataPipeConsumerHandleImpl(CoreImpl core, int mojoHandle) {
+ super(core, mojoHandle);
+ }
+
+ /**
+ * @see HandleBase#HandleBase(HandleBase)
+ */
+ DataPipeConsumerHandleImpl(HandleBase other) {
+ super(other);
+ }
+
+ /**
+ * @see org.chromium.mojo.system.Handle#pass()
+ */
+ @Override
+ public ConsumerHandle pass() {
+ return new DataPipeConsumerHandleImpl(this);
+ }
+
+ /**
+ * @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 ResultAnd<Integer> 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/impl/DataPipeProducerHandleImpl.java b/mojo/android/system/src/org/chromium/mojo/system/impl/DataPipeProducerHandleImpl.java
new file mode 100644
index 0000000000..901f26c029
--- /dev/null
+++ b/mojo/android/system/src/org/chromium/mojo/system/impl/DataPipeProducerHandleImpl.java
@@ -0,0 +1,64 @@
+// 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.impl;
+
+import org.chromium.mojo.system.DataPipe.ProducerHandle;
+import org.chromium.mojo.system.DataPipe.WriteFlags;
+import org.chromium.mojo.system.ResultAnd;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Implementation of {@link ProducerHandle}.
+ */
+class DataPipeProducerHandleImpl extends HandleBase implements ProducerHandle {
+
+ /**
+ * @see HandleBase#HandleBase(CoreImpl, int)
+ */
+ DataPipeProducerHandleImpl(CoreImpl core, int mojoHandle) {
+ super(core, mojoHandle);
+ }
+
+ /**
+ * @see HandleBase#HandleBase(HandleBase)
+ */
+ DataPipeProducerHandleImpl(HandleBase handle) {
+ super(handle);
+ }
+
+ /**
+ * @see org.chromium.mojo.system.DataPipe.ProducerHandle#pass()
+ */
+ @Override
+ public ProducerHandle pass() {
+ return new DataPipeProducerHandleImpl(this);
+ }
+
+ /**
+ * @see ProducerHandle#writeData(ByteBuffer, WriteFlags)
+ */
+ @Override
+ public ResultAnd<Integer> writeData(ByteBuffer elements, WriteFlags flags) {
+ return mCore.writeData(this, elements, flags);
+ }
+
+ /**
+ * @see ProducerHandle#beginWriteData(int, WriteFlags)
+ */
+ @Override
+ public ByteBuffer beginWriteData(int numBytes, WriteFlags flags) {
+ return mCore.beginWriteData(this, numBytes, flags);
+ }
+
+ /**
+ * @see ProducerHandle#endWriteData(int)
+ */
+ @Override
+ public void endWriteData(int numBytesWritten) {
+ mCore.endWriteData(this, numBytesWritten);
+ }
+
+}
diff --git a/mojo/android/system/src/org/chromium/mojo/system/impl/HandleBase.java b/mojo/android/system/src/org/chromium/mojo/system/impl/HandleBase.java
new file mode 100644
index 0000000000..4d149a48d7
--- /dev/null
+++ b/mojo/android/system/src/org/chromium/mojo/system/impl/HandleBase.java
@@ -0,0 +1,140 @@
+// 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.impl;
+
+import android.util.Log;
+
+import org.chromium.mojo.system.Core;
+import org.chromium.mojo.system.Core.HandleSignalsState;
+import org.chromium.mojo.system.Handle;
+import org.chromium.mojo.system.UntypedHandle;
+
+/**
+ * Implementation of {@link Handle}.
+ */
+abstract class HandleBase implements Handle {
+
+ private static final String TAG = "HandleImpl";
+
+ /**
+ * 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.
+ */
+ HandleBase(CoreImpl core, int mojoHandle) {
+ mCore = core;
+ mMojoHandle = mojoHandle;
+ }
+
+ /**
+ * Constructor for transforming {@link HandleBase} into a specific one. It is used to transform
+ * an {@link UntypedHandle} into a typed one, or any handle into an {@link UntypedHandle}.
+ */
+ protected HandleBase(HandleBase other) {
+ mCore = other.mCore;
+ HandleBase otherAsHandleImpl = other;
+ int mojoHandle = otherAsHandleImpl.mMojoHandle;
+ otherAsHandleImpl.mMojoHandle = CoreImpl.INVALID_HANDLE;
+ mMojoHandle = mojoHandle;
+ }
+
+ /**
+ * @see org.chromium.mojo.system.Handle#close()
+ */
+ @Override
+ public void close() {
+ if (mMojoHandle != CoreImpl.INVALID_HANDLE) {
+ // After a close, the handle is invalid whether the close succeed or not.
+ int handle = mMojoHandle;
+ mMojoHandle = CoreImpl.INVALID_HANDLE;
+ mCore.close(handle);
+ }
+ }
+
+ /**
+ * @see org.chromium.mojo.system.Handle#querySignalsState()
+ */
+ @Override
+ public HandleSignalsState querySignalsState() {
+ return mCore.queryHandleSignalsState(mMojoHandle);
+ }
+
+ /**
+ * @see org.chromium.mojo.system.Handle#isValid()
+ */
+ @Override
+ public boolean isValid() {
+ return mMojoHandle != CoreImpl.INVALID_HANDLE;
+ }
+
+ /**
+ * @see org.chromium.mojo.system.Handle#toUntypedHandle()
+ */
+ @Override
+ public UntypedHandle toUntypedHandle() {
+ return new UntypedHandleImpl(this);
+ }
+
+ /**
+ * @see org.chromium.mojo.system.Handle#getCore()
+ */
+ @Override
+ public Core getCore() {
+ return mCore;
+ }
+
+ /**
+ * @see Handle#releaseNativeHandle()
+ */
+ @Override
+ public int releaseNativeHandle() {
+ int result = mMojoHandle;
+ mMojoHandle = CoreImpl.INVALID_HANDLE;
+ return result;
+ }
+
+ /**
+ * 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 = CoreImpl.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/impl/MessagePipeHandleImpl.java b/mojo/android/system/src/org/chromium/mojo/system/impl/MessagePipeHandleImpl.java
new file mode 100644
index 0000000000..b3df0aed5b
--- /dev/null
+++ b/mojo/android/system/src/org/chromium/mojo/system/impl/MessagePipeHandleImpl.java
@@ -0,0 +1,58 @@
+// 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.impl;
+
+import org.chromium.mojo.system.Handle;
+import org.chromium.mojo.system.MessagePipeHandle;
+import org.chromium.mojo.system.ResultAnd;
+
+import java.nio.ByteBuffer;
+import java.util.List;
+
+/**
+ * Implementation of {@link MessagePipeHandle}.
+ */
+class MessagePipeHandleImpl extends HandleBase implements MessagePipeHandle {
+
+ /**
+ * @see HandleBase#HandleBase(CoreImpl, int)
+ */
+ MessagePipeHandleImpl(CoreImpl core, int mojoHandle) {
+ super(core, mojoHandle);
+ }
+
+ /**
+ * @see HandleBase#HandleBase(HandleBase)
+ */
+ MessagePipeHandleImpl(HandleBase handle) {
+ super(handle);
+ }
+
+ /**
+ * @see org.chromium.mojo.system.MessagePipeHandle#pass()
+ */
+ @Override
+ public MessagePipeHandle pass() {
+ return new MessagePipeHandleImpl(this);
+ }
+
+ /**
+ * @see MessagePipeHandle#writeMessage(ByteBuffer, List, WriteFlags)
+ */
+ @Override
+ public void writeMessage(ByteBuffer bytes, List<? extends Handle> handles, WriteFlags flags) {
+ mCore.writeMessage(this, bytes, handles, flags);
+ }
+
+ /**
+ * @see MessagePipeHandle#readMessage(ByteBuffer, int, ReadFlags)
+ */
+ @Override
+ public ResultAnd<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/impl/SharedBufferHandleImpl.java b/mojo/android/system/src/org/chromium/mojo/system/impl/SharedBufferHandleImpl.java
new file mode 100644
index 0000000000..76ef73945f
--- /dev/null
+++ b/mojo/android/system/src/org/chromium/mojo/system/impl/SharedBufferHandleImpl.java
@@ -0,0 +1,62 @@
+// 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.impl;
+
+import org.chromium.mojo.system.SharedBufferHandle;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Implementation of {@link SharedBufferHandle}.
+ */
+class SharedBufferHandleImpl extends HandleBase implements SharedBufferHandle {
+
+ /**
+ * @see HandleBase#HandleBase(CoreImpl, int)
+ */
+ SharedBufferHandleImpl(CoreImpl core, int mojoHandle) {
+ super(core, mojoHandle);
+ }
+
+ /**
+ * @see HandleBase#HandleBase(HandleBase)
+ */
+ SharedBufferHandleImpl(HandleBase handle) {
+ super(handle);
+ }
+
+ /**
+ * @see org.chromium.mojo.system.SharedBufferHandle#pass()
+ */
+ @Override
+ public SharedBufferHandle pass() {
+ return new SharedBufferHandleImpl(this);
+ }
+
+ /**
+ * @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/impl/UntypedHandleImpl.java b/mojo/android/system/src/org/chromium/mojo/system/impl/UntypedHandleImpl.java
new file mode 100644
index 0000000000..4774ab86e9
--- /dev/null
+++ b/mojo/android/system/src/org/chromium/mojo/system/impl/UntypedHandleImpl.java
@@ -0,0 +1,72 @@
+// 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.impl;
+
+import org.chromium.mojo.system.DataPipe.ConsumerHandle;
+import org.chromium.mojo.system.DataPipe.ProducerHandle;
+import org.chromium.mojo.system.MessagePipeHandle;
+import org.chromium.mojo.system.SharedBufferHandle;
+import org.chromium.mojo.system.UntypedHandle;
+
+/**
+ * Implementation of {@link UntypedHandle}.
+ */
+class UntypedHandleImpl extends HandleBase implements UntypedHandle {
+
+ /**
+ * @see HandleBase#HandleBase(CoreImpl, int)
+ */
+ UntypedHandleImpl(CoreImpl core, int mojoHandle) {
+ super(core, mojoHandle);
+ }
+
+ /**
+ * @see HandleBase#HandleBase(HandleBase)
+ */
+ UntypedHandleImpl(HandleBase handle) {
+ super(handle);
+ }
+
+ /**
+ * @see org.chromium.mojo.system.UntypedHandle#pass()
+ */
+ @Override
+ public UntypedHandle pass() {
+ return new UntypedHandleImpl(this);
+ }
+
+ /**
+ * @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);
+ }
+
+}
diff --git a/mojo/android/system/src/org/chromium/mojo/system/impl/WatcherImpl.java b/mojo/android/system/src/org/chromium/mojo/system/impl/WatcherImpl.java
new file mode 100644
index 0000000000..094ad90265
--- /dev/null
+++ b/mojo/android/system/src/org/chromium/mojo/system/impl/WatcherImpl.java
@@ -0,0 +1,63 @@
+// Copyright 2016 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.impl;
+
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+import org.chromium.mojo.system.Core;
+import org.chromium.mojo.system.Handle;
+import org.chromium.mojo.system.MojoResult;
+import org.chromium.mojo.system.Watcher;
+
+@JNINamespace("mojo::android")
+class WatcherImpl implements Watcher {
+ private long mImplPtr = nativeCreateWatcher();
+ private Callback mCallback;
+
+ @Override
+ public int start(Handle handle, Core.HandleSignals signals, Callback callback) {
+ if (mImplPtr == 0) {
+ return MojoResult.INVALID_ARGUMENT;
+ }
+ if (!(handle instanceof HandleBase)) {
+ return MojoResult.INVALID_ARGUMENT;
+ }
+ int result =
+ nativeStart(mImplPtr, ((HandleBase) handle).getMojoHandle(), signals.getFlags());
+ if (result == MojoResult.OK) mCallback = callback;
+ return result;
+ }
+
+ @Override
+ public void cancel() {
+ if (mImplPtr == 0) {
+ return;
+ }
+ mCallback = null;
+ nativeCancel(mImplPtr);
+ }
+
+ @Override
+ public void destroy() {
+ if (mImplPtr == 0) {
+ return;
+ }
+ nativeDelete(mImplPtr);
+ mImplPtr = 0;
+ }
+
+ @CalledByNative
+ private void onHandleReady(int result) {
+ mCallback.onResult(result);
+ }
+
+ private native long nativeCreateWatcher();
+
+ private native int nativeStart(long implPtr, int mojoHandle, int flags);
+
+ private native void nativeCancel(long implPtr);
+
+ private native void nativeDelete(long implPtr);
+}