• 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 "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 
AsyncWaitCallbackData__anon96bcc2850111::AsyncWaitCallbackData30   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 
AsyncWaitCallback(void * data,MojoResult result)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 
Constructor(JNIEnv * env,jobject jcaller)52 static void Constructor(JNIEnv* env, jobject jcaller) {
53   mojo::embedder::Init();
54 }
55 
GetTimeTicksNow(JNIEnv * env,jobject jcaller)56 static jlong GetTimeTicksNow(JNIEnv* env, jobject jcaller) {
57   return MojoGetTimeTicksNow();
58 }
59 
WaitMany(JNIEnv * env,jobject jcaller,jobject buffer,jlong deadline)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 
CreateMessagePipe(JNIEnv * env,jobject jcaller)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 
CreateDataPipe(JNIEnv * env,jobject jcaller,jobject options_buffer)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 
CreateSharedBuffer(JNIEnv * env,jobject jcaller,jobject options_buffer,jlong num_bytes)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 
Close(JNIEnv * env,jobject jcaller,jint mojo_handle)125 static jint Close(JNIEnv* env, jobject jcaller, jint mojo_handle) {
126   return MojoClose(mojo_handle);
127 }
128 
Wait(JNIEnv * env,jobject jcaller,jint mojo_handle,jint signals,jlong deadline)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 
WriteMessage(JNIEnv * env,jobject jcaller,jint mojo_handle,jobject bytes,jint num_bytes,jobject handles_buffer,jint flags)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 
ReadMessage(JNIEnv * env,jobject jcaller,jint mojo_handle,jobject bytes,jobject handles_buffer,jint flags)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 
ReadData(JNIEnv * env,jobject jcaller,jint mojo_handle,jobject elements,jint elements_capacity,jint flags)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 
BeginReadData(JNIEnv * env,jobject jcaller,jint mojo_handle,jint num_bytes,jint flags)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 
EndReadData(JNIEnv * env,jobject jcaller,jint mojo_handle,jint num_bytes_read)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 
WriteData(JNIEnv * env,jobject jcaller,jint mojo_handle,jobject elements,jint limit,jint flags)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 
BeginWriteData(JNIEnv * env,jobject jcaller,jint mojo_handle,jint num_bytes,jint flags)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 
EndWriteData(JNIEnv * env,jobject jcaller,jint mojo_handle,jint num_bytes_written)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 
Duplicate(JNIEnv * env,jobject jcaller,jint mojo_handle,jobject options_buffer)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 
Map(JNIEnv * env,jobject jcaller,jint mojo_handle,jlong offset,jlong num_bytes,jint flags)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 
Unmap(JNIEnv * env,jobject jcaller,jobject buffer)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 
AsyncWait(JNIEnv * env,jobject jcaller,jint mojo_handle,jint signals,jlong deadline,jobject callback)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 
CancelAsyncWait(JNIEnv * env,jobject jcaller,jlong id,jlong data_ptr)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 
RegisterCoreImpl(JNIEnv * env)363 bool RegisterCoreImpl(JNIEnv* env) {
364   return RegisterNativesImpl(env);
365 }
366 
367 }  // namespace android
368 }  // namespace mojo
369