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 "mojo/android/system/core_impl.h"
      6 
      7 #include <stddef.h>
      8 #include <stdint.h>
      9 
     10 #include "base/android/base_jni_registrar.h"
     11 #include "base/android/jni_android.h"
     12 #include "base/android/jni_registrar.h"
     13 #include "base/android/library_loader/library_loader_hooks.h"
     14 #include "base/android/scoped_java_ref.h"
     15 #include "jni/CoreImpl_jni.h"
     16 #include "mojo/public/c/system/core.h"
     17 
     18 namespace mojo {
     19 namespace android {
     20 
     21 using base::android::JavaParamRef;
     22 using base::android::ScopedJavaLocalRef;
     23 
     24 static jlong GetTimeTicksNow(JNIEnv* env,
     25                              const JavaParamRef<jobject>& jcaller) {
     26   return MojoGetTimeTicksNow();
     27 }
     28 
     29 static jint WaitMany(JNIEnv* env,
     30                      const JavaParamRef<jobject>& jcaller,
     31                      const JavaParamRef<jobject>& buffer,
     32                      jlong deadline) {
     33   // |buffer| contains, in this order
     34   // input: The array of N handles (MojoHandle, 4 bytes each)
     35   // input: The array of N signals (MojoHandleSignals, 4 bytes each)
     36   // space for output: The array of N handle states (MojoHandleSignalsState, 8
     37   //                   bytes each)
     38   // space for output: The result index (uint32_t, 4 bytes)
     39   uint8_t* buffer_start =
     40       static_cast<uint8_t*>(env->GetDirectBufferAddress(buffer));
     41   DCHECK(buffer_start);
     42   DCHECK_EQ(reinterpret_cast<uintptr_t>(buffer_start) % 8, 0u);
     43   // Each handle of the input array contributes 4 (MojoHandle) + 4
     44   // (MojoHandleSignals) + 8 (MojoHandleSignalsState) = 16 bytes to the size of
     45   // the buffer.
     46   const size_t size_per_handle = 16;
     47   const size_t buffer_size = env->GetDirectBufferCapacity(buffer);
     48   DCHECK_EQ((buffer_size - 4) % size_per_handle, 0u);
     49 
     50   const size_t nb_handles = (buffer_size - 4) / size_per_handle;
     51   const MojoHandle* handle_start =
     52       reinterpret_cast<const MojoHandle*>(buffer_start);
     53   const MojoHandleSignals* signals_start =
     54       reinterpret_cast<const MojoHandleSignals*>(buffer_start + 4 * nb_handles);
     55   MojoHandleSignalsState* states_start =
     56       reinterpret_cast<MojoHandleSignalsState*>(buffer_start + 8 * nb_handles);
     57   uint32_t* result_index =
     58       reinterpret_cast<uint32_t*>(buffer_start + 16 * nb_handles);
     59   *result_index = static_cast<uint32_t>(-1);
     60   return MojoWaitMany(handle_start, signals_start, nb_handles, deadline,
     61                       result_index, states_start);
     62 }
     63 
     64 static ScopedJavaLocalRef<jobject> CreateMessagePipe(
     65     JNIEnv* env,
     66     const JavaParamRef<jobject>& jcaller,
     67     const JavaParamRef<jobject>& options_buffer) {
     68   const MojoCreateMessagePipeOptions* options = NULL;
     69   if (options_buffer) {
     70     const void* buffer_start = env->GetDirectBufferAddress(options_buffer);
     71     DCHECK(buffer_start);
     72     DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u);
     73     const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer);
     74     DCHECK_EQ(buffer_size, sizeof(MojoCreateMessagePipeOptions));
     75     options = static_cast<const MojoCreateMessagePipeOptions*>(buffer_start);
     76     DCHECK_EQ(options->struct_size, buffer_size);
     77   }
     78   MojoHandle handle1;
     79   MojoHandle handle2;
     80   MojoResult result = MojoCreateMessagePipe(options, &handle1, &handle2);
     81   return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2);
     82 }
     83 
     84 static ScopedJavaLocalRef<jobject> CreateDataPipe(
     85     JNIEnv* env,
     86     const JavaParamRef<jobject>& jcaller,
     87     const JavaParamRef<jobject>& options_buffer) {
     88   const MojoCreateDataPipeOptions* options = NULL;
     89   if (options_buffer) {
     90     const void* buffer_start = env->GetDirectBufferAddress(options_buffer);
     91     DCHECK(buffer_start);
     92     DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u);
     93     const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer);
     94     DCHECK_EQ(buffer_size, sizeof(MojoCreateDataPipeOptions));
     95     options = static_cast<const MojoCreateDataPipeOptions*>(buffer_start);
     96     DCHECK_EQ(options->struct_size, buffer_size);
     97   }
     98   MojoHandle handle1;
     99   MojoHandle handle2;
    100   MojoResult result = MojoCreateDataPipe(options, &handle1, &handle2);
    101   return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2);
    102 }
    103 
    104 static ScopedJavaLocalRef<jobject> CreateSharedBuffer(
    105     JNIEnv* env,
    106     const JavaParamRef<jobject>& jcaller,
    107     const JavaParamRef<jobject>& options_buffer,
    108     jlong num_bytes) {
    109   const MojoCreateSharedBufferOptions* options = 0;
    110   if (options_buffer) {
    111     const void* buffer_start = env->GetDirectBufferAddress(options_buffer);
    112     DCHECK(buffer_start);
    113     DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u);
    114     const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer);
    115     DCHECK_EQ(buffer_size, sizeof(MojoCreateSharedBufferOptions));
    116     options = static_cast<const MojoCreateSharedBufferOptions*>(buffer_start);
    117     DCHECK_EQ(options->struct_size, buffer_size);
    118   }
    119   MojoHandle handle;
    120   MojoResult result = MojoCreateSharedBuffer(options, num_bytes, &handle);
    121   return Java_CoreImpl_newResultAndInteger(env, result, handle);
    122 }
    123 
    124 static jint Close(JNIEnv* env,
    125                   const JavaParamRef<jobject>& jcaller,
    126                   jint mojo_handle) {
    127   return MojoClose(mojo_handle);
    128 }
    129 
    130 static jint Wait(JNIEnv* env,
    131                  const JavaParamRef<jobject>& jcaller,
    132                  const JavaParamRef<jobject>& buffer,
    133                  jint mojo_handle,
    134                  jint signals,
    135                  jlong deadline) {
    136   // Buffer contains space for the MojoHandleSignalsState
    137   void* buffer_start = env->GetDirectBufferAddress(buffer);
    138   DCHECK(buffer_start);
    139   DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u);
    140   DCHECK_EQ(sizeof(struct MojoHandleSignalsState),
    141             static_cast<size_t>(env->GetDirectBufferCapacity(buffer)));
    142   struct MojoHandleSignalsState* signals_state =
    143       static_cast<struct MojoHandleSignalsState*>(buffer_start);
    144   return MojoWait(mojo_handle, signals, deadline, signals_state);
    145 }
    146 
    147 static jint WriteMessage(JNIEnv* env,
    148                          const JavaParamRef<jobject>& jcaller,
    149                          jint mojo_handle,
    150                          const JavaParamRef<jobject>& bytes,
    151                          jint num_bytes,
    152                          const JavaParamRef<jobject>& handles_buffer,
    153                          jint flags) {
    154   const void* buffer_start = 0;
    155   uint32_t buffer_size = 0;
    156   if (bytes) {
    157     buffer_start = env->GetDirectBufferAddress(bytes);
    158     DCHECK(buffer_start);
    159     DCHECK(env->GetDirectBufferCapacity(bytes) >= num_bytes);
    160     buffer_size = num_bytes;
    161   }
    162   const MojoHandle* handles = 0;
    163   uint32_t num_handles = 0;
    164   if (handles_buffer) {
    165     handles =
    166         static_cast<MojoHandle*>(env->GetDirectBufferAddress(handles_buffer));
    167     num_handles = env->GetDirectBufferCapacity(handles_buffer) / 4;
    168   }
    169   // Java code will handle invalidating handles if the write succeeded.
    170   return MojoWriteMessage(
    171       mojo_handle, buffer_start, buffer_size, handles, num_handles, flags);
    172 }
    173 
    174 static ScopedJavaLocalRef<jobject> ReadMessage(
    175     JNIEnv* env,
    176     const JavaParamRef<jobject>& jcaller,
    177     jint mojo_handle,
    178     const JavaParamRef<jobject>& bytes,
    179     const JavaParamRef<jobject>& handles_buffer,
    180     jint flags) {
    181   void* buffer_start = 0;
    182   uint32_t buffer_size = 0;
    183   if (bytes) {
    184     buffer_start = env->GetDirectBufferAddress(bytes);
    185     DCHECK(buffer_start);
    186     buffer_size = env->GetDirectBufferCapacity(bytes);
    187   }
    188   MojoHandle* handles = 0;
    189   uint32_t num_handles = 0;
    190   if (handles_buffer) {
    191     handles =
    192         static_cast<MojoHandle*>(env->GetDirectBufferAddress(handles_buffer));
    193     num_handles = env->GetDirectBufferCapacity(handles_buffer) / 4;
    194   }
    195   MojoResult result = MojoReadMessage(
    196       mojo_handle, buffer_start, &buffer_size, handles, &num_handles, flags);
    197   // Jave code will handle taking ownership of any received handle.
    198   return Java_CoreImpl_newReadMessageResult(env, result, buffer_size,
    199                                             num_handles);
    200 }
    201 
    202 static ScopedJavaLocalRef<jobject> ReadData(
    203     JNIEnv* env,
    204     const JavaParamRef<jobject>& jcaller,
    205     jint mojo_handle,
    206     const JavaParamRef<jobject>& elements,
    207     jint elements_capacity,
    208     jint flags) {
    209   void* buffer_start = 0;
    210   uint32_t buffer_size = elements_capacity;
    211   if (elements) {
    212     buffer_start = env->GetDirectBufferAddress(elements);
    213     DCHECK(buffer_start);
    214     DCHECK(elements_capacity <= env->GetDirectBufferCapacity(elements));
    215   }
    216   MojoResult result =
    217       MojoReadData(mojo_handle, buffer_start, &buffer_size, flags);
    218   return Java_CoreImpl_newResultAndInteger(
    219       env, result, (result == MOJO_RESULT_OK) ? buffer_size : 0);
    220 }
    221 
    222 static ScopedJavaLocalRef<jobject> BeginReadData(
    223     JNIEnv* env,
    224     const JavaParamRef<jobject>& jcaller,
    225     jint mojo_handle,
    226     jint num_bytes,
    227     jint flags) {
    228   void const* buffer = 0;
    229   uint32_t buffer_size = num_bytes;
    230   MojoResult result =
    231       MojoBeginReadData(mojo_handle, &buffer, &buffer_size, flags);
    232   jobject byte_buffer = 0;
    233   if (result == MOJO_RESULT_OK) {
    234     byte_buffer =
    235         env->NewDirectByteBuffer(const_cast<void*>(buffer), buffer_size);
    236   }
    237   return Java_CoreImpl_newResultAndBuffer(env, result, byte_buffer);
    238 }
    239 
    240 static jint EndReadData(JNIEnv* env,
    241                         const JavaParamRef<jobject>& jcaller,
    242                         jint mojo_handle,
    243                         jint num_bytes_read) {
    244   return MojoEndReadData(mojo_handle, num_bytes_read);
    245 }
    246 
    247 static ScopedJavaLocalRef<jobject> WriteData(
    248     JNIEnv* env,
    249     const JavaParamRef<jobject>& jcaller,
    250     jint mojo_handle,
    251     const JavaParamRef<jobject>& elements,
    252     jint limit,
    253     jint flags) {
    254   void* buffer_start = env->GetDirectBufferAddress(elements);
    255   DCHECK(buffer_start);
    256   DCHECK(limit <= env->GetDirectBufferCapacity(elements));
    257   uint32_t buffer_size = limit;
    258   MojoResult result =
    259       MojoWriteData(mojo_handle, buffer_start, &buffer_size, flags);
    260   return Java_CoreImpl_newResultAndInteger(
    261       env, result, (result == MOJO_RESULT_OK) ? buffer_size : 0);
    262 }
    263 
    264 static ScopedJavaLocalRef<jobject> BeginWriteData(
    265     JNIEnv* env,
    266     const JavaParamRef<jobject>& jcaller,
    267     jint mojo_handle,
    268     jint num_bytes,
    269     jint flags) {
    270   void* buffer = 0;
    271   uint32_t buffer_size = num_bytes;
    272   MojoResult result =
    273       MojoBeginWriteData(mojo_handle, &buffer, &buffer_size, flags);
    274   jobject byte_buffer = 0;
    275   if (result == MOJO_RESULT_OK) {
    276     byte_buffer = env->NewDirectByteBuffer(buffer, buffer_size);
    277   }
    278   return Java_CoreImpl_newResultAndBuffer(env, result, byte_buffer);
    279 }
    280 
    281 static jint EndWriteData(JNIEnv* env,
    282                          const JavaParamRef<jobject>& jcaller,
    283                          jint mojo_handle,
    284                          jint num_bytes_written) {
    285   return MojoEndWriteData(mojo_handle, num_bytes_written);
    286 }
    287 
    288 static ScopedJavaLocalRef<jobject> Duplicate(
    289     JNIEnv* env,
    290     const JavaParamRef<jobject>& jcaller,
    291     jint mojo_handle,
    292     const JavaParamRef<jobject>& options_buffer) {
    293   const MojoDuplicateBufferHandleOptions* options = 0;
    294   if (options_buffer) {
    295     const void* buffer_start = env->GetDirectBufferAddress(options_buffer);
    296     DCHECK(buffer_start);
    297     const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer);
    298     DCHECK_EQ(buffer_size, sizeof(MojoDuplicateBufferHandleOptions));
    299     options =
    300         static_cast<const MojoDuplicateBufferHandleOptions*>(buffer_start);
    301     DCHECK_EQ(options->struct_size, buffer_size);
    302   }
    303   MojoHandle handle;
    304   MojoResult result = MojoDuplicateBufferHandle(mojo_handle, options, &handle);
    305   return Java_CoreImpl_newResultAndInteger(env, result, handle);
    306 }
    307 
    308 static ScopedJavaLocalRef<jobject> Map(JNIEnv* env,
    309                                        const JavaParamRef<jobject>& jcaller,
    310                                        jint mojo_handle,
    311                                        jlong offset,
    312                                        jlong num_bytes,
    313                                        jint flags) {
    314   void* buffer = 0;
    315   MojoResult result =
    316       MojoMapBuffer(mojo_handle, offset, num_bytes, &buffer, flags);
    317   jobject byte_buffer = 0;
    318   if (result == MOJO_RESULT_OK) {
    319     byte_buffer = env->NewDirectByteBuffer(buffer, num_bytes);
    320   }
    321   return Java_CoreImpl_newResultAndBuffer(env, result, byte_buffer);
    322 }
    323 
    324 static int Unmap(JNIEnv* env,
    325                  const JavaParamRef<jobject>& jcaller,
    326                  const JavaParamRef<jobject>& buffer) {
    327   void* buffer_start = env->GetDirectBufferAddress(buffer);
    328   DCHECK(buffer_start);
    329   return MojoUnmapBuffer(buffer_start);
    330 }
    331 
    332 static jint GetNativeBufferOffset(JNIEnv* env,
    333                                   const JavaParamRef<jobject>& jcaller,
    334                                   const JavaParamRef<jobject>& buffer,
    335                                   jint alignment) {
    336   jint offset =
    337       reinterpret_cast<uintptr_t>(env->GetDirectBufferAddress(buffer)) %
    338       alignment;
    339   if (offset == 0)
    340     return 0;
    341   return alignment - offset;
    342 }
    343 
    344 bool RegisterCoreImpl(JNIEnv* env) {
    345   return RegisterNativesImpl(env);
    346 }
    347 
    348 }  // namespace android
    349 }  // namespace mojo
    350