• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
AsyncWaitCallbackData__anon6ca7b7c10111::AsyncWaitCallbackData35   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 
AsyncWaitCallback(mojo::common::HandleWatcher * watcher,void * data,MojoResult result)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 
GetTimeTicksNow(JNIEnv * env,const JavaParamRef<jobject> & jcaller)60 static jlong GetTimeTicksNow(JNIEnv* env,
61                              const JavaParamRef<jobject>& jcaller) {
62   return MojoGetTimeTicksNow();
63 }
64 
WaitMany(JNIEnv * env,const JavaParamRef<jobject> & jcaller,const JavaParamRef<jobject> & buffer,jlong deadline)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 
CreateMessagePipe(JNIEnv * env,const JavaParamRef<jobject> & jcaller,const JavaParamRef<jobject> & options_buffer)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 
CreateDataPipe(JNIEnv * env,const JavaParamRef<jobject> & jcaller,const JavaParamRef<jobject> & options_buffer)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 
CreateSharedBuffer(JNIEnv * env,const JavaParamRef<jobject> & jcaller,const JavaParamRef<jobject> & options_buffer,jlong num_bytes)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 
Close(JNIEnv * env,const JavaParamRef<jobject> & jcaller,jint mojo_handle)160 static jint Close(JNIEnv* env,
161                   const JavaParamRef<jobject>& jcaller,
162                   jint mojo_handle) {
163   return MojoClose(mojo_handle);
164 }
165 
Wait(JNIEnv * env,const JavaParamRef<jobject> & jcaller,const JavaParamRef<jobject> & buffer,jint mojo_handle,jint signals,jlong deadline)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 
WriteMessage(JNIEnv * env,const JavaParamRef<jobject> & jcaller,jint mojo_handle,const JavaParamRef<jobject> & bytes,jint num_bytes,const JavaParamRef<jobject> & handles_buffer,jint flags)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 
ReadMessage(JNIEnv * env,const JavaParamRef<jobject> & jcaller,jint mojo_handle,const JavaParamRef<jobject> & bytes,const JavaParamRef<jobject> & handles_buffer,jint flags)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 
ReadData(JNIEnv * env,const JavaParamRef<jobject> & jcaller,jint mojo_handle,const JavaParamRef<jobject> & elements,jint elements_capacity,jint flags)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 
BeginReadData(JNIEnv * env,const JavaParamRef<jobject> & jcaller,jint mojo_handle,jint num_bytes,jint flags)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 
EndReadData(JNIEnv * env,const JavaParamRef<jobject> & jcaller,jint mojo_handle,jint num_bytes_read)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 
WriteData(JNIEnv * env,const JavaParamRef<jobject> & jcaller,jint mojo_handle,const JavaParamRef<jobject> & elements,jint limit,jint flags)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 
BeginWriteData(JNIEnv * env,const JavaParamRef<jobject> & jcaller,jint mojo_handle,jint num_bytes,jint flags)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 
EndWriteData(JNIEnv * env,const JavaParamRef<jobject> & jcaller,jint mojo_handle,jint num_bytes_written)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 
Duplicate(JNIEnv * env,const JavaParamRef<jobject> & jcaller,jint mojo_handle,const JavaParamRef<jobject> & options_buffer)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 
Map(JNIEnv * env,const JavaParamRef<jobject> & jcaller,jint mojo_handle,jlong offset,jlong num_bytes,jint flags)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 
Unmap(JNIEnv * env,const JavaParamRef<jobject> & jcaller,const JavaParamRef<jobject> & buffer)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 
AsyncWait(JNIEnv * env,const JavaParamRef<jobject> & jcaller,jint mojo_handle,jint signals,jlong deadline,const JavaParamRef<jobject> & callback)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 
CancelAsyncWait(JNIEnv * env,const JavaParamRef<jobject> & jcaller,jlong id,jlong data_ptr)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 
GetNativeBufferOffset(JNIEnv * env,const JavaParamRef<jobject> & jcaller,const JavaParamRef<jobject> & buffer,jint alignment)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 
RegisterCoreImpl(JNIEnv * env)425 bool RegisterCoreImpl(JNIEnv* env) {
426   return RegisterNativesImpl(env);
427 }
428 
429 }  // namespace android
430 }  // namespace mojo
431