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/memory/scoped_ptr.h"
     14 #include "base/message_loop/message_loop.h"
     15 #include "jni/CoreImpl_jni.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 jlong GetTimeTicksNow(JNIEnv* env, jobject jcaller) {
     53   return MojoGetTimeTicksNow();
     54 }
     55 
     56 static jint WaitMany(JNIEnv* env,
     57                      jobject jcaller,
     58                      jobject buffer,
     59                      jlong deadline) {
     60   // Buffer contains first the list of handles, then the list of signals.
     61   const void* buffer_start = env->GetDirectBufferAddress(buffer);
     62   DCHECK(buffer_start);
     63   DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u);
     64   const size_t record_size = 8;
     65   const size_t buffer_size = env->GetDirectBufferCapacity(buffer);
     66   DCHECK_EQ(buffer_size % record_size, 0u);
     67 
     68   const size_t nb_handles = buffer_size / record_size;
     69   const MojoHandle* handle_start = static_cast<const MojoHandle*>(buffer_start);
     70   const MojoHandleSignals* signals_start =
     71       static_cast<const MojoHandleSignals*>(handle_start + nb_handles);
     72   return MojoWaitMany(handle_start, signals_start, nb_handles, deadline);
     73 }
     74 
     75 static jobject CreateMessagePipe(JNIEnv* env,
     76                                  jobject jcaller,
     77                                  jobject options_buffer) {
     78   const MojoCreateMessagePipeOptions* options = NULL;
     79   if (options_buffer) {
     80     const void* buffer_start = env->GetDirectBufferAddress(options_buffer);
     81     DCHECK(buffer_start);
     82     DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u);
     83     const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer);
     84     DCHECK_EQ(buffer_size, sizeof(MojoCreateMessagePipeOptions));
     85     options = static_cast<const MojoCreateMessagePipeOptions*>(buffer_start);
     86     DCHECK_EQ(options->struct_size, buffer_size);
     87   }
     88   MojoHandle handle1;
     89   MojoHandle handle2;
     90   MojoResult result = MojoCreateMessagePipe(options, &handle1, &handle2);
     91   return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2)
     92       .Release();
     93 }
     94 
     95 static jobject CreateDataPipe(JNIEnv* env,
     96                               jobject jcaller,
     97                               jobject options_buffer) {
     98   const MojoCreateDataPipeOptions* options = NULL;
     99   if (options_buffer) {
    100     const void* buffer_start = env->GetDirectBufferAddress(options_buffer);
    101     DCHECK(buffer_start);
    102     DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u);
    103     const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer);
    104     DCHECK_EQ(buffer_size, sizeof(MojoCreateDataPipeOptions));
    105     options = static_cast<const MojoCreateDataPipeOptions*>(buffer_start);
    106     DCHECK_EQ(options->struct_size, buffer_size);
    107   }
    108   MojoHandle handle1;
    109   MojoHandle handle2;
    110   MojoResult result = MojoCreateDataPipe(options, &handle1, &handle2);
    111   return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2)
    112       .Release();
    113 }
    114 
    115 static jobject CreateSharedBuffer(JNIEnv* env,
    116                                   jobject jcaller,
    117                                   jobject options_buffer,
    118                                   jlong num_bytes) {
    119   const MojoCreateSharedBufferOptions* options = 0;
    120   if (options_buffer) {
    121     const void* buffer_start = env->GetDirectBufferAddress(options_buffer);
    122     DCHECK(buffer_start);
    123     DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u);
    124     const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer);
    125     DCHECK_EQ(buffer_size, sizeof(MojoCreateSharedBufferOptions));
    126     options = static_cast<const MojoCreateSharedBufferOptions*>(buffer_start);
    127     DCHECK_EQ(options->struct_size, buffer_size);
    128   }
    129   MojoHandle handle;
    130   MojoResult result = MojoCreateSharedBuffer(options, num_bytes, &handle);
    131   return Java_CoreImpl_newNativeCreationResult(env, result, handle, 0)
    132       .Release();
    133 }
    134 
    135 static jint Close(JNIEnv* env, jobject jcaller, jint mojo_handle) {
    136   return MojoClose(mojo_handle);
    137 }
    138 
    139 static jint Wait(JNIEnv* env,
    140                  jobject jcaller,
    141                  jint mojo_handle,
    142                  jint signals,
    143                  jlong deadline) {
    144   return MojoWait(mojo_handle, signals, deadline);
    145 }
    146 
    147 static jint WriteMessage(JNIEnv* env,
    148                          jobject jcaller,
    149                          jint mojo_handle,
    150                          jobject bytes,
    151                          jint num_bytes,
    152                          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 jobject ReadMessage(JNIEnv* env,
    175                            jobject jcaller,
    176                            jint mojo_handle,
    177                            jobject bytes,
    178                            jobject handles_buffer,
    179                            jint flags) {
    180   void* buffer_start = 0;
    181   uint32_t buffer_size = 0;
    182   if (bytes) {
    183     buffer_start = env->GetDirectBufferAddress(bytes);
    184     DCHECK(buffer_start);
    185     buffer_size = env->GetDirectBufferCapacity(bytes);
    186   }
    187   MojoHandle* handles = 0;
    188   uint32_t num_handles = 0;
    189   if (handles_buffer) {
    190     handles =
    191         static_cast<MojoHandle*>(env->GetDirectBufferAddress(handles_buffer));
    192     num_handles = env->GetDirectBufferCapacity(handles_buffer) / 4;
    193   }
    194   MojoResult result = MojoReadMessage(
    195       mojo_handle, buffer_start, &buffer_size, handles, &num_handles, flags);
    196   // Jave code will handle taking ownership of any received handle.
    197   return Java_CoreImpl_newReadMessageResult(
    198              env, result, buffer_size, num_handles).Release();
    199 }
    200 
    201 static jint ReadData(JNIEnv* env,
    202                      jobject jcaller,
    203                      jint mojo_handle,
    204                      jobject elements,
    205                      jint elements_capacity,
    206                      jint flags) {
    207   void* buffer_start = 0;
    208   uint32_t buffer_size = elements_capacity;
    209   if (elements) {
    210     buffer_start = env->GetDirectBufferAddress(elements);
    211     DCHECK(buffer_start);
    212     DCHECK(elements_capacity <= env->GetDirectBufferCapacity(elements));
    213   }
    214   MojoResult result =
    215       MojoReadData(mojo_handle, buffer_start, &buffer_size, flags);
    216   if (result < 0) {
    217     return result;
    218   }
    219   return buffer_size;
    220 }
    221 
    222 static jobject BeginReadData(JNIEnv* env,
    223                              jobject jcaller,
    224                              jint mojo_handle,
    225                              jint num_bytes,
    226                              jint flags) {
    227   void const* buffer = 0;
    228   uint32_t buffer_size = num_bytes;
    229   MojoResult result =
    230       MojoBeginReadData(mojo_handle, &buffer, &buffer_size, flags);
    231   jobject byte_buffer = 0;
    232   if (result == MOJO_RESULT_OK) {
    233     byte_buffer =
    234         env->NewDirectByteBuffer(const_cast<void*>(buffer), buffer_size);
    235   }
    236   return Java_CoreImpl_newNativeCodeAndBufferResult(env, result, byte_buffer)
    237       .Release();
    238 }
    239 
    240 static jint EndReadData(JNIEnv* env,
    241                         jobject jcaller,
    242                         jint mojo_handle,
    243                         jint num_bytes_read) {
    244   return MojoEndReadData(mojo_handle, num_bytes_read);
    245 }
    246 
    247 static jint WriteData(JNIEnv* env,
    248                       jobject jcaller,
    249                       jint mojo_handle,
    250                       jobject elements,
    251                       jint limit,
    252                       jint flags) {
    253   void* buffer_start = env->GetDirectBufferAddress(elements);
    254   DCHECK(buffer_start);
    255   DCHECK(limit <= env->GetDirectBufferCapacity(elements));
    256   uint32_t buffer_size = limit;
    257   MojoResult result =
    258       MojoWriteData(mojo_handle, buffer_start, &buffer_size, flags);
    259   if (result < 0) {
    260     return result;
    261   }
    262   return buffer_size;
    263 }
    264 
    265 static jobject BeginWriteData(JNIEnv* env,
    266                               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_newNativeCodeAndBufferResult(env, result, byte_buffer)
    279       .Release();
    280 }
    281 
    282 static jint EndWriteData(JNIEnv* env,
    283                          jobject jcaller,
    284                          jint mojo_handle,
    285                          jint num_bytes_written) {
    286   return MojoEndWriteData(mojo_handle, num_bytes_written);
    287 }
    288 
    289 static jobject Duplicate(JNIEnv* env,
    290                          jobject jcaller,
    291                          jint mojo_handle,
    292                          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_newNativeCreationResult(env, result, handle, 0)
    306       .Release();
    307 }
    308 
    309 static jobject Map(JNIEnv* env,
    310                    jobject jcaller,
    311                    jint mojo_handle,
    312                    jlong offset,
    313                    jlong num_bytes,
    314                    jint flags) {
    315   void* buffer = 0;
    316   MojoResult result =
    317       MojoMapBuffer(mojo_handle, offset, num_bytes, &buffer, flags);
    318   jobject byte_buffer = 0;
    319   if (result == MOJO_RESULT_OK) {
    320     byte_buffer = env->NewDirectByteBuffer(buffer, num_bytes);
    321   }
    322   return Java_CoreImpl_newNativeCodeAndBufferResult(env, result, byte_buffer)
    323       .Release();
    324 }
    325 
    326 static int Unmap(JNIEnv* env, jobject jcaller, jobject buffer) {
    327   void* buffer_start = env->GetDirectBufferAddress(buffer);
    328   DCHECK(buffer_start);
    329   return MojoUnmapBuffer(buffer_start);
    330 }
    331 
    332 static jobject AsyncWait(JNIEnv* env,
    333                          jobject jcaller,
    334                          jint mojo_handle,
    335                          jint signals,
    336                          jlong deadline,
    337                          jobject callback) {
    338   AsyncWaitCallbackData* callback_data =
    339       new AsyncWaitCallbackData(env, jcaller, callback);
    340   MojoAsyncWaitID cancel_id;
    341   if (static_cast<MojoHandle>(mojo_handle) != MOJO_HANDLE_INVALID) {
    342     cancel_id = Environment::GetDefaultAsyncWaiter()->AsyncWait(
    343         mojo_handle, signals, deadline, AsyncWaitCallback, callback_data);
    344   } else {
    345     cancel_id = kInvalidHandleCancelID;
    346     base::MessageLoop::current()->PostTask(
    347         FROM_HERE,
    348         base::Bind(
    349             &AsyncWaitCallback, callback_data, MOJO_RESULT_INVALID_ARGUMENT));
    350   }
    351   base::android::ScopedJavaLocalRef<jobject> cancellable =
    352       Java_CoreImpl_newAsyncWaiterCancellableImpl(
    353           env, jcaller, cancel_id, reinterpret_cast<intptr_t>(callback_data));
    354   callback_data->cancellable.Reset(env, cancellable.obj());
    355   return cancellable.Release();
    356 }
    357 
    358 static void CancelAsyncWait(JNIEnv* env,
    359                             jobject jcaller,
    360                             jlong id,
    361                             jlong data_ptr) {
    362   if (id == 0) {
    363     // If |id| is |kInvalidHandleCancelID|, the async wait was done on an
    364     // invalid handle, so the AsyncWaitCallback will be called and will clear
    365     // the data_ptr.
    366     return;
    367   }
    368   scoped_ptr<AsyncWaitCallbackData> deleter(
    369       reinterpret_cast<AsyncWaitCallbackData*>(data_ptr));
    370   Environment::GetDefaultAsyncWaiter()->CancelWait(id);
    371 }
    372 
    373 bool RegisterCoreImpl(JNIEnv* env) {
    374   return RegisterNativesImpl(env);
    375 }
    376 
    377 }  // namespace android
    378 }  // namespace mojo
    379