diff options
Diffstat (limited to 'mojo/android/system/src/org/chromium')
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); +} |