diff options
author | qsr@chromium.org <qsr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-23 16:02:32 +0000 |
---|---|---|
committer | qsr@chromium.org <qsr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-23 16:02:32 +0000 |
commit | 70c0364a44341bf10c5157c11d3689a3cf7c6054 (patch) | |
tree | 201dff677afe4bb771b89f370a4c93ee5e276305 /mojo/android/system | |
parent | 76b34ffc13b9d895f60e20a752f5d09317d00db0 (diff) | |
download | chromium_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/system')
10 files changed, 1298 insertions, 0 deletions
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); + } + +} |