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