Home | History | Annotate | Download | only in system
      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 #include <stddef.h>
      6 #include <stdint.h>
      7 
      8 #include "base/android/jni_android.h"
      9 #include "base/android/jni_array.h"
     10 #include "base/android/scoped_java_ref.h"
     11 #include "jni/CoreImpl_jni.h"
     12 #include "mojo/public/c/system/core.h"
     13 #include "mojo/public/cpp/system/message_pipe.h"
     14 
     15 namespace mojo {
     16 namespace android {
     17 
     18 using base::android::JavaParamRef;
     19 using base::android::ScopedJavaLocalRef;
     20 
     21 static jlong JNI_CoreImpl_GetTimeTicksNow(
     22     JNIEnv* env,
     23     const JavaParamRef<jobject>& jcaller) {
     24   return MojoGetTimeTicksNow();
     25 }
     26 
     27 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_CreateMessagePipe(
     28     JNIEnv* env,
     29     const JavaParamRef<jobject>& jcaller,
     30     const JavaParamRef<jobject>& options_buffer) {
     31   const MojoCreateMessagePipeOptions* options = NULL;
     32   if (options_buffer) {
     33     const void* buffer_start = env->GetDirectBufferAddress(options_buffer);
     34     DCHECK(buffer_start);
     35     DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u);
     36     const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer);
     37     DCHECK_EQ(buffer_size, sizeof(MojoCreateMessagePipeOptions));
     38     options = static_cast<const MojoCreateMessagePipeOptions*>(buffer_start);
     39     DCHECK_EQ(options->struct_size, buffer_size);
     40   }
     41   MojoHandle handle1;
     42   MojoHandle handle2;
     43   MojoResult result = MojoCreateMessagePipe(options, &handle1, &handle2);
     44   return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2);
     45 }
     46 
     47 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_CreateDataPipe(
     48     JNIEnv* env,
     49     const JavaParamRef<jobject>& jcaller,
     50     const JavaParamRef<jobject>& options_buffer) {
     51   const MojoCreateDataPipeOptions* options = NULL;
     52   if (options_buffer) {
     53     const void* buffer_start = env->GetDirectBufferAddress(options_buffer);
     54     DCHECK(buffer_start);
     55     DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u);
     56     const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer);
     57     DCHECK_EQ(buffer_size, sizeof(MojoCreateDataPipeOptions));
     58     options = static_cast<const MojoCreateDataPipeOptions*>(buffer_start);
     59     DCHECK_EQ(options->struct_size, buffer_size);
     60   }
     61   MojoHandle handle1;
     62   MojoHandle handle2;
     63   MojoResult result = MojoCreateDataPipe(options, &handle1, &handle2);
     64   return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2);
     65 }
     66 
     67 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_CreateSharedBuffer(
     68     JNIEnv* env,
     69     const JavaParamRef<jobject>& jcaller,
     70     const JavaParamRef<jobject>& options_buffer,
     71     jlong num_bytes) {
     72   const MojoCreateSharedBufferOptions* options = 0;
     73   if (options_buffer) {
     74     const void* buffer_start = env->GetDirectBufferAddress(options_buffer);
     75     DCHECK(buffer_start);
     76     DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u);
     77     const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer);
     78     DCHECK_EQ(buffer_size, sizeof(MojoCreateSharedBufferOptions));
     79     options = static_cast<const MojoCreateSharedBufferOptions*>(buffer_start);
     80     DCHECK_EQ(options->struct_size, buffer_size);
     81   }
     82   MojoHandle handle;
     83   MojoResult result = MojoCreateSharedBuffer(num_bytes, options, &handle);
     84   return Java_CoreImpl_newResultAndInteger(env, result, handle);
     85 }
     86 
     87 static jint JNI_CoreImpl_Close(JNIEnv* env,
     88                                const JavaParamRef<jobject>& jcaller,
     89                                jint mojo_handle) {
     90   return MojoClose(mojo_handle);
     91 }
     92 
     93 static jint JNI_CoreImpl_QueryHandleSignalsState(
     94     JNIEnv* env,
     95     const JavaParamRef<jobject>& jcaller,
     96     jint mojo_handle,
     97     const JavaParamRef<jobject>& buffer) {
     98   MojoHandleSignalsState* signals_state =
     99       static_cast<MojoHandleSignalsState*>(env->GetDirectBufferAddress(buffer));
    100   DCHECK(signals_state);
    101   DCHECK_EQ(sizeof(MojoHandleSignalsState),
    102             static_cast<size_t>(env->GetDirectBufferCapacity(buffer)));
    103   return MojoQueryHandleSignalsState(mojo_handle, signals_state);
    104 }
    105 
    106 static jint JNI_CoreImpl_WriteMessage(
    107     JNIEnv* env,
    108     const JavaParamRef<jobject>& jcaller,
    109     jint mojo_handle,
    110     const JavaParamRef<jobject>& bytes,
    111     jint num_bytes,
    112     const JavaParamRef<jobject>& handles_buffer,
    113     jint flags) {
    114   const void* buffer_start = 0;
    115   uint32_t buffer_size = 0;
    116   if (bytes) {
    117     buffer_start = env->GetDirectBufferAddress(bytes);
    118     DCHECK(buffer_start);
    119     DCHECK(env->GetDirectBufferCapacity(bytes) >= num_bytes);
    120     buffer_size = num_bytes;
    121   }
    122   const MojoHandle* handles = 0;
    123   uint32_t num_handles = 0;
    124   if (handles_buffer) {
    125     handles =
    126         static_cast<MojoHandle*>(env->GetDirectBufferAddress(handles_buffer));
    127     num_handles = env->GetDirectBufferCapacity(handles_buffer) / 4;
    128   }
    129   // Java code will handle invalidating handles if the write succeeded.
    130   return WriteMessageRaw(
    131       MessagePipeHandle(static_cast<MojoHandle>(mojo_handle)), buffer_start,
    132       buffer_size, handles, num_handles, flags);
    133 }
    134 
    135 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_ReadMessage(
    136     JNIEnv* env,
    137     const JavaParamRef<jobject>& jcaller,
    138     jint mojo_handle,
    139     jint flags) {
    140   ScopedMessageHandle message;
    141   MojoResult result =
    142       ReadMessageNew(MessagePipeHandle(mojo_handle), &message, flags);
    143   if (result != MOJO_RESULT_OK)
    144     return Java_CoreImpl_newReadMessageResult(env, result, nullptr, nullptr);
    145   DCHECK(message.is_valid());
    146 
    147   result = MojoSerializeMessage(message->value(), nullptr);
    148   if (result != MOJO_RESULT_OK && result != MOJO_RESULT_FAILED_PRECONDITION) {
    149     return Java_CoreImpl_newReadMessageResult(env, MOJO_RESULT_ABORTED, nullptr,
    150                                               nullptr);
    151   }
    152 
    153   uint32_t num_bytes;
    154   void* buffer;
    155   uint32_t num_handles = 0;
    156   std::vector<MojoHandle> handles;
    157   result = MojoGetMessageData(message->value(), nullptr, &buffer, &num_bytes,
    158                               nullptr, &num_handles);
    159   if (result == MOJO_RESULT_RESOURCE_EXHAUSTED) {
    160     handles.resize(num_handles);
    161     result = MojoGetMessageData(message->value(), nullptr, &buffer, &num_bytes,
    162                                 handles.data(), &num_handles);
    163   }
    164 
    165   if (result != MOJO_RESULT_OK)
    166     return Java_CoreImpl_newReadMessageResult(env, result, nullptr, nullptr);
    167 
    168   return Java_CoreImpl_newReadMessageResult(
    169       env, result,
    170       base::android::ToJavaByteArray(env, static_cast<uint8_t*>(buffer),
    171                                      num_bytes),
    172       base::android::ToJavaIntArray(
    173           env, reinterpret_cast<jint*>(handles.data()), num_handles));
    174 }
    175 
    176 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_ReadData(
    177     JNIEnv* env,
    178     const JavaParamRef<jobject>& jcaller,
    179     jint mojo_handle,
    180     const JavaParamRef<jobject>& elements,
    181     jint elements_capacity,
    182     jint flags) {
    183   void* buffer_start = 0;
    184   uint32_t buffer_size = elements_capacity;
    185   if (elements) {
    186     buffer_start = env->GetDirectBufferAddress(elements);
    187     DCHECK(buffer_start);
    188     DCHECK(elements_capacity <= env->GetDirectBufferCapacity(elements));
    189   }
    190   MojoReadDataOptions options;
    191   options.struct_size = sizeof(options);
    192   options.flags = flags;
    193   MojoResult result =
    194       MojoReadData(mojo_handle, &options, buffer_start, &buffer_size);
    195   return Java_CoreImpl_newResultAndInteger(
    196       env, result, (result == MOJO_RESULT_OK) ? buffer_size : 0);
    197 }
    198 
    199 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_BeginReadData(
    200     JNIEnv* env,
    201     const JavaParamRef<jobject>& jcaller,
    202     jint mojo_handle,
    203     jint num_bytes,
    204     jint flags) {
    205   void const* buffer = 0;
    206   uint32_t buffer_size = num_bytes;
    207 
    208   MojoBeginReadDataOptions options;
    209   options.struct_size = sizeof(options);
    210   options.flags = flags;
    211   MojoResult result =
    212       MojoBeginReadData(mojo_handle, &options, &buffer, &buffer_size);
    213   if (result == MOJO_RESULT_OK) {
    214     ScopedJavaLocalRef<jobject> byte_buffer(
    215         env, env->NewDirectByteBuffer(const_cast<void*>(buffer), buffer_size));
    216     return Java_CoreImpl_newResultAndBuffer(env, result, byte_buffer);
    217   } else {
    218     return Java_CoreImpl_newResultAndBuffer(env, result, nullptr);
    219   }
    220 }
    221 
    222 static jint JNI_CoreImpl_EndReadData(JNIEnv* env,
    223                                      const JavaParamRef<jobject>& jcaller,
    224                                      jint mojo_handle,
    225                                      jint num_bytes_read) {
    226   return MojoEndReadData(mojo_handle, num_bytes_read, nullptr);
    227 }
    228 
    229 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_WriteData(
    230     JNIEnv* env,
    231     const JavaParamRef<jobject>& jcaller,
    232     jint mojo_handle,
    233     const JavaParamRef<jobject>& elements,
    234     jint limit,
    235     jint flags) {
    236   void* buffer_start = env->GetDirectBufferAddress(elements);
    237   DCHECK(buffer_start);
    238   DCHECK(limit <= env->GetDirectBufferCapacity(elements));
    239   uint32_t buffer_size = limit;
    240 
    241   MojoWriteDataOptions options;
    242   options.struct_size = sizeof(options);
    243   options.flags = flags;
    244   MojoResult result =
    245       MojoWriteData(mojo_handle, buffer_start, &buffer_size, &options);
    246   return Java_CoreImpl_newResultAndInteger(
    247       env, result, (result == MOJO_RESULT_OK) ? buffer_size : 0);
    248 }
    249 
    250 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_BeginWriteData(
    251     JNIEnv* env,
    252     const JavaParamRef<jobject>& jcaller,
    253     jint mojo_handle,
    254     jint num_bytes,
    255     jint flags) {
    256   void* buffer = 0;
    257   uint32_t buffer_size = num_bytes;
    258   MojoBeginWriteDataOptions options;
    259   options.struct_size = sizeof(options);
    260   options.flags = flags;
    261   MojoResult result =
    262       MojoBeginWriteData(mojo_handle, &options, &buffer, &buffer_size);
    263   if (result == MOJO_RESULT_OK) {
    264     ScopedJavaLocalRef<jobject> byte_buffer(
    265         env, env->NewDirectByteBuffer(buffer, buffer_size));
    266     return Java_CoreImpl_newResultAndBuffer(env, result, byte_buffer);
    267   } else {
    268     return Java_CoreImpl_newResultAndBuffer(env, result, nullptr);
    269   }
    270 }
    271 
    272 static jint JNI_CoreImpl_EndWriteData(JNIEnv* env,
    273                                       const JavaParamRef<jobject>& jcaller,
    274                                       jint mojo_handle,
    275                                       jint num_bytes_written) {
    276   return MojoEndWriteData(mojo_handle, num_bytes_written, nullptr);
    277 }
    278 
    279 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_Duplicate(
    280     JNIEnv* env,
    281     const JavaParamRef<jobject>& jcaller,
    282     jint mojo_handle,
    283     const JavaParamRef<jobject>& options_buffer) {
    284   const MojoDuplicateBufferHandleOptions* options = 0;
    285   if (options_buffer) {
    286     const void* buffer_start = env->GetDirectBufferAddress(options_buffer);
    287     DCHECK(buffer_start);
    288     const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer);
    289     DCHECK_EQ(buffer_size, sizeof(MojoDuplicateBufferHandleOptions));
    290     options =
    291         static_cast<const MojoDuplicateBufferHandleOptions*>(buffer_start);
    292     DCHECK_EQ(options->struct_size, buffer_size);
    293   }
    294   MojoHandle handle;
    295   MojoResult result = MojoDuplicateBufferHandle(mojo_handle, options, &handle);
    296   return Java_CoreImpl_newResultAndInteger(env, result, handle);
    297 }
    298 
    299 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_Map(
    300     JNIEnv* env,
    301     const JavaParamRef<jobject>& jcaller,
    302     jint mojo_handle,
    303     jlong offset,
    304     jlong num_bytes,
    305     jint flags) {
    306   void* buffer = 0;
    307   MojoMapBufferOptions options;
    308   options.struct_size = sizeof(options);
    309   options.flags = flags;
    310   MojoResult result =
    311       MojoMapBuffer(mojo_handle, offset, num_bytes, &options, &buffer);
    312   if (result == MOJO_RESULT_OK) {
    313     ScopedJavaLocalRef<jobject> byte_buffer(
    314         env, env->NewDirectByteBuffer(buffer, num_bytes));
    315     return Java_CoreImpl_newResultAndBuffer(env, result, byte_buffer);
    316   } else {
    317     return Java_CoreImpl_newResultAndBuffer(env, result, nullptr);
    318   }
    319 }
    320 
    321 static int JNI_CoreImpl_Unmap(JNIEnv* env,
    322                               const JavaParamRef<jobject>& jcaller,
    323                               const JavaParamRef<jobject>& buffer) {
    324   void* buffer_start = env->GetDirectBufferAddress(buffer);
    325   DCHECK(buffer_start);
    326   return MojoUnmapBuffer(buffer_start);
    327 }
    328 
    329 static jint JNI_CoreImpl_GetNativeBufferOffset(
    330     JNIEnv* env,
    331     const JavaParamRef<jobject>& jcaller,
    332     const JavaParamRef<jobject>& buffer,
    333     jint alignment) {
    334   jint offset =
    335       reinterpret_cast<uintptr_t>(env->GetDirectBufferAddress(buffer)) %
    336       alignment;
    337   if (offset == 0)
    338     return 0;
    339   return alignment - offset;
    340 }
    341 
    342 }  // namespace android
    343 }  // namespace mojo
    344