Index: mojo/system/android/src/org/chromium/mojo/system/CoreImpl.java |
diff --git a/mojo/system/android/src/org/chromium/mojo/system/CoreImpl.java b/mojo/system/android/src/org/chromium/mojo/system/CoreImpl.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..1468dc0c351916d42805411ad95311096c3e193a |
--- /dev/null |
+++ b/mojo/system/android/src/org/chromium/mojo/system/CoreImpl.java |
@@ -0,0 +1,619 @@ |
+// 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.DataPipe.ReadFlags; |
+import org.chromium.mojo.system.DataPipe.WriteFlags; |
+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; |
+ |
+/** |
+ * TODO(qsr): Insert description here. |
+ */ |
+@JNINamespace("mojo") |
+public class CoreImpl implements Core { |
+ |
+ /** |
+ * The singleton instance. |
+ */ |
+ private static Core sINSTANCE = null; |
+ |
+ /** |
+ * @return the instance. |
+ */ |
+ public static synchronized Core getInstance() { |
+ if (sINSTANCE == null) { |
+ sINSTANCE = new CoreImpl(); |
+ } |
+ return sINSTANCE; |
+ } |
+ |
+ private CoreImpl() { |
+ nativeConstructor(); |
+ } |
+ |
+ /* |
+ * (non-Javadoc) |
+ * @see org.chromium.mojo.system.Core#getTimeTicksNow() |
+ */ |
+ @Override |
+ public long getTimeTicksNow() { |
+ return nativeGetTimeTicksNow(); |
+ } |
+ |
+ private static MojoResult waitMojoResultToBoolean(int code) { |
+ MojoResult mojoResult = MojoResult.forCode(code); |
+ switch (mojoResult) { |
+ case OK: |
+ case DEADLINE_EXCEEDED: |
+ case CANCELLED: |
+ case FAILED_PRECONDITION: |
+ return mojoResult; |
+ default: |
+ throw new MojoException(mojoResult); |
+ } |
+ |
+ } |
+ |
+ private static ByteBuffer allocateDirectBuffer(int capacity) { |
+ ByteBuffer buffer = ByteBuffer.allocateDirect(capacity); |
+ buffer.order(ByteOrder.LITTLE_ENDIAN); |
+ return buffer; |
+ } |
+ |
+ /* |
+ * (non-Javadoc) |
+ * @see org.chromium.mojo.system.Core#waitMany(...) |
+ */ |
+ @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(4 * index, realHandler.getMojoHandle()); |
+ buffer.putInt(4 * handles.size() + 4 * 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.handleIndex = code; |
+ result.mojoResult = waitMojoResultToBoolean(code); |
+ return result; |
+ } |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @param handle |
+ * @param flags |
+ * @param deadline |
+ * @return TODO(qsr) |
+ */ |
+ @Override |
+ public MojoResult wait(Handle handle, WaitFlags flags, long deadline) { |
+ return waitMojoResultToBoolean(nativeWait(((HandleImpl) handle).getMojoHandle(), |
+ flags.getFlags(), deadline)); |
+ } |
+ |
+ /* |
+ * (non-Javadoc) |
+ * @see org.chromium.mojo.system.Core#createMessagePipe() |
+ */ |
+ @Override |
+ public Pair<MessagePipeHandle, MessagePipeHandle> createMessagePipe() { |
+ NativeCreationResult result = nativeCreateMessagePipe(); |
+ if (result.mojoResult != MojoResult.OK) { |
+ throw new MojoException(result.mojoResult); |
+ } |
+ return Pair.create( |
+ new MessagePipeHandleImpl(this, result.mojoHandle1), |
+ new MessagePipeHandleImpl(this, result.mojoHandle2)); |
+ } |
+ |
+ /* |
+ * (non-Javadoc) |
+ * @see org.chromium.mojo.system.Core#createMessagePipe(...) |
+ */ |
+ @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.flags.getFlags()); |
+ optionsBuffer.putInt(8, options.elementNumBytes); |
+ optionsBuffer.putInt(12, options.capacityNumBytes); |
+ } |
+ NativeCreationResult result = nativeCreateDataPipe(optionsBuffer); |
+ if (result.mojoResult != MojoResult.OK) { |
+ throw new MojoException(result.mojoResult); |
+ } |
+ return Pair.create( |
+ new DataPipeProducerHandleImpl(this, result.mojoHandle1), |
+ new DataPipeConsumerHandleImpl(this, result.mojoHandle2)); |
+ } |
+ |
+ /* |
+ * (non-Javadoc) |
+ * @see org.chromium.mojo.system.Core#createSharedBuffer(...) |
+ */ |
+ @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.flags.getFlags()); |
+ } |
+ NativeCreationResult result = nativeCreateSharedBuffer(optionsBuffer, numBytes); |
+ if (result.mojoResult != MojoResult.OK) { |
+ throw new MojoException(result.mojoResult); |
+ } |
+ assert result.mojoHandle2 == 0; |
+ return new SharedBufferHandleImpl(this, result.mojoHandle1); |
+ } |
+ |
+ int closeWithResult(int mojoHandle) { |
+ return nativeClose(mojoHandle); |
+ } |
+ |
+ void close(int mojoHandle) { |
+ MojoResult mojoResult = MojoResult.forCode(nativeClose(mojoHandle)); |
+ if (mojoResult != MojoResult.OK) { |
+ throw new MojoException(mojoResult); |
+ } |
+ } |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @param pipeHandle |
+ * @param bytes |
+ * @param handles |
+ * @param flags |
+ */ |
+ void writeMessage(MessagePipeHandleImpl pipeHandle, ByteBuffer bytes, |
+ List<Handle> handles, MessagePipeHandle.WriteFlags flags) { |
+ ByteBuffer handlesBuffer = null; |
+ if (handles != null && !handles.isEmpty()) { |
+ handlesBuffer = allocateDirectBuffer(handles.size() * 4); |
+ for (Handle handle : handles) { |
+ HandleImpl realHandle = (HandleImpl) handle; |
+ handlesBuffer.putInt(realHandle.getMojoHandle()); |
+ } |
+ handlesBuffer.position(0); |
+ } |
+ MojoResult mojoResult = MojoResult.forCode( |
+ 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(); |
+ } |
+ } |
+ } |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @param handle |
+ * @param bytes |
+ * @param maxNumberOfHandles |
+ * @param flags |
+ * @return TODO(qsr) |
+ */ |
+ MessagePipeHandle.ReadMessageResult readMessage(MessagePipeHandleImpl handle, |
+ ByteBuffer bytes, int maxNumberOfHandles, |
+ MessagePipeHandle.ReadFlags flags) { |
+ ByteBuffer handlesBuffer = null; |
+ if (maxNumberOfHandles > 0) { |
+ handlesBuffer = allocateDirectBuffer(maxNumberOfHandles * 4); |
+ } |
+ NativeReadMessageResult result = nativeReadMessage( |
+ handle.getMojoHandle(), bytes, handlesBuffer, flags.getFlags()); |
+ if (result.mojoResult != MojoResult.OK && |
+ result.mojoResult != MojoResult.RESOURCE_EXHAUSTED) { |
+ throw new MojoException(result.mojoResult); |
+ } |
+ |
+ if (result.mojoResult == MojoResult.OK) { |
+ if (bytes != null) { |
+ bytes.position(0); |
+ bytes.limit(result.readMessageResult.messageSize); |
+ } |
+ |
+ List<UntypedHandle> handles = new ArrayList<UntypedHandle>( |
+ result.readMessageResult.handlesCount); |
+ for (int i = 0; i < result.readMessageResult.handlesCount; ++i) { |
+ int mojoHandle = handlesBuffer.getInt(4 * i); |
+ handles.add(new UntypedHandleImpl(this, mojoHandle)); |
+ } |
+ result.readMessageResult.handles = handles; |
+ } |
+ return result.readMessageResult; |
+ } |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @param handle |
+ * @param elements |
+ * @param flags |
+ * @return TODO(qsr) |
+ */ |
+ int readData(DataPipeConsumerHandleImpl handle, ByteBuffer elements, |
+ ReadFlags flags) { |
+ int result = nativeReadData(handle.getMojoHandle(), elements, |
+ flags.getFlags()); |
+ if (result < 0) { |
+ throw new MojoException(MojoResult.forCode(result)); |
+ } |
+ return result; |
+ } |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @param handle |
+ * @param numBytes |
+ * @param flags |
+ * @return TODO(qsr) |
+ */ |
+ ByteBuffer beingReadData(DataPipeConsumerHandleImpl handle, |
+ int numBytes, ReadFlags flags) { |
+ NativeCodeAndBufferResult result = nativeBeginReadData( |
+ handle.getMojoHandle(), |
+ numBytes, |
+ flags.getFlags()); |
+ if (result.mojoResult != MojoResult.OK) { |
+ throw new MojoException(result.mojoResult); |
+ } |
+ return result.buffer.asReadOnlyBuffer(); |
+ } |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @param handle |
+ * @param numBytesRead |
+ */ |
+ void endReadData(DataPipeConsumerHandleImpl handle, |
+ int numBytesRead) { |
+ MojoResult result = MojoResult.forCode( |
+ nativeEndReadData(handle.getMojoHandle(), numBytesRead)); |
+ if (result != MojoResult.OK) { |
+ throw new MojoException(result); |
+ } |
+ } |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @param handle |
+ * @param flags |
+ * @return TODO(qsr) |
+ */ |
+ int writeData(DataPipeProducerHandleImpl handle, ByteBuffer elements, WriteFlags flags) { |
+ return nativeWriteData(handle.getMojoHandle(), elements, elements.limit(), |
+ flags.getFlags()); |
+ } |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @param handle |
+ * @param numBytes |
+ * @param flags |
+ * @return TODO(qsr) |
+ */ |
+ ByteBuffer beingWriteData(DataPipeProducerHandleImpl handle, |
+ int numBytes, WriteFlags flags) { |
+ NativeCodeAndBufferResult result = nativeBeginWriteData( |
+ handle.getMojoHandle(), |
+ numBytes, |
+ flags.getFlags()); |
+ if (result.mojoResult != MojoResult.OK) { |
+ throw new MojoException(result.mojoResult); |
+ } |
+ return result.buffer; |
+ } |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @param handle |
+ * @param numBytesWritten |
+ */ |
+ void endWriteData(DataPipeProducerHandleImpl handle, |
+ int numBytesWritten) { |
+ MojoResult result = MojoResult.forCode( |
+ nativeEndWriteData(handle.getMojoHandle(), numBytesWritten)); |
+ if (result != MojoResult.OK) { |
+ throw new MojoException(result); |
+ } |
+ } |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @param handle |
+ * @param options |
+ * @return TODO(qsr) |
+ */ |
+ SharedBufferHandle duplicate(SharedBufferHandleImpl handle, |
+ DuplicateOptions options) { |
+ ByteBuffer optionsBuffer = null; |
+ if (options != null) { |
+ optionsBuffer = allocateDirectBuffer(8); |
+ optionsBuffer.putInt(0, 8); |
+ optionsBuffer.putInt(4, options.flags.getFlags()); |
+ } |
+ NativeCreationResult result = nativeDuplicate(handle.getMojoHandle(), |
+ optionsBuffer); |
+ if (result.mojoResult != MojoResult.OK) { |
+ throw new MojoException(result.mojoResult); |
+ } |
+ assert result.mojoHandle2 == 0; |
+ return new SharedBufferHandleImpl(this, result.mojoHandle1); |
+ } |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @param handle |
+ * @param offset |
+ * @param numBytes |
+ * @param flags |
+ * @return TODO(qsr) |
+ */ |
+ ByteBuffer map(SharedBufferHandleImpl handle, long offset, long numBytes, |
+ MapFlags flags) { |
+ NativeCodeAndBufferResult result = nativeMap(handle.getMojoHandle(), offset, numBytes, |
+ flags.getFlags()); |
+ if (result.mojoResult != MojoResult.OK) { |
+ throw new MojoException(result.mojoResult); |
+ } |
+ return result.buffer; |
+ } |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @param handle |
+ * @param buffer |
+ */ |
+ void unmap(SharedBufferHandleImpl handle, ByteBuffer buffer) { |
+ MojoResult result = MojoResult.forCode(nativeUnmap(buffer)); |
+ if (result != MojoResult.OK) { |
+ throw new MojoException(result); |
+ } |
+ } |
+ |
+ private native void nativeConstructor(); |
+ |
+ private native long nativeGetTimeTicksNow(); |
+ |
+ private native int nativeWaitMany(ByteBuffer buffer, long deadline); |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @return TODO(qsr) |
+ */ |
+ private native NativeCreationResult nativeCreateMessagePipe(); |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @param optionsBuffer |
+ * @return TODO(qsr) |
+ */ |
+ private native NativeCreationResult nativeCreateDataPipe( |
+ ByteBuffer optionsBuffer); |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @param optionsBuffer |
+ * @param numBytes |
+ * @return TODO(qsr) |
+ */ |
+ private native NativeCreationResult nativeCreateSharedBuffer(ByteBuffer optionsBuffer, |
+ long numBytes); |
+ |
+ private native int nativeClose(int mojoHandle); |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @param mojoHandle |
+ * @param flags |
+ * @param deadline |
+ */ |
+ private native int nativeWait(int mojoHandle, int flags, long deadline); |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @param mojoHandle |
+ * @param bytes |
+ * @param handlesBuffer |
+ * @param flags |
+ */ |
+ private native int nativeWriteMessage(int mojoHandle, ByteBuffer bytes, int numBytes, |
+ ByteBuffer handlesBuffer, int flags); |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @param mojoHandle |
+ * @param bytes |
+ * @param handlesBuffer |
+ * @param flags |
+ * @return TODO(qsr) |
+ */ |
+ private native NativeReadMessageResult nativeReadMessage(int mojoHandle, ByteBuffer bytes, |
+ ByteBuffer handlesBuffer, |
+ int flags); |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @param mojoHandle |
+ * @param elements |
+ * @param flags |
+ * @return TODO(qsr) |
+ */ |
+ private native int nativeReadData(int mojoHandle, ByteBuffer elements, int flags); |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @param mojoHandle |
+ * @param flags |
+ * @return TODO(qsr) |
+ */ |
+ private native NativeCodeAndBufferResult nativeBeginReadData(int mojoHandle, int numBytes, |
+ int flags); |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @param mojoHandle |
+ * @param numBytesRead |
+ * @return TODO(qsr) |
+ */ |
+ private native int nativeEndReadData(int mojoHandle, int numBytesRead); |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @param mojoHandle |
+ * @param elements |
+ * @param limit |
+ * @param flags |
+ * @return TODO(qsr) |
+ */ |
+ private native int nativeWriteData(int mojoHandle, ByteBuffer elements, int limit, int flags); |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @param mojoHandle |
+ * @param numBytes |
+ * @param flags |
+ * @return TODO(qsr) |
+ */ |
+ private native NativeCodeAndBufferResult nativeBeginWriteData(int mojoHandle, int numBytes, |
+ int flags); |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @param mojoHandle |
+ * @param numBytesWritten |
+ * @return TODO(qsr) |
+ */ |
+ private native int nativeEndWriteData(int mojoHandle, int numBytesWritten); |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @param mojoHandle |
+ * @param optionsBuffer |
+ * @return TODO(qsr) |
+ */ |
+ private native NativeCreationResult nativeDuplicate(int mojoHandle, ByteBuffer optionsBuffer); |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @param mojoHandle |
+ * @param offset |
+ * @param numBytes |
+ * @param flags |
+ * @return TODO(qsr) |
+ */ |
+ private native NativeCodeAndBufferResult nativeMap(int mojoHandle, long offset, long numBytes, |
+ int flags); |
+ |
+ /** |
+ * TODO(qsr): |
+ * |
+ * @param buffer |
+ */ |
+ private native int nativeUnmap(ByteBuffer buffer); |
+ |
+ private static class NativeCodeAndBufferResult { |
bulach
2014/04/14 17:39:56
nit: from here until 617, please move before the "
qsr
2014/04/15 08:37:37
Done.
|
+ public MojoResult mojoResult; |
+ public ByteBuffer buffer; |
+ } |
+ |
+ @CalledByNative |
+ private static NativeCodeAndBufferResult newNativeCodeAndBufferResult(int mojoResult, |
+ ByteBuffer buffer) { |
+ NativeCodeAndBufferResult result = new NativeCodeAndBufferResult(); |
+ result.mojoResult = MojoResult.forCode(mojoResult); |
+ result.buffer = buffer; |
+ return result; |
+ } |
+ |
+ private static class NativeReadMessageResult { |
+ public MojoResult mojoResult; |
+ public MessagePipeHandle.ReadMessageResult readMessageResult; |
+ } |
+ |
+ @CalledByNative |
+ private static NativeReadMessageResult newNativeReadMessageResult(int mojoResult, |
+ int messageSize, |
+ int handlesCount) { |
+ NativeReadMessageResult result = new NativeReadMessageResult(); |
+ result.mojoResult = MojoResult.forCode(mojoResult); |
+ MessagePipeHandle.ReadMessageResult readMessageResult = |
+ new MessagePipeHandle.ReadMessageResult(); |
+ readMessageResult.wasMessageRead = (result.mojoResult == MojoResult.OK); |
+ readMessageResult.messageSize = messageSize; |
+ readMessageResult.handlesCount = handlesCount; |
+ result.readMessageResult = readMessageResult; |
+ return result; |
+ } |
+ |
+ private static class NativeCreationResult { |
+ public MojoResult mojoResult; |
+ public int mojoHandle1; |
+ public int mojoHandle2; |
+ } |
+ |
+ @CalledByNative |
+ private static NativeCreationResult newNativeCreationResult(int mojoResult, |
+ int mojoHandle1, int mojoHandle2) { |
+ NativeCreationResult result = new NativeCreationResult(); |
+ result.mojoResult = MojoResult.forCode(mojoResult); |
+ result.mojoHandle1 = mojoHandle1; |
+ result.mojoHandle2 = mojoHandle2; |
+ return result; |
+ } |
+ |
+} |