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 "base/android/base_jni_registrar.h"
      8 #include "base/android/jni_android.h"
      9 #include "base/android/jni_registrar.h"
     10 #include "base/android/library_loader/library_loader_hooks.h"
     11 #include "base/android/scoped_java_ref.h"
     12 #include "base/bind.h"
     13 #include "base/message_loop/message_loop.h"
     14 #include "jni/CoreImpl_jni.h"
     15 #include "mojo/embedder/embedder.h"
     16 #include "mojo/public/c/environment/async_waiter.h"
     17 #include "mojo/public/c/system/core.h"
     18 #include "mojo/public/cpp/environment/environment.h"
     19 
     20 namespace {
     21 
     22 // |AsyncWait| is guaranteed never to return 0.
     23 const MojoAsyncWaitID kInvalidHandleCancelID = 0;
     24 
     25 struct AsyncWaitCallbackData {
     26   base::android::ScopedJavaGlobalRef<jobject> core_impl;
     27   base::android::ScopedJavaGlobalRef<jobject> callback;
     28   base::android::ScopedJavaGlobalRef<jobject> cancellable;
     29 
     30   AsyncWaitCallbackData(JNIEnv* env, jobject core_impl, jobject callback) {
     31     this->core_impl.Reset(env, core_impl);
     32     this->callback.Reset(env, callback);
     33   }
     34 };
     35 
     36 void AsyncWaitCallback(void* data, MojoResult result) {
     37   scoped_ptr<AsyncWaitCallbackData> callback_data(
     38       static_cast<AsyncWaitCallbackData*>(data));
     39   mojo::android::Java_CoreImpl_onAsyncWaitResult(
     40       base::android::AttachCurrentThread(),
     41       callback_data->core_impl.obj(),
     42       result,
     43       callback_data->callback.obj(),
     44       callback_data->cancellable.obj());
     45 }
     46 
     47 }  // namespace
     48 
     49 namespace mojo {
     50 namespace android {
     51 
     52 static void Constructor(JNIEnv* env, jobject jcaller) {
     53   mojo::embedder::Init();
     54 }
     55 
     56 static jlong GetTimeTicksNow(JNIEnv* env, jobject jcaller) {
     57   return MojoGetTimeTicksNow();
     58 }
     59 
     60 static jint WaitMany(JNIEnv* env,
     61                      jobject jcaller,
     62                      jobject buffer,
     63                      jlong deadline) {
     64   // Buffer contains first the list of handles, then the list of flags.
     65   const void* buffer_start = env->GetDirectBufferAddress(buffer);
     66   DCHECK(buffer_start);
     67   const size_t record_size = 8;
     68   const size_t buffer_size = env->GetDirectBufferCapacity(buffer);
     69   DCHECK_EQ(buffer_size % record_size, 0u);
     70 
     71   const size_t nb_handles = buffer_size / record_size;
     72   const MojoHandle* handle_start = static_cast<const MojoHandle*>(buffer_start);
     73   const MojoHandleSignals* signals_start =
     74       static_cast<const MojoHandleSignals*>(handle_start + nb_handles);
     75   return MojoWaitMany(handle_start, signals_start, nb_handles, deadline);
     76 }
     77 
     78 static jobject CreateMessagePipe(JNIEnv* env, jobject jcaller) {
     79   MojoHandle handle1;
     80   MojoHandle handle2;
     81   // TODO(vtl): Add support for the options struct.
     82   MojoResult result = MojoCreateMessagePipe(NULL, &handle1, &handle2);
     83   return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2)
     84       .Release();
     85 }
     86 
     87 static jobject CreateDataPipe(JNIEnv* env,
     88                               jobject jcaller,
     89                               jobject options_buffer) {
     90   const MojoCreateDataPipeOptions* options = NULL;
     91   if (options_buffer) {
     92     const void* buffer_start = env->GetDirectBufferAddress(options_buffer);
     93     DCHECK(buffer_start);
     94     const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer);
     95     DCHECK_EQ(buffer_size, sizeof(MojoCreateDataPipeOptions));
     96     options = static_cast<const MojoCreateDataPipeOptions*>(buffer_start);
     97     DCHECK_EQ(options->struct_size, buffer_size);
     98   }
     99   MojoHandle handle1;
    100   MojoHandle handle2;
    101   MojoResult result = MojoCreateDataPipe(options, &handle1, &handle2);
    102   return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2)
    103       .Release();
    104 }
    105 
    106 static jobject CreateSharedBuffer(JNIEnv* env,
    107                                   jobject jcaller,
    108                                   jobject options_buffer,
    109                                   jlong num_bytes) {
    110   const MojoCreateSharedBufferOptions* options = 0;
    111   if (options_buffer) {
    112     const void* buffer_start = env->GetDirectBufferAddress(options_buffer);
    113     DCHECK(buffer_start);
    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_newNativeCreationResult(env, result, handle, 0)
    122       .Release();
    123 }
    124 
    125 static jint Close(JNIEnv* env, jobject jcaller, jint mojo_handle) {
    126   return MojoClose(mojo_handle);
    127 }
    128 
    129 static jint Wait(JNIEnv* env,
    130                  jobject jcaller,
    131                  jint mojo_handle,
    132                  jint signals,
    133                  jlong deadline) {
    134   return MojoWait(mojo_handle, signals, deadline);
    135 }
    136 
    137 static jint WriteMessage(JNIEnv* env,
    138                          jobject jcaller,
    139                          jint mojo_handle,
    140                          jobject bytes,
    141                          jint num_bytes,
    142                          jobject handles_buffer,
    143                          jint flags) {
    144   const void* buffer_start = 0;
    145   uint32_t buffer_size = 0;
    146   if (bytes) {
    147     buffer_start = env->GetDirectBufferAddress(bytes);
    148     DCHECK(buffer_start);
    149     DCHECK(env->GetDirectBufferCapacity(bytes) >= num_bytes);
    150     buffer_size = num_bytes;
    151   }
    152   const MojoHandle* handles = 0;
    153   uint32_t num_handles = 0;
    154   if (handles_buffer) {
    155     handles =
    156         static_cast<MojoHandle*>(env->GetDirectBufferAddress(handles_buffer));
    157     num_handles = env->GetDirectBufferCapacity(handles_buffer) / 4;
    158   }
    159   // Java code will handle invalidating handles if the write succeeded.
    160   return MojoWriteMessage(
    161       mojo_handle, buffer_start, buffer_size, handles, num_handles, flags);
    162 }
    163 
    164 static jobject ReadMessage(JNIEnv* env,
    165                            jobject jcaller,
    166                            jint mojo_handle,
    167                            jobject bytes,
    168                            jobject handles_buffer,
    169                            jint flags) {
    170   void* buffer_start = 0;
    171   uint32_t buffer_size = 0;
    172   if (bytes) {
    173     buffer_start = env->GetDirectBufferAddress(bytes);
    174     DCHECK(buffer_start);
    175     buffer_size = env->GetDirectBufferCapacity(bytes);
    176   }
    177   MojoHandle* handles = 0;
    178   uint32_t num_handles = 0;
    179   if (handles_buffer) {
    180     handles =
    181         static_cast<MojoHandle*>(env->GetDirectBufferAddress(handles_buffer));
    182     num_handles = env->GetDirectBufferCapacity(handles_buffer) / 4;
    183   }
    184   MojoResult result = MojoReadMessage(
    185       mojo_handle, buffer_start, &buffer_size, handles, &num_handles, flags);
    186   // Jave code will handle taking ownership of any received handle.
    187   return Java_CoreImpl_newReadMessageResult(
    188              env, result, buffer_size, num_handles).Release();
    189 }
    190 
    191 static jint ReadData(JNIEnv* env,
    192                      jobject jcaller,
    193                      jint mojo_handle,
    194                      jobject elements,
    195                      jint elements_capacity,
    196                      jint flags) {
    197   void* buffer_start = 0;
    198   uint32_t buffer_size = elements_capacity;
    199   if (elements) {
    200     buffer_start = env->GetDirectBufferAddress(elements);
    201     DCHECK(buffer_start);
    202     DCHECK(elements_capacity <= env->GetDirectBufferCapacity(elements));
    203   }
    204   MojoResult result =
    205       MojoReadData(mojo_handle, buffer_start, &buffer_size, flags);
    206   if (result < 0) {
    207     return result;
    208   }
    209   return buffer_size;
    210 }
    211 
    212 static jobject BeginReadData(JNIEnv* env,
    213                              jobject jcaller,
    214                              jint mojo_handle,
    215                              jint num_bytes,
    216                              jint flags) {
    217   void const* buffer = 0;
    218   uint32_t buffer_size = num_bytes;
    219   MojoResult result =
    220       MojoBeginReadData(mojo_handle, &buffer, &buffer_size, flags);
    221   jobject byte_buffer = 0;
    222   if (result == MOJO_RESULT_OK) {
    223     byte_buffer =
    224         env->NewDirectByteBuffer(const_cast<void*>(buffer), buffer_size);
    225   }
    226   return Java_CoreImpl_newNativeCodeAndBufferResult(env, result, byte_buffer)
    227       .Release();
    228 }
    229 
    230 static jint EndReadData(JNIEnv* env,
    231                         jobject jcaller,
    232                         jint mojo_handle,
    233                         jint num_bytes_read) {
    234   return MojoEndReadData(mojo_handle, num_bytes_read);
    235 }
    236 
    237 static jint WriteData(JNIEnv* env,
    238                       jobject jcaller,
    239                       jint mojo_handle,
    240                       jobject elements,
    241                       jint limit,
    242                       jint flags) {
    243   void* buffer_start = env->GetDirectBufferAddress(elements);
    244   DCHECK(buffer_start);
    245   DCHECK(limit <= env->GetDirectBufferCapacity(elements));
    246   uint32_t buffer_size = limit;
    247   MojoResult result =
    248       MojoWriteData(mojo_handle, buffer_start, &buffer_size, flags);
    249   if (result < 0) {
    250     return result;
    251   }
    252   return buffer_size;
    253 }
    254 
    255 static jobject BeginWriteData(JNIEnv* env,
    256                               jobject jcaller,
    257                               jint mojo_handle,
    258                               jint num_bytes,
    259                               jint flags) {
    260   void* buffer = 0;
    261   uint32_t buffer_size = num_bytes;
    262   MojoResult result =
    263       MojoBeginWriteData(mojo_handle, &buffer, &buffer_size, flags);
    264   jobject byte_buffer = 0;
    265   if (result == MOJO_RESULT_OK) {
    266     byte_buffer = env->NewDirectByteBuffer(buffer, buffer_size);
    267   }
    268   return Java_CoreImpl_newNativeCodeAndBufferResult(env, result, byte_buffer)
    269       .Release();
    270 }
    271 
    272 static jint EndWriteData(JNIEnv* env,
    273                          jobject jcaller,
    274                          jint mojo_handle,
    275                          jint num_bytes_written) {
    276   return MojoEndWriteData(mojo_handle, num_bytes_written);
    277 }
    278 
    279 static jobject Duplicate(JNIEnv* env,
    280                          jobject jcaller,
    281                          jint mojo_handle,
    282                          jobject options_buffer) {
    283   const MojoDuplicateBufferHandleOptions* options = 0;
    284   if (options_buffer) {
    285     const void* buffer_start = env->GetDirectBufferAddress(options_buffer);
    286     DCHECK(buffer_start);
    287     const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer);
    288     DCHECK_EQ(buffer_size, sizeof(MojoDuplicateBufferHandleOptions));
    289     options =
    290         static_cast<const MojoDuplicateBufferHandleOptions*>(buffer_start);
    291     DCHECK_EQ(options->struct_size, buffer_size);
    292   }
    293   MojoHandle handle;
    294   MojoResult result = MojoDuplicateBufferHandle(mojo_handle, options, &handle);
    295   return Java_CoreImpl_newNativeCreationResult(env, result, handle, 0)
    296       .Release();
    297 }
    298 
    299 static jobject Map(JNIEnv* env,
    300                    jobject jcaller,
    301                    jint mojo_handle,
    302                    jlong offset,
    303                    jlong num_bytes,
    304                    jint flags) {
    305   void* buffer = 0;
    306   MojoResult result =
    307       MojoMapBuffer(mojo_handle, offset, num_bytes, &buffer, flags);
    308   jobject byte_buffer = 0;
    309   if (result == MOJO_RESULT_OK) {
    310     byte_buffer = env->NewDirectByteBuffer(buffer, num_bytes);
    311   }
    312   return Java_CoreImpl_newNativeCodeAndBufferResult(env, result, byte_buffer)
    313       .Release();
    314 }
    315 
    316 static int Unmap(JNIEnv* env, jobject jcaller, jobject buffer) {
    317   void* buffer_start = env->GetDirectBufferAddress(buffer);
    318   DCHECK(buffer_start);
    319   return MojoUnmapBuffer(buffer_start);
    320 }
    321 
    322 static jobject AsyncWait(JNIEnv* env,
    323                          jobject jcaller,
    324                          jint mojo_handle,
    325                          jint signals,
    326                          jlong deadline,
    327                          jobject callback) {
    328   AsyncWaitCallbackData* callback_data =
    329       new AsyncWaitCallbackData(env, jcaller, callback);
    330   MojoAsyncWaitID cancel_id;
    331   if (static_cast<MojoHandle>(mojo_handle) != MOJO_HANDLE_INVALID) {
    332     cancel_id = mojo::Environment::GetDefaultAsyncWaiter()->AsyncWait(
    333         mojo_handle, signals, deadline, AsyncWaitCallback, callback_data);
    334   } else {
    335     cancel_id = kInvalidHandleCancelID;
    336     base::MessageLoop::current()->PostTask(
    337         FROM_HERE,
    338         base::Bind(
    339             &AsyncWaitCallback, callback_data, MOJO_RESULT_INVALID_ARGUMENT));
    340   }
    341   base::android::ScopedJavaLocalRef<jobject> cancellable =
    342       Java_CoreImpl_newAsyncWaiterCancellableImpl(
    343           env, jcaller, cancel_id, reinterpret_cast<intptr_t>(callback_data));
    344   callback_data->cancellable.Reset(env, cancellable.obj());
    345   return cancellable.Release();
    346 }
    347 
    348 static void CancelAsyncWait(JNIEnv* env,
    349                             jobject jcaller,
    350                             jlong id,
    351                             jlong data_ptr) {
    352   if (id == 0) {
    353     // If |id| is |kInvalidHandleCancelID|, the async wait was done on an
    354     // invalid handle, so the AsyncWaitCallback will be called and will clear
    355     // the data_ptr.
    356     return;
    357   }
    358   scoped_ptr<AsyncWaitCallbackData> deleter(
    359       reinterpret_cast<AsyncWaitCallbackData*>(data_ptr));
    360   mojo::Environment::GetDefaultAsyncWaiter()->CancelWait(id);
    361 }
    362 
    363 bool RegisterCoreImpl(JNIEnv* env) {
    364   return RegisterNativesImpl(env);
    365 }
    366 
    367 }  // namespace android
    368 }  // namespace mojo
    369