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