Home | History | Annotate | Download | only in impl
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 package org.chromium.mojo.system.impl;
      6 
      7 import org.chromium.base.annotations.CalledByNative;
      8 import org.chromium.base.annotations.JNINamespace;
      9 import org.chromium.base.annotations.MainDex;
     10 import org.chromium.mojo.system.AsyncWaiter;
     11 import org.chromium.mojo.system.Core;
     12 import org.chromium.mojo.system.DataPipe;
     13 import org.chromium.mojo.system.DataPipe.ConsumerHandle;
     14 import org.chromium.mojo.system.DataPipe.ProducerHandle;
     15 import org.chromium.mojo.system.Handle;
     16 import org.chromium.mojo.system.MessagePipeHandle;
     17 import org.chromium.mojo.system.MojoException;
     18 import org.chromium.mojo.system.MojoResult;
     19 import org.chromium.mojo.system.Pair;
     20 import org.chromium.mojo.system.ResultAnd;
     21 import org.chromium.mojo.system.RunLoop;
     22 import org.chromium.mojo.system.SharedBufferHandle;
     23 import org.chromium.mojo.system.SharedBufferHandle.DuplicateOptions;
     24 import org.chromium.mojo.system.SharedBufferHandle.MapFlags;
     25 import org.chromium.mojo.system.UntypedHandle;
     26 
     27 import java.nio.ByteBuffer;
     28 import java.nio.ByteOrder;
     29 import java.util.ArrayList;
     30 import java.util.Arrays;
     31 import java.util.List;
     32 
     33 /**
     34  * Implementation of {@link Core}.
     35  */
     36 @JNINamespace("mojo::android")
     37 @MainDex
     38 public class CoreImpl implements Core, AsyncWaiter {
     39     /**
     40      * Discard flag for the |MojoReadData| operation.
     41      */
     42     private static final int MOJO_READ_DATA_FLAG_DISCARD = 1 << 1;
     43 
     44     /**
     45      * the size of a handle, in bytes.
     46      */
     47     private static final int HANDLE_SIZE = 4;
     48 
     49     /**
     50      * the size of a flag, in bytes.
     51      */
     52     private static final int FLAG_SIZE = 4;
     53 
     54     /**
     55      * The mojo handle for an invalid handle.
     56      */
     57     static final int INVALID_HANDLE = 0;
     58 
     59     private static class LazyHolder { private static final Core INSTANCE = new CoreImpl(); }
     60 
     61     /**
     62      * The run loop for the current thread.
     63      */
     64     private final ThreadLocal<BaseRunLoop> mCurrentRunLoop = new ThreadLocal<BaseRunLoop>();
     65 
     66     /**
     67      * The offset needed to get an aligned buffer.
     68      */
     69     private final int mByteBufferOffset;
     70 
     71     /**
     72      * @return the instance.
     73      */
     74     public static Core getInstance() {
     75         return LazyHolder.INSTANCE;
     76     }
     77 
     78     private CoreImpl() {
     79         // Fix for the ART runtime, before:
     80         // https://android.googlesource.com/platform/libcore/+/fb6c80875a8a8d0a9628562f89c250b6a962e824%5E!/
     81         // This assumes consistent allocation.
     82         mByteBufferOffset = nativeGetNativeBufferOffset(ByteBuffer.allocateDirect(8), 8);
     83     }
     84 
     85     /**
     86      * @see Core#getTimeTicksNow()
     87      */
     88     @Override
     89     public long getTimeTicksNow() {
     90         return nativeGetTimeTicksNow();
     91     }
     92 
     93     /**
     94      * @see Core#waitMany(List, long)
     95      */
     96     @Override
     97     public WaitManyResult waitMany(List<Pair<Handle, HandleSignals>> handles, long deadline) {
     98         // Allocate a direct buffer to allow native code not to reach back to java. The buffer
     99         // layout will be:
    100         // input: The array of handles (int, 4 bytes each)
    101         // input: The array of signals (int, 4 bytes each)
    102         // space for output: The array of handle states (2 ints, 8 bytes each)
    103         // Space for output: The result index (int, 4 bytes)
    104         // The handles and signals will be filled before calling the native method. When the native
    105         // method returns, the handle states and the index will have been set.
    106         ByteBuffer buffer = allocateDirectBuffer(handles.size() * 16 + 4);
    107         int index = 0;
    108         for (Pair<Handle, HandleSignals> handle : handles) {
    109             buffer.putInt(HANDLE_SIZE * index, getMojoHandle(handle.first));
    110             buffer.putInt(
    111                     HANDLE_SIZE * handles.size() + FLAG_SIZE * index, handle.second.getFlags());
    112             index++;
    113         }
    114         int code = nativeWaitMany(buffer, deadline);
    115         WaitManyResult result = new WaitManyResult();
    116         result.setMojoResult(filterMojoResultForWait(code));
    117         result.setHandleIndex(buffer.getInt(handles.size() * 16));
    118         if (result.getMojoResult() != MojoResult.INVALID_ARGUMENT
    119                 && result.getMojoResult() != MojoResult.RESOURCE_EXHAUSTED) {
    120             HandleSignalsState[] states = new HandleSignalsState[handles.size()];
    121             for (int i = 0; i < handles.size(); ++i) {
    122                 states[i] = new HandleSignalsState(
    123                         new HandleSignals(buffer.getInt(8 * (handles.size() + i))),
    124                         new HandleSignals(buffer.getInt(8 * (handles.size() + i) + 4)));
    125             }
    126             result.setSignalStates(Arrays.asList(states));
    127         }
    128         return result;
    129     }
    130 
    131     /**
    132      * @see Core#wait(Handle, HandleSignals, long)
    133      */
    134     @Override
    135     public WaitResult wait(Handle handle, HandleSignals signals, long deadline) {
    136         // Allocate a direct buffer to allow native code not to reach back to java. Buffer will
    137         // contain spaces to write the handle state.
    138         ByteBuffer buffer = allocateDirectBuffer(8);
    139         WaitResult result = new WaitResult();
    140         result.setMojoResult(filterMojoResultForWait(
    141                 nativeWait(buffer, getMojoHandle(handle), signals.getFlags(), deadline)));
    142         HandleSignalsState signalsState = new HandleSignalsState(
    143                 new HandleSignals(buffer.getInt(0)), new HandleSignals(buffer.getInt(4)));
    144         result.setHandleSignalsState(signalsState);
    145         return result;
    146     }
    147 
    148     /**
    149      * @see Core#createMessagePipe(MessagePipeHandle.CreateOptions)
    150      */
    151     @Override
    152     public Pair<MessagePipeHandle, MessagePipeHandle> createMessagePipe(
    153             MessagePipeHandle.CreateOptions options) {
    154         ByteBuffer optionsBuffer = null;
    155         if (options != null) {
    156             optionsBuffer = allocateDirectBuffer(8);
    157             optionsBuffer.putInt(0, 8);
    158             optionsBuffer.putInt(4, options.getFlags().getFlags());
    159         }
    160         ResultAnd<IntegerPair> result = nativeCreateMessagePipe(optionsBuffer);
    161         if (result.getMojoResult() != MojoResult.OK) {
    162             throw new MojoException(result.getMojoResult());
    163         }
    164         return Pair.<MessagePipeHandle, MessagePipeHandle>create(
    165                 new MessagePipeHandleImpl(this, result.getValue().first),
    166                 new MessagePipeHandleImpl(this, result.getValue().second));
    167     }
    168 
    169     /**
    170      * @see Core#createDataPipe(DataPipe.CreateOptions)
    171      */
    172     @Override
    173     public Pair<ProducerHandle, ConsumerHandle> createDataPipe(DataPipe.CreateOptions options) {
    174         ByteBuffer optionsBuffer = null;
    175         if (options != null) {
    176             optionsBuffer = allocateDirectBuffer(16);
    177             optionsBuffer.putInt(0, 16);
    178             optionsBuffer.putInt(4, options.getFlags().getFlags());
    179             optionsBuffer.putInt(8, options.getElementNumBytes());
    180             optionsBuffer.putInt(12, options.getCapacityNumBytes());
    181         }
    182         ResultAnd<IntegerPair> result = nativeCreateDataPipe(optionsBuffer);
    183         if (result.getMojoResult() != MojoResult.OK) {
    184             throw new MojoException(result.getMojoResult());
    185         }
    186         return Pair.<ProducerHandle, ConsumerHandle>create(
    187                 new DataPipeProducerHandleImpl(this, result.getValue().first),
    188                 new DataPipeConsumerHandleImpl(this, result.getValue().second));
    189     }
    190 
    191     /**
    192      * @see Core#createSharedBuffer(SharedBufferHandle.CreateOptions, long)
    193      */
    194     @Override
    195     public SharedBufferHandle createSharedBuffer(
    196             SharedBufferHandle.CreateOptions options, long numBytes) {
    197         ByteBuffer optionsBuffer = null;
    198         if (options != null) {
    199             optionsBuffer = allocateDirectBuffer(8);
    200             optionsBuffer.putInt(0, 8);
    201             optionsBuffer.putInt(4, options.getFlags().getFlags());
    202         }
    203         ResultAnd<Integer> result = nativeCreateSharedBuffer(optionsBuffer, numBytes);
    204         if (result.getMojoResult() != MojoResult.OK) {
    205             throw new MojoException(result.getMojoResult());
    206         }
    207         return new SharedBufferHandleImpl(this, result.getValue());
    208     }
    209 
    210     /**
    211      * @see org.chromium.mojo.system.Core#acquireNativeHandle(int)
    212      */
    213     @Override
    214     public UntypedHandle acquireNativeHandle(int handle) {
    215         return new UntypedHandleImpl(this, handle);
    216     }
    217 
    218     /**
    219      * @see Core#getDefaultAsyncWaiter()
    220      */
    221     @Override
    222     public AsyncWaiter getDefaultAsyncWaiter() {
    223         return this;
    224     }
    225 
    226     /**
    227      * @see Core#createDefaultRunLoop()
    228      */
    229     @Override
    230     public RunLoop createDefaultRunLoop() {
    231         if (mCurrentRunLoop.get() != null) {
    232             throw new MojoException(MojoResult.FAILED_PRECONDITION);
    233         }
    234         BaseRunLoop runLoop = new BaseRunLoop(this);
    235         mCurrentRunLoop.set(runLoop);
    236         return runLoop;
    237     }
    238 
    239     /**
    240      * @see Core#getCurrentRunLoop()
    241      */
    242     @Override
    243     public RunLoop getCurrentRunLoop() {
    244         return mCurrentRunLoop.get();
    245     }
    246 
    247     /**
    248      * Remove the current run loop.
    249      */
    250     void clearCurrentRunLoop() {
    251         mCurrentRunLoop.remove();
    252     }
    253 
    254     /**
    255      * @see AsyncWaiter#asyncWait(Handle, Core.HandleSignals, long, Callback)
    256      */
    257     @Override
    258     public Cancellable asyncWait(
    259             Handle handle, HandleSignals signals, long deadline, Callback callback) {
    260         return nativeAsyncWait(getMojoHandle(handle), signals.getFlags(), deadline, callback);
    261     }
    262 
    263     int closeWithResult(int mojoHandle) {
    264         return nativeClose(mojoHandle);
    265     }
    266 
    267     void close(int mojoHandle) {
    268         int mojoResult = nativeClose(mojoHandle);
    269         if (mojoResult != MojoResult.OK) {
    270             throw new MojoException(mojoResult);
    271         }
    272     }
    273 
    274     /**
    275      * @see MessagePipeHandle#writeMessage(ByteBuffer, List, MessagePipeHandle.WriteFlags)
    276      */
    277     void writeMessage(MessagePipeHandleImpl pipeHandle, ByteBuffer bytes,
    278             List<? extends Handle> handles, MessagePipeHandle.WriteFlags flags) {
    279         ByteBuffer handlesBuffer = null;
    280         if (handles != null && !handles.isEmpty()) {
    281             handlesBuffer = allocateDirectBuffer(handles.size() * HANDLE_SIZE);
    282             for (Handle handle : handles) {
    283                 handlesBuffer.putInt(getMojoHandle(handle));
    284             }
    285             handlesBuffer.position(0);
    286         }
    287         int mojoResult = nativeWriteMessage(pipeHandle.getMojoHandle(), bytes,
    288                 bytes == null ? 0 : bytes.limit(), handlesBuffer, flags.getFlags());
    289         if (mojoResult != MojoResult.OK) {
    290             throw new MojoException(mojoResult);
    291         }
    292         // Success means the handles have been invalidated.
    293         if (handles != null) {
    294             for (Handle handle : handles) {
    295                 if (handle.isValid()) {
    296                     ((HandleBase) handle).invalidateHandle();
    297                 }
    298             }
    299         }
    300     }
    301 
    302     /**
    303      * @see MessagePipeHandle#readMessage(ByteBuffer, int, MessagePipeHandle.ReadFlags)
    304      */
    305     ResultAnd<MessagePipeHandle.ReadMessageResult> readMessage(MessagePipeHandleImpl handle,
    306             ByteBuffer bytes, int maxNumberOfHandles, MessagePipeHandle.ReadFlags flags) {
    307         ByteBuffer handlesBuffer = null;
    308         if (maxNumberOfHandles > 0) {
    309             handlesBuffer = allocateDirectBuffer(maxNumberOfHandles * HANDLE_SIZE);
    310         }
    311         ResultAnd<MessagePipeHandle.ReadMessageResult> result =
    312                 nativeReadMessage(handle.getMojoHandle(), bytes, handlesBuffer, flags.getFlags());
    313         if (result.getMojoResult() != MojoResult.OK
    314                 && result.getMojoResult() != MojoResult.RESOURCE_EXHAUSTED
    315                 && result.getMojoResult() != MojoResult.SHOULD_WAIT) {
    316             throw new MojoException(result.getMojoResult());
    317         }
    318 
    319         if (result.getMojoResult() == MojoResult.OK) {
    320             MessagePipeHandle.ReadMessageResult readResult = result.getValue();
    321             if (bytes != null) {
    322                 bytes.position(0);
    323                 bytes.limit(readResult.getMessageSize());
    324             }
    325 
    326             List<UntypedHandle> handles =
    327                     new ArrayList<UntypedHandle>(readResult.getHandlesCount());
    328             for (int i = 0; i < readResult.getHandlesCount(); ++i) {
    329                 int mojoHandle = handlesBuffer.getInt(HANDLE_SIZE * i);
    330                 handles.add(new UntypedHandleImpl(this, mojoHandle));
    331             }
    332             readResult.setHandles(handles);
    333         }
    334         return result;
    335     }
    336 
    337     /**
    338      * @see ConsumerHandle#discardData(int, DataPipe.ReadFlags)
    339      */
    340     int discardData(DataPipeConsumerHandleImpl handle, int numBytes, DataPipe.ReadFlags flags) {
    341         ResultAnd<Integer> result = nativeReadData(handle.getMojoHandle(), null, numBytes,
    342                 flags.getFlags() | MOJO_READ_DATA_FLAG_DISCARD);
    343         if (result.getMojoResult() != MojoResult.OK) {
    344             throw new MojoException(result.getMojoResult());
    345         }
    346         return result.getValue();
    347     }
    348 
    349     /**
    350      * @see ConsumerHandle#readData(ByteBuffer, DataPipe.ReadFlags)
    351      */
    352     ResultAnd<Integer> readData(
    353             DataPipeConsumerHandleImpl handle, ByteBuffer elements, DataPipe.ReadFlags flags) {
    354         ResultAnd<Integer> result = nativeReadData(handle.getMojoHandle(), elements,
    355                 elements == null ? 0 : elements.capacity(), flags.getFlags());
    356         if (result.getMojoResult() != MojoResult.OK
    357                 && result.getMojoResult() != MojoResult.SHOULD_WAIT) {
    358             throw new MojoException(result.getMojoResult());
    359         }
    360         if (result.getMojoResult() == MojoResult.OK) {
    361             if (elements != null) {
    362                 elements.limit(result.getValue());
    363             }
    364         }
    365         return result;
    366     }
    367 
    368     /**
    369      * @see ConsumerHandle#beginReadData(int, DataPipe.ReadFlags)
    370      */
    371     ByteBuffer beginReadData(
    372             DataPipeConsumerHandleImpl handle, int numBytes, DataPipe.ReadFlags flags) {
    373         ResultAnd<ByteBuffer> result =
    374                 nativeBeginReadData(handle.getMojoHandle(), numBytes, flags.getFlags());
    375         if (result.getMojoResult() != MojoResult.OK) {
    376             throw new MojoException(result.getMojoResult());
    377         }
    378         return result.getValue().asReadOnlyBuffer();
    379     }
    380 
    381     /**
    382      * @see ConsumerHandle#endReadData(int)
    383      */
    384     void endReadData(DataPipeConsumerHandleImpl handle, int numBytesRead) {
    385         int result = nativeEndReadData(handle.getMojoHandle(), numBytesRead);
    386         if (result != MojoResult.OK) {
    387             throw new MojoException(result);
    388         }
    389     }
    390 
    391     /**
    392      * @see ProducerHandle#writeData(ByteBuffer, DataPipe.WriteFlags)
    393      */
    394     ResultAnd<Integer> writeData(
    395             DataPipeProducerHandleImpl handle, ByteBuffer elements, DataPipe.WriteFlags flags) {
    396         return nativeWriteData(
    397                 handle.getMojoHandle(), elements, elements.limit(), flags.getFlags());
    398     }
    399 
    400     /**
    401      * @see ProducerHandle#beginWriteData(int, DataPipe.WriteFlags)
    402      */
    403     ByteBuffer beginWriteData(
    404             DataPipeProducerHandleImpl handle, int numBytes, DataPipe.WriteFlags flags) {
    405         ResultAnd<ByteBuffer> result =
    406                 nativeBeginWriteData(handle.getMojoHandle(), numBytes, flags.getFlags());
    407         if (result.getMojoResult() != MojoResult.OK) {
    408             throw new MojoException(result.getMojoResult());
    409         }
    410         return result.getValue();
    411     }
    412 
    413     /**
    414      * @see ProducerHandle#endWriteData(int)
    415      */
    416     void endWriteData(DataPipeProducerHandleImpl handle, int numBytesWritten) {
    417         int result = nativeEndWriteData(handle.getMojoHandle(), numBytesWritten);
    418         if (result != MojoResult.OK) {
    419             throw new MojoException(result);
    420         }
    421     }
    422 
    423     /**
    424      * @see SharedBufferHandle#duplicate(DuplicateOptions)
    425      */
    426     SharedBufferHandle duplicate(SharedBufferHandleImpl handle, DuplicateOptions options) {
    427         ByteBuffer optionsBuffer = null;
    428         if (options != null) {
    429             optionsBuffer = allocateDirectBuffer(8);
    430             optionsBuffer.putInt(0, 8);
    431             optionsBuffer.putInt(4, options.getFlags().getFlags());
    432         }
    433         ResultAnd<Integer> result = nativeDuplicate(handle.getMojoHandle(), optionsBuffer);
    434         if (result.getMojoResult() != MojoResult.OK) {
    435             throw new MojoException(result.getMojoResult());
    436         }
    437         return new SharedBufferHandleImpl(this, result.getValue());
    438     }
    439 
    440     /**
    441      * @see SharedBufferHandle#map(long, long, MapFlags)
    442      */
    443     ByteBuffer map(SharedBufferHandleImpl handle, long offset, long numBytes, MapFlags flags) {
    444         ResultAnd<ByteBuffer> result =
    445                 nativeMap(handle.getMojoHandle(), offset, numBytes, flags.getFlags());
    446         if (result.getMojoResult() != MojoResult.OK) {
    447             throw new MojoException(result.getMojoResult());
    448         }
    449         return result.getValue();
    450     }
    451 
    452     /**
    453      * @see SharedBufferHandle#unmap(ByteBuffer)
    454      */
    455     void unmap(ByteBuffer buffer) {
    456         int result = nativeUnmap(buffer);
    457         if (result != MojoResult.OK) {
    458             throw new MojoException(result);
    459         }
    460     }
    461 
    462     /**
    463      * @return the mojo handle associated to the given handle, considering invalid handles.
    464      */
    465     private int getMojoHandle(Handle handle) {
    466         if (handle.isValid()) {
    467             return ((HandleBase) handle).getMojoHandle();
    468         }
    469         return 0;
    470     }
    471 
    472     private static boolean isUnrecoverableError(int code) {
    473         switch (code) {
    474             case MojoResult.OK:
    475             case MojoResult.DEADLINE_EXCEEDED:
    476             case MojoResult.CANCELLED:
    477             case MojoResult.FAILED_PRECONDITION:
    478                 return false;
    479             default:
    480                 return true;
    481         }
    482     }
    483 
    484     private static int filterMojoResultForWait(int code) {
    485         if (isUnrecoverableError(code)) {
    486             throw new MojoException(code);
    487         }
    488         return code;
    489     }
    490 
    491     private ByteBuffer allocateDirectBuffer(int capacity) {
    492         ByteBuffer buffer = ByteBuffer.allocateDirect(capacity + mByteBufferOffset);
    493         if (mByteBufferOffset != 0) {
    494             buffer.position(mByteBufferOffset);
    495             buffer = buffer.slice();
    496         }
    497         return buffer.order(ByteOrder.nativeOrder());
    498     }
    499 
    500     /**
    501      * Implementation of {@link org.chromium.mojo.system.AsyncWaiter.Cancellable}.
    502      */
    503     private class AsyncWaiterCancellableImpl implements AsyncWaiter.Cancellable {
    504         private final long mId;
    505         private final long mDataPtr;
    506         private boolean mActive = true;
    507 
    508         private AsyncWaiterCancellableImpl(long id, long dataPtr) {
    509             this.mId = id;
    510             this.mDataPtr = dataPtr;
    511         }
    512 
    513         /**
    514          * @see org.chromium.mojo.system.AsyncWaiter.Cancellable#cancel()
    515          */
    516         @Override
    517         public void cancel() {
    518             if (mActive) {
    519                 mActive = false;
    520                 nativeCancelAsyncWait(mId, mDataPtr);
    521             }
    522         }
    523 
    524         private boolean isActive() {
    525             return mActive;
    526         }
    527 
    528         private void deactivate() {
    529             mActive = false;
    530         }
    531     }
    532 
    533     @CalledByNative
    534     private AsyncWaiterCancellableImpl newAsyncWaiterCancellableImpl(long id, long dataPtr) {
    535         return new AsyncWaiterCancellableImpl(id, dataPtr);
    536     }
    537 
    538     @CalledByNative
    539     private void onAsyncWaitResult(
    540             int mojoResult, AsyncWaiter.Callback callback, AsyncWaiterCancellableImpl cancellable) {
    541         if (!cancellable.isActive()) {
    542             // If cancellable is not active, the user cancelled the wait.
    543             return;
    544         }
    545         cancellable.deactivate();
    546         if (isUnrecoverableError(mojoResult)) {
    547             callback.onError(new MojoException(mojoResult));
    548             return;
    549         }
    550         callback.onResult(mojoResult);
    551     }
    552 
    553     @CalledByNative
    554     private static ResultAnd<ByteBuffer> newResultAndBuffer(int mojoResult, ByteBuffer buffer) {
    555         return new ResultAnd<>(mojoResult, buffer);
    556     }
    557 
    558     /**
    559      * Trivial alias for Pair<Integer, Integer>. This is needed because our jni generator is unable
    560      * to handle class that contains space.
    561      */
    562     private static final class IntegerPair extends Pair<Integer, Integer> {
    563         public IntegerPair(Integer first, Integer second) {
    564             super(first, second);
    565         }
    566     }
    567 
    568     @CalledByNative
    569     private static ResultAnd<MessagePipeHandle.ReadMessageResult> newReadMessageResult(
    570             int mojoResult, int messageSize, int handlesCount) {
    571         MessagePipeHandle.ReadMessageResult result = new MessagePipeHandle.ReadMessageResult();
    572         result.setMessageSize(messageSize);
    573         result.setHandlesCount(handlesCount);
    574         return new ResultAnd<>(mojoResult, result);
    575     }
    576 
    577     @CalledByNative
    578     private static ResultAnd<Integer> newResultAndInteger(int mojoResult, int numBytesRead) {
    579         return new ResultAnd<>(mojoResult, numBytesRead);
    580     }
    581 
    582     @CalledByNative
    583     private static ResultAnd<IntegerPair> newNativeCreationResult(
    584             int mojoResult, int mojoHandle1, int mojoHandle2) {
    585         return new ResultAnd<>(mojoResult, new IntegerPair(mojoHandle1, mojoHandle2));
    586     }
    587 
    588     private native long nativeGetTimeTicksNow();
    589 
    590     private native int nativeWaitMany(ByteBuffer buffer, long deadline);
    591 
    592     private native ResultAnd<IntegerPair> nativeCreateMessagePipe(ByteBuffer optionsBuffer);
    593 
    594     private native ResultAnd<IntegerPair> nativeCreateDataPipe(ByteBuffer optionsBuffer);
    595 
    596     private native ResultAnd<Integer> nativeCreateSharedBuffer(
    597             ByteBuffer optionsBuffer, long numBytes);
    598 
    599     private native int nativeClose(int mojoHandle);
    600 
    601     private native int nativeWait(ByteBuffer buffer, int mojoHandle, int signals, long deadline);
    602 
    603     private native int nativeWriteMessage(
    604             int mojoHandle, ByteBuffer bytes, int numBytes, ByteBuffer handlesBuffer, int flags);
    605 
    606     private native ResultAnd<MessagePipeHandle.ReadMessageResult> nativeReadMessage(
    607             int mojoHandle, ByteBuffer bytes, ByteBuffer handlesBuffer, int flags);
    608 
    609     private native ResultAnd<Integer> nativeReadData(
    610             int mojoHandle, ByteBuffer elements, int elementsSize, int flags);
    611 
    612     private native ResultAnd<ByteBuffer> nativeBeginReadData(
    613             int mojoHandle, int numBytes, int flags);
    614 
    615     private native int nativeEndReadData(int mojoHandle, int numBytesRead);
    616 
    617     private native ResultAnd<Integer> nativeWriteData(
    618             int mojoHandle, ByteBuffer elements, int limit, int flags);
    619 
    620     private native ResultAnd<ByteBuffer> nativeBeginWriteData(
    621             int mojoHandle, int numBytes, int flags);
    622 
    623     private native int nativeEndWriteData(int mojoHandle, int numBytesWritten);
    624 
    625     private native ResultAnd<Integer> nativeDuplicate(int mojoHandle, ByteBuffer optionsBuffer);
    626 
    627     private native ResultAnd<ByteBuffer> nativeMap(
    628             int mojoHandle, long offset, long numBytes, int flags);
    629 
    630     private native int nativeUnmap(ByteBuffer buffer);
    631 
    632     private native AsyncWaiterCancellableImpl nativeAsyncWait(
    633             int mojoHandle, int signals, long deadline, AsyncWaiter.Callback callback);
    634 
    635     private native void nativeCancelAsyncWait(long mId, long dataPtr);
    636 
    637     private native int nativeGetNativeBufferOffset(ByteBuffer buffer, int alignment);
    638 }
    639