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 <memory>
     11 
     12 #include "base/android/base_jni_registrar.h"
     13 #include "base/android/jni_android.h"
     14 #include "base/android/jni_registrar.h"
     15 #include "base/android/library_loader/library_loader_hooks.h"
     16 #include "base/android/scoped_java_ref.h"
     17 #include "base/bind.h"
     18 #include "base/location.h"
     19 #include "base/single_thread_task_runner.h"
     20 #include "base/threading/thread_task_runner_handle.h"
     21 #include "jni/CoreImpl_jni.h"
     22 #include "mojo/message_pump/handle_watcher.h"
     23 #include "mojo/public/c/system/core.h"
     24 
     25 namespace {
     26 
     27 using MojoAsyncWaitID = uintptr_t;
     28 const MojoAsyncWaitID kInvalidHandleCancelID = 0;
     29 
     30 struct AsyncWaitCallbackData {
     31   base::android::ScopedJavaGlobalRef<jobject> core_impl;
     32   base::android::ScopedJavaGlobalRef<jobject> callback;
     33   base::android::ScopedJavaGlobalRef<jobject> cancellable;
     34 
     35   AsyncWaitCallbackData(JNIEnv* env, jobject core_impl, jobject callback) {
     36     this->core_impl.Reset(env, core_impl);
     37     this->callback.Reset(env, callback);
     38   }
     39 };
     40 
     41 void AsyncWaitCallback(mojo::common::HandleWatcher* watcher,
     42                        void* data,
     43                        MojoResult result) {
     44   delete watcher;
     45   std::unique_ptr<AsyncWaitCallbackData> callback_data(
     46       static_cast<AsyncWaitCallbackData*>(data));
     47   mojo::android::Java_CoreImpl_onAsyncWaitResult(
     48       base::android::AttachCurrentThread(),
     49       callback_data->core_impl.obj(),
     50       result,
     51       callback_data->callback.obj(),
     52       callback_data->cancellable.obj());
     53 }
     54 
     55 }  // namespace
     56 
     57 namespace mojo {
     58 namespace android {
     59 
     60 static jlong GetTimeTicksNow(JNIEnv* env,
     61                              const JavaParamRef<jobject>& jcaller) {
     62   return MojoGetTimeTicksNow();
     63 }
     64 
     65 static jint WaitMany(JNIEnv* env,
     66                      const JavaParamRef<jobject>& jcaller,
     67                      const JavaParamRef<jobject>& buffer,
     68                      jlong deadline) {
     69   // |buffer| contains, in this order
     70   // input: The array of N handles (MojoHandle, 4 bytes each)
     71   // input: The array of N signals (MojoHandleSignals, 4 bytes each)
     72   // space for output: The array of N handle states (MojoHandleSignalsState, 8
     73   //                   bytes each)
     74   // space for output: The result index (uint32_t, 4 bytes)
     75   uint8_t* buffer_start =
     76       static_cast<uint8_t*>(env->GetDirectBufferAddress(buffer));
     77   DCHECK(buffer_start);
     78   DCHECK_EQ(reinterpret_cast<uintptr_t>(buffer_start) % 8, 0u);
     79   // Each handle of the input array contributes 4 (MojoHandle) + 4
     80   // (MojoHandleSignals) + 8 (MojoHandleSignalsState) = 16 bytes to the size of
     81   // the buffer.
     82   const size_t size_per_handle = 16;
     83   const size_t buffer_size = env->GetDirectBufferCapacity(buffer);
     84   DCHECK_EQ((buffer_size - 4) % size_per_handle, 0u);
     85 
     86   const size_t nb_handles = (buffer_size - 4) / size_per_handle;
     87   const MojoHandle* handle_start =
     88       reinterpret_cast<const MojoHandle*>(buffer_start);
     89   const MojoHandleSignals* signals_start =
     90       reinterpret_cast<const MojoHandleSignals*>(buffer_start + 4 * nb_handles);
     91   MojoHandleSignalsState* states_start =
     92       reinterpret_cast<MojoHandleSignalsState*>(buffer_start + 8 * nb_handles);
     93   uint32_t* result_index =
     94       reinterpret_cast<uint32_t*>(buffer_start + 16 * nb_handles);
     95   *result_index = static_cast<uint32_t>(-1);
     96   return MojoWaitMany(handle_start, signals_start, nb_handles, deadline,
     97                       result_index, states_start);
     98 }
     99 
    100 static ScopedJavaLocalRef<jobject> CreateMessagePipe(
    101     JNIEnv* env,
    102     const JavaParamRef<jobject>& jcaller,
    103     const JavaParamRef<jobject>& options_buffer) {
    104   const MojoCreateMessagePipeOptions* options = NULL;
    105   if (options_buffer) {
    106     const void* buffer_start = env->GetDirectBufferAddress(options_buffer);
    107     DCHECK(buffer_start);
    108     DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u);
    109     const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer);
    110     DCHECK_EQ(buffer_size, sizeof(MojoCreateMessagePipeOptions));
    111     options = static_cast<const MojoCreateMessagePipeOptions*>(buffer_start);
    112     DCHECK_EQ(options->struct_size, buffer_size);
    113   }
    114   MojoHandle handle1;
    115   MojoHandle handle2;
    116   MojoResult result = MojoCreateMessagePipe(options, &handle1, &handle2);
    117   return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2);
    118 }
    119 
    120 static ScopedJavaLocalRef<jobject> CreateDataPipe(
    121     JNIEnv* env,
    122     const JavaParamRef<jobject>& jcaller,
    123     const JavaParamRef<jobject>& options_buffer) {
    124   const MojoCreateDataPipeOptions* options = NULL;
    125   if (options_buffer) {
    126     const void* buffer_start = env->GetDirectBufferAddress(options_buffer);
    127     DCHECK(buffer_start);
    128     DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u);
    129     const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer);
    130     DCHECK_EQ(buffer_size, sizeof(MojoCreateDataPipeOptions));
    131     options = static_cast<const MojoCreateDataPipeOptions*>(buffer_start);
    132     DCHECK_EQ(options->struct_size, buffer_size);
    133   }
    134   MojoHandle handle1;
    135   MojoHandle handle2;
    136   MojoResult result = MojoCreateDataPipe(options, &handle1, &handle2);
    137   return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2);
    138 }
    139 
    140 static ScopedJavaLocalRef<jobject> CreateSharedBuffer(
    141     JNIEnv* env,
    142     const JavaParamRef<jobject>& jcaller,
    143     const JavaParamRef<jobject>& options_buffer,
    144     jlong num_bytes) {
    145   const MojoCreateSharedBufferOptions* options = 0;
    146   if (options_buffer) {
    147     const void* buffer_start = env->GetDirectBufferAddress(options_buffer);
    148     DCHECK(buffer_start);
    149     DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u);
    150     const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer);
    151     DCHECK_EQ(buffer_size, sizeof(MojoCreateSharedBufferOptions));
    152     options = static_cast<const MojoCreateSharedBufferOptions*>(buffer_start);
    153     DCHECK_EQ(options->struct_size, buffer_size);
    154   }
    155   MojoHandle handle;
    156   MojoResult result = MojoCreateSharedBuffer(options, num_bytes, &handle);
    157   return Java_CoreImpl_newResultAndInteger(env, result, handle);
    158 }
    159 
    160 static jint Close(JNIEnv* env,
    161                   const JavaParamRef<jobject>& jcaller,
    162                   jint mojo_handle) {
    163   return MojoClose(mojo_handle);
    164 }
    165 
    166 static jint Wait(JNIEnv* env,
    167                  const JavaParamRef<jobject>& jcaller,
    168                  const JavaParamRef<jobject>& buffer,
    169                  jint mojo_handle,
    170                  jint signals,
    171                  jlong deadline) {
    172   // Buffer contains space for the MojoHandleSignalsState
    173   void* buffer_start = env->GetDirectBufferAddress(buffer);
    174   DCHECK(buffer_start);
    175   DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u);
    176   DCHECK_EQ(sizeof(struct MojoHandleSignalsState),
    177             static_cast<size_t>(env->GetDirectBufferCapacity(buffer)));
    178   struct MojoHandleSignalsState* signals_state =
    179       static_cast<struct MojoHandleSignalsState*>(buffer_start);
    180   return MojoWait(mojo_handle, signals, deadline, signals_state);
    181 }
    182 
    183 static jint WriteMessage(JNIEnv* env,
    184                          const JavaParamRef<jobject>& jcaller,
    185                          jint mojo_handle,
    186                          const JavaParamRef<jobject>& bytes,
    187                          jint num_bytes,
    188                          const JavaParamRef<jobject>& handles_buffer,
    189                          jint flags) {
    190   const void* buffer_start = 0;
    191   uint32_t buffer_size = 0;
    192   if (bytes) {
    193     buffer_start = env->GetDirectBufferAddress(bytes);
    194     DCHECK(buffer_start);
    195     DCHECK(env->GetDirectBufferCapacity(bytes) >= num_bytes);
    196     buffer_size = num_bytes;
    197   }
    198   const MojoHandle* handles = 0;
    199   uint32_t num_handles = 0;
    200   if (handles_buffer) {
    201     handles =
    202         static_cast<MojoHandle*>(env->GetDirectBufferAddress(handles_buffer));
    203     num_handles = env->GetDirectBufferCapacity(handles_buffer) / 4;
    204   }
    205   // Java code will handle invalidating handles if the write succeeded.
    206   return MojoWriteMessage(
    207       mojo_handle, buffer_start, buffer_size, handles, num_handles, flags);
    208 }
    209 
    210 static ScopedJavaLocalRef<jobject> ReadMessage(
    211     JNIEnv* env,
    212     const JavaParamRef<jobject>& jcaller,
    213     jint mojo_handle,
    214     const JavaParamRef<jobject>& bytes,
    215     const JavaParamRef<jobject>& handles_buffer,
    216     jint flags) {
    217   void* buffer_start = 0;
    218   uint32_t buffer_size = 0;
    219   if (bytes) {
    220     buffer_start = env->GetDirectBufferAddress(bytes);
    221     DCHECK(buffer_start);
    222     buffer_size = env->GetDirectBufferCapacity(bytes);
    223   }
    224   MojoHandle* handles = 0;
    225   uint32_t num_handles = 0;
    226   if (handles_buffer) {
    227     handles =
    228         static_cast<MojoHandle*>(env->GetDirectBufferAddress(handles_buffer));
    229     num_handles = env->GetDirectBufferCapacity(handles_buffer) / 4;
    230   }
    231   MojoResult result = MojoReadMessage(
    232       mojo_handle, buffer_start, &buffer_size, handles, &num_handles, flags);
    233   // Jave code will handle taking ownership of any received handle.
    234   return Java_CoreImpl_newReadMessageResult(env, result, buffer_size,
    235                                             num_handles);
    236 }
    237 
    238 static ScopedJavaLocalRef<jobject> ReadData(
    239     JNIEnv* env,
    240     const JavaParamRef<jobject>& jcaller,
    241     jint mojo_handle,
    242     const JavaParamRef<jobject>& elements,
    243     jint elements_capacity,
    244     jint flags) {
    245   void* buffer_start = 0;
    246   uint32_t buffer_size = elements_capacity;
    247   if (elements) {
    248     buffer_start = env->GetDirectBufferAddress(elements);
    249     DCHECK(buffer_start);
    250     DCHECK(elements_capacity <= env->GetDirectBufferCapacity(elements));
    251   }
    252   MojoResult result =
    253       MojoReadData(mojo_handle, buffer_start, &buffer_size, flags);
    254   return Java_CoreImpl_newResultAndInteger(
    255       env, result, (result == MOJO_RESULT_OK) ? buffer_size : 0);
    256 }
    257 
    258 static ScopedJavaLocalRef<jobject> BeginReadData(
    259     JNIEnv* env,
    260     const JavaParamRef<jobject>& jcaller,
    261     jint mojo_handle,
    262     jint num_bytes,
    263     jint flags) {
    264   void const* buffer = 0;
    265   uint32_t buffer_size = num_bytes;
    266   MojoResult result =
    267       MojoBeginReadData(mojo_handle, &buffer, &buffer_size, flags);
    268   jobject byte_buffer = 0;
    269   if (result == MOJO_RESULT_OK) {
    270     byte_buffer =
    271         env->NewDirectByteBuffer(const_cast<void*>(buffer), buffer_size);
    272   }
    273   return Java_CoreImpl_newResultAndBuffer(env, result, byte_buffer);
    274 }
    275 
    276 static jint EndReadData(JNIEnv* env,
    277                         const JavaParamRef<jobject>& jcaller,
    278                         jint mojo_handle,
    279                         jint num_bytes_read) {
    280   return MojoEndReadData(mojo_handle, num_bytes_read);
    281 }
    282 
    283 static ScopedJavaLocalRef<jobject> WriteData(
    284     JNIEnv* env,
    285     const JavaParamRef<jobject>& jcaller,
    286     jint mojo_handle,
    287     const JavaParamRef<jobject>& elements,
    288     jint limit,
    289     jint flags) {
    290   void* buffer_start = env->GetDirectBufferAddress(elements);
    291   DCHECK(buffer_start);
    292   DCHECK(limit <= env->GetDirectBufferCapacity(elements));
    293   uint32_t buffer_size = limit;
    294   MojoResult result =
    295       MojoWriteData(mojo_handle, buffer_start, &buffer_size, flags);
    296   return Java_CoreImpl_newResultAndInteger(
    297       env, result, (result == MOJO_RESULT_OK) ? buffer_size : 0);
    298 }
    299 
    300 static ScopedJavaLocalRef<jobject> BeginWriteData(
    301     JNIEnv* env,
    302     const JavaParamRef<jobject>& jcaller,
    303     jint mojo_handle,
    304     jint num_bytes,
    305     jint flags) {
    306   void* buffer = 0;
    307   uint32_t buffer_size = num_bytes;
    308   MojoResult result =
    309       MojoBeginWriteData(mojo_handle, &buffer, &buffer_size, flags);
    310   jobject byte_buffer = 0;
    311   if (result == MOJO_RESULT_OK) {
    312     byte_buffer = env->NewDirectByteBuffer(buffer, buffer_size);
    313   }
    314   return Java_CoreImpl_newResultAndBuffer(env, result, byte_buffer);
    315 }
    316 
    317 static jint EndWriteData(JNIEnv* env,
    318                          const JavaParamRef<jobject>& jcaller,
    319                          jint mojo_handle,
    320                          jint num_bytes_written) {
    321   return MojoEndWriteData(mojo_handle, num_bytes_written);
    322 }
    323 
    324 static ScopedJavaLocalRef<jobject> Duplicate(
    325     JNIEnv* env,
    326     const JavaParamRef<jobject>& jcaller,
    327     jint mojo_handle,
    328     const JavaParamRef<jobject>& options_buffer) {
    329   const MojoDuplicateBufferHandleOptions* options = 0;
    330   if (options_buffer) {
    331     const void* buffer_start = env->GetDirectBufferAddress(options_buffer);
    332     DCHECK(buffer_start);
    333     const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer);
    334     DCHECK_EQ(buffer_size, sizeof(MojoDuplicateBufferHandleOptions));
    335     options =
    336         static_cast<const MojoDuplicateBufferHandleOptions*>(buffer_start);
    337     DCHECK_EQ(options->struct_size, buffer_size);
    338   }
    339   MojoHandle handle;
    340   MojoResult result = MojoDuplicateBufferHandle(mojo_handle, options, &handle);
    341   return Java_CoreImpl_newResultAndInteger(env, result, handle);
    342 }
    343 
    344 static ScopedJavaLocalRef<jobject> Map(JNIEnv* env,
    345                                        const JavaParamRef<jobject>& jcaller,
    346                                        jint mojo_handle,
    347                                        jlong offset,
    348                                        jlong num_bytes,
    349                                        jint flags) {
    350   void* buffer = 0;
    351   MojoResult result =
    352       MojoMapBuffer(mojo_handle, offset, num_bytes, &buffer, flags);
    353   jobject byte_buffer = 0;
    354   if (result == MOJO_RESULT_OK) {
    355     byte_buffer = env->NewDirectByteBuffer(buffer, num_bytes);
    356   }
    357   return Java_CoreImpl_newResultAndBuffer(env, result, byte_buffer);
    358 }
    359 
    360 static int Unmap(JNIEnv* env,
    361                  const JavaParamRef<jobject>& jcaller,
    362                  const JavaParamRef<jobject>& buffer) {
    363   void* buffer_start = env->GetDirectBufferAddress(buffer);
    364   DCHECK(buffer_start);
    365   return MojoUnmapBuffer(buffer_start);
    366 }
    367 
    368 static ScopedJavaLocalRef<jobject> AsyncWait(
    369     JNIEnv* env,
    370     const JavaParamRef<jobject>& jcaller,
    371     jint mojo_handle,
    372     jint signals,
    373     jlong deadline,
    374     const JavaParamRef<jobject>& callback) {
    375   AsyncWaitCallbackData* callback_data =
    376       new AsyncWaitCallbackData(env, jcaller, callback);
    377   MojoAsyncWaitID cancel_id;
    378   if (static_cast<MojoHandle>(mojo_handle) != MOJO_HANDLE_INVALID) {
    379     common::HandleWatcher* watcher = new common::HandleWatcher();
    380     cancel_id = reinterpret_cast<MojoAsyncWaitID>(watcher);
    381     watcher->Start(Handle(static_cast<MojoHandle>(mojo_handle)), signals,
    382                    deadline,
    383                    base::Bind(&AsyncWaitCallback, watcher, callback_data));
    384   } else {
    385     cancel_id = kInvalidHandleCancelID;
    386     base::ThreadTaskRunnerHandle::Get()->PostTask(
    387         FROM_HERE, base::Bind(&AsyncWaitCallback, nullptr, callback_data,
    388                               MOJO_RESULT_INVALID_ARGUMENT));
    389   }
    390   base::android::ScopedJavaLocalRef<jobject> cancellable =
    391       Java_CoreImpl_newAsyncWaiterCancellableImpl(
    392           env, jcaller, cancel_id, reinterpret_cast<intptr_t>(callback_data));
    393   callback_data->cancellable.Reset(env, cancellable.obj());
    394   return cancellable;
    395 }
    396 
    397 static void CancelAsyncWait(JNIEnv* env,
    398                             const JavaParamRef<jobject>& jcaller,
    399                             jlong id,
    400                             jlong data_ptr) {
    401   if (id == 0) {
    402     // If |id| is |kInvalidHandleCancelID|, the async wait was done on an
    403     // invalid handle, so the AsyncWaitCallback will be called and will clear
    404     // the data_ptr.
    405     return;
    406   }
    407   std::unique_ptr<AsyncWaitCallbackData> deleter(
    408       reinterpret_cast<AsyncWaitCallbackData*>(data_ptr));
    409   delete reinterpret_cast<common::HandleWatcher*>(
    410       static_cast<MojoAsyncWaitID>(id));
    411 }
    412 
    413 static jint GetNativeBufferOffset(JNIEnv* env,
    414                                   const JavaParamRef<jobject>& jcaller,
    415                                   const JavaParamRef<jobject>& buffer,
    416                                   jint alignment) {
    417   jint offset =
    418       reinterpret_cast<uintptr_t>(env->GetDirectBufferAddress(buffer)) %
    419       alignment;
    420   if (offset == 0)
    421     return 0;
    422   return alignment - offset;
    423 }
    424 
    425 bool RegisterCoreImpl(JNIEnv* env) {
    426   return RegisterNativesImpl(env);
    427 }
    428 
    429 }  // namespace android
    430 }  // namespace mojo
    431