Update V8 to version 4.7.19.
[chromium-blink-merge.git] / mojo / android / system / core_impl.cc
blob63191169b884dde7fa0a0f66033ed35fe29879c3
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.
5 #include "mojo/android/system/core_impl.h"
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"
20 namespace {
22 // |AsyncWait| is guaranteed never to return 0.
23 const MojoAsyncWaitID kInvalidHandleCancelID = 0;
25 struct AsyncWaitCallbackData {
26 base::android::ScopedJavaGlobalRef<jobject> core_impl;
27 base::android::ScopedJavaGlobalRef<jobject> callback;
28 base::android::ScopedJavaGlobalRef<jobject> cancellable;
30 AsyncWaitCallbackData(JNIEnv* env, jobject core_impl, jobject callback) {
31 this->core_impl.Reset(env, core_impl);
32 this->callback.Reset(env, callback);
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());
47 } // namespace
49 namespace mojo {
50 namespace android {
52 static jlong GetTimeTicksNow(JNIEnv* env, jobject jcaller) {
53 return MojoGetTimeTicksNow();
56 static jint WaitMany(JNIEnv* env,
57 jobject jcaller,
58 jobject buffer,
59 jlong deadline) {
60 // |buffer| contains, in this order
61 // input: The array of N handles (MojoHandle, 4 bytes each)
62 // input: The array of N signals (MojoHandleSignals, 4 bytes each)
63 // space for output: The array of N handle states (MojoHandleSignalsState, 8
64 // bytes each)
65 // space for output: The result index (uint32_t, 4 bytes)
66 uint8_t* buffer_start =
67 static_cast<uint8_t*>(env->GetDirectBufferAddress(buffer));
68 DCHECK(buffer_start);
69 DCHECK_EQ(reinterpret_cast<uintptr_t>(buffer_start) % 8, 0u);
70 // Each handle of the input array contributes 4 (MojoHandle) + 4
71 // (MojoHandleSignals) + 8 (MojoHandleSignalsState) = 16 bytes to the size of
72 // the buffer.
73 const size_t size_per_handle = 16;
74 const size_t buffer_size = env->GetDirectBufferCapacity(buffer);
75 DCHECK_EQ((buffer_size - 4) % size_per_handle, 0u);
77 const size_t nb_handles = (buffer_size - 4) / size_per_handle;
78 const MojoHandle* handle_start =
79 reinterpret_cast<const MojoHandle*>(buffer_start);
80 const MojoHandleSignals* signals_start =
81 reinterpret_cast<const MojoHandleSignals*>(buffer_start + 4 * nb_handles);
82 MojoHandleSignalsState* states_start =
83 reinterpret_cast<MojoHandleSignalsState*>(buffer_start + 8 * nb_handles);
84 uint32_t* result_index =
85 reinterpret_cast<uint32_t*>(buffer_start + 16 * nb_handles);
86 *result_index = static_cast<uint32_t>(-1);
87 return MojoWaitMany(handle_start, signals_start, nb_handles, deadline,
88 result_index, states_start);
91 static ScopedJavaLocalRef<jobject> CreateMessagePipe(JNIEnv* env,
92 jobject jcaller,
93 jobject options_buffer) {
94 const MojoCreateMessagePipeOptions* options = NULL;
95 if (options_buffer) {
96 const void* buffer_start = env->GetDirectBufferAddress(options_buffer);
97 DCHECK(buffer_start);
98 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u);
99 const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer);
100 DCHECK_EQ(buffer_size, sizeof(MojoCreateMessagePipeOptions));
101 options = static_cast<const MojoCreateMessagePipeOptions*>(buffer_start);
102 DCHECK_EQ(options->struct_size, buffer_size);
104 MojoHandle handle1;
105 MojoHandle handle2;
106 MojoResult result = MojoCreateMessagePipe(options, &handle1, &handle2);
107 return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2);
110 static ScopedJavaLocalRef<jobject> CreateDataPipe(JNIEnv* env,
111 jobject jcaller,
112 jobject options_buffer) {
113 const MojoCreateDataPipeOptions* options = NULL;
114 if (options_buffer) {
115 const void* buffer_start = env->GetDirectBufferAddress(options_buffer);
116 DCHECK(buffer_start);
117 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u);
118 const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer);
119 DCHECK_EQ(buffer_size, sizeof(MojoCreateDataPipeOptions));
120 options = static_cast<const MojoCreateDataPipeOptions*>(buffer_start);
121 DCHECK_EQ(options->struct_size, buffer_size);
123 MojoHandle handle1;
124 MojoHandle handle2;
125 MojoResult result = MojoCreateDataPipe(options, &handle1, &handle2);
126 return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2);
129 static ScopedJavaLocalRef<jobject> CreateSharedBuffer(JNIEnv* env,
130 jobject jcaller,
131 jobject options_buffer,
132 jlong num_bytes) {
133 const MojoCreateSharedBufferOptions* options = 0;
134 if (options_buffer) {
135 const void* buffer_start = env->GetDirectBufferAddress(options_buffer);
136 DCHECK(buffer_start);
137 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u);
138 const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer);
139 DCHECK_EQ(buffer_size, sizeof(MojoCreateSharedBufferOptions));
140 options = static_cast<const MojoCreateSharedBufferOptions*>(buffer_start);
141 DCHECK_EQ(options->struct_size, buffer_size);
143 MojoHandle handle;
144 MojoResult result = MojoCreateSharedBuffer(options, num_bytes, &handle);
145 return Java_CoreImpl_newResultAndInteger(env, result, handle);
148 static jint Close(JNIEnv* env, jobject jcaller, jint mojo_handle) {
149 return MojoClose(mojo_handle);
152 static jint Wait(JNIEnv* env,
153 jobject jcaller,
154 jobject buffer,
155 jint mojo_handle,
156 jint signals,
157 jlong deadline) {
158 // Buffer contains space for the MojoHandleSignalsState
159 void* buffer_start = env->GetDirectBufferAddress(buffer);
160 DCHECK(buffer_start);
161 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u);
162 DCHECK_EQ(sizeof(struct MojoHandleSignalsState),
163 static_cast<size_t>(env->GetDirectBufferCapacity(buffer)));
164 struct MojoHandleSignalsState* signals_state =
165 static_cast<struct MojoHandleSignalsState*>(buffer_start);
166 return MojoWait(mojo_handle, signals, deadline, signals_state);
169 static jint WriteMessage(JNIEnv* env,
170 jobject jcaller,
171 jint mojo_handle,
172 jobject bytes,
173 jint num_bytes,
174 jobject handles_buffer,
175 jint flags) {
176 const void* buffer_start = 0;
177 uint32_t buffer_size = 0;
178 if (bytes) {
179 buffer_start = env->GetDirectBufferAddress(bytes);
180 DCHECK(buffer_start);
181 DCHECK(env->GetDirectBufferCapacity(bytes) >= num_bytes);
182 buffer_size = num_bytes;
184 const MojoHandle* handles = 0;
185 uint32_t num_handles = 0;
186 if (handles_buffer) {
187 handles =
188 static_cast<MojoHandle*>(env->GetDirectBufferAddress(handles_buffer));
189 num_handles = env->GetDirectBufferCapacity(handles_buffer) / 4;
191 // Java code will handle invalidating handles if the write succeeded.
192 return MojoWriteMessage(
193 mojo_handle, buffer_start, buffer_size, handles, num_handles, flags);
196 static ScopedJavaLocalRef<jobject> ReadMessage(JNIEnv* env,
197 jobject jcaller,
198 jint mojo_handle,
199 jobject bytes,
200 jobject handles_buffer,
201 jint flags) {
202 void* buffer_start = 0;
203 uint32_t buffer_size = 0;
204 if (bytes) {
205 buffer_start = env->GetDirectBufferAddress(bytes);
206 DCHECK(buffer_start);
207 buffer_size = env->GetDirectBufferCapacity(bytes);
209 MojoHandle* handles = 0;
210 uint32_t num_handles = 0;
211 if (handles_buffer) {
212 handles =
213 static_cast<MojoHandle*>(env->GetDirectBufferAddress(handles_buffer));
214 num_handles = env->GetDirectBufferCapacity(handles_buffer) / 4;
216 MojoResult result = MojoReadMessage(
217 mojo_handle, buffer_start, &buffer_size, handles, &num_handles, flags);
218 // Jave code will handle taking ownership of any received handle.
219 return Java_CoreImpl_newReadMessageResult(env, result, buffer_size,
220 num_handles);
223 static ScopedJavaLocalRef<jobject> ReadData(JNIEnv* env,
224 jobject jcaller,
225 jint mojo_handle,
226 jobject elements,
227 jint elements_capacity,
228 jint flags) {
229 void* buffer_start = 0;
230 uint32_t buffer_size = elements_capacity;
231 if (elements) {
232 buffer_start = env->GetDirectBufferAddress(elements);
233 DCHECK(buffer_start);
234 DCHECK(elements_capacity <= env->GetDirectBufferCapacity(elements));
236 MojoResult result =
237 MojoReadData(mojo_handle, buffer_start, &buffer_size, flags);
238 return Java_CoreImpl_newResultAndInteger(
239 env, result, (result == MOJO_RESULT_OK) ? buffer_size : 0);
242 static ScopedJavaLocalRef<jobject> BeginReadData(JNIEnv* env,
243 jobject jcaller,
244 jint mojo_handle,
245 jint num_bytes,
246 jint flags) {
247 void const* buffer = 0;
248 uint32_t buffer_size = num_bytes;
249 MojoResult result =
250 MojoBeginReadData(mojo_handle, &buffer, &buffer_size, flags);
251 jobject byte_buffer = 0;
252 if (result == MOJO_RESULT_OK) {
253 byte_buffer =
254 env->NewDirectByteBuffer(const_cast<void*>(buffer), buffer_size);
256 return Java_CoreImpl_newResultAndBuffer(env, result, byte_buffer);
259 static jint EndReadData(JNIEnv* env,
260 jobject jcaller,
261 jint mojo_handle,
262 jint num_bytes_read) {
263 return MojoEndReadData(mojo_handle, num_bytes_read);
266 static ScopedJavaLocalRef<jobject> WriteData(JNIEnv* env,
267 jobject jcaller,
268 jint mojo_handle,
269 jobject elements,
270 jint limit,
271 jint flags) {
272 void* buffer_start = env->GetDirectBufferAddress(elements);
273 DCHECK(buffer_start);
274 DCHECK(limit <= env->GetDirectBufferCapacity(elements));
275 uint32_t buffer_size = limit;
276 MojoResult result =
277 MojoWriteData(mojo_handle, buffer_start, &buffer_size, flags);
278 return Java_CoreImpl_newResultAndInteger(
279 env, result, (result == MOJO_RESULT_OK) ? buffer_size : 0);
282 static ScopedJavaLocalRef<jobject> BeginWriteData(JNIEnv* env,
283 jobject jcaller,
284 jint mojo_handle,
285 jint num_bytes,
286 jint flags) {
287 void* buffer = 0;
288 uint32_t buffer_size = num_bytes;
289 MojoResult result =
290 MojoBeginWriteData(mojo_handle, &buffer, &buffer_size, flags);
291 jobject byte_buffer = 0;
292 if (result == MOJO_RESULT_OK) {
293 byte_buffer = env->NewDirectByteBuffer(buffer, buffer_size);
295 return Java_CoreImpl_newResultAndBuffer(env, result, byte_buffer);
298 static jint EndWriteData(JNIEnv* env,
299 jobject jcaller,
300 jint mojo_handle,
301 jint num_bytes_written) {
302 return MojoEndWriteData(mojo_handle, num_bytes_written);
305 static ScopedJavaLocalRef<jobject> Duplicate(JNIEnv* env,
306 jobject jcaller,
307 jint mojo_handle,
308 jobject options_buffer) {
309 const MojoDuplicateBufferHandleOptions* options = 0;
310 if (options_buffer) {
311 const void* buffer_start = env->GetDirectBufferAddress(options_buffer);
312 DCHECK(buffer_start);
313 const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer);
314 DCHECK_EQ(buffer_size, sizeof(MojoDuplicateBufferHandleOptions));
315 options =
316 static_cast<const MojoDuplicateBufferHandleOptions*>(buffer_start);
317 DCHECK_EQ(options->struct_size, buffer_size);
319 MojoHandle handle;
320 MojoResult result = MojoDuplicateBufferHandle(mojo_handle, options, &handle);
321 return Java_CoreImpl_newResultAndInteger(env, result, handle);
324 static ScopedJavaLocalRef<jobject> Map(JNIEnv* env,
325 jobject jcaller,
326 jint mojo_handle,
327 jlong offset,
328 jlong num_bytes,
329 jint flags) {
330 void* buffer = 0;
331 MojoResult result =
332 MojoMapBuffer(mojo_handle, offset, num_bytes, &buffer, flags);
333 jobject byte_buffer = 0;
334 if (result == MOJO_RESULT_OK) {
335 byte_buffer = env->NewDirectByteBuffer(buffer, num_bytes);
337 return Java_CoreImpl_newResultAndBuffer(env, result, byte_buffer);
340 static int Unmap(JNIEnv* env, jobject jcaller, jobject buffer) {
341 void* buffer_start = env->GetDirectBufferAddress(buffer);
342 DCHECK(buffer_start);
343 return MojoUnmapBuffer(buffer_start);
346 static ScopedJavaLocalRef<jobject> AsyncWait(JNIEnv* env,
347 jobject jcaller,
348 jint mojo_handle,
349 jint signals,
350 jlong deadline,
351 jobject callback) {
352 AsyncWaitCallbackData* callback_data =
353 new AsyncWaitCallbackData(env, jcaller, callback);
354 MojoAsyncWaitID cancel_id;
355 if (static_cast<MojoHandle>(mojo_handle) != MOJO_HANDLE_INVALID) {
356 cancel_id = Environment::GetDefaultAsyncWaiter()->AsyncWait(
357 mojo_handle, signals, deadline, AsyncWaitCallback, callback_data);
358 } else {
359 cancel_id = kInvalidHandleCancelID;
360 base::MessageLoop::current()->PostTask(
361 FROM_HERE,
362 base::Bind(
363 &AsyncWaitCallback, callback_data, MOJO_RESULT_INVALID_ARGUMENT));
365 base::android::ScopedJavaLocalRef<jobject> cancellable =
366 Java_CoreImpl_newAsyncWaiterCancellableImpl(
367 env, jcaller, cancel_id, reinterpret_cast<intptr_t>(callback_data));
368 callback_data->cancellable.Reset(env, cancellable.obj());
369 return cancellable;
372 static void CancelAsyncWait(JNIEnv* env,
373 jobject jcaller,
374 jlong id,
375 jlong data_ptr) {
376 if (id == 0) {
377 // If |id| is |kInvalidHandleCancelID|, the async wait was done on an
378 // invalid handle, so the AsyncWaitCallback will be called and will clear
379 // the data_ptr.
380 return;
382 scoped_ptr<AsyncWaitCallbackData> deleter(
383 reinterpret_cast<AsyncWaitCallbackData*>(data_ptr));
384 Environment::GetDefaultAsyncWaiter()->CancelWait(id);
387 static jint GetNativeBufferOffset(JNIEnv* env,
388 jobject jcaller,
389 jobject buffer,
390 jint alignment) {
391 jint offset =
392 reinterpret_cast<uintptr_t>(env->GetDirectBufferAddress(buffer)) %
393 alignment;
394 if (offset == 0)
395 return 0;
396 return alignment - offset;
399 bool RegisterCoreImpl(JNIEnv* env) {
400 return RegisterNativesImpl(env);
403 } // namespace android
404 } // namespace mojo