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__anon64426de20111::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