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/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/default_async_waiter.h"
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(),
43 callback_data
->callback
.obj(),
44 callback_data
->cancellable
.obj());
52 static void Constructor(JNIEnv
* env
, jobject jcaller
) {
53 mojo::embedder::Init();
56 static jlong
GetTimeTicksNow(JNIEnv
* env
, jobject jcaller
) {
57 return MojoGetTimeTicksNow();
60 static jint
WaitMany(JNIEnv
* env
,
64 // Buffer contains first the list of handles, then the list of flags.
65 const void* buffer_start
= env
->GetDirectBufferAddress(buffer
);
67 const size_t record_size
= 8;
68 const size_t buffer_size
= env
->GetDirectBufferCapacity(buffer
);
69 DCHECK_EQ(buffer_size
% record_size
, 0u);
71 const size_t nb_handles
= buffer_size
/ record_size
;
72 const MojoHandle
* handle_start
= static_cast<const MojoHandle
*>(buffer_start
);
73 const MojoWaitFlags
* flags_start
=
74 static_cast<const MojoWaitFlags
*>(handle_start
+ nb_handles
);
75 return MojoWaitMany(handle_start
, flags_start
, nb_handles
, deadline
);
78 static jobject
CreateMessagePipe(JNIEnv
* env
, jobject jcaller
) {
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
)
87 static jobject
CreateDataPipe(JNIEnv
* env
,
89 jobject options_buffer
) {
90 const MojoCreateDataPipeOptions
* options
= NULL
;
92 const void* buffer_start
= env
->GetDirectBufferAddress(options_buffer
);
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
);
101 MojoResult result
= MojoCreateDataPipe(options
, &handle1
, &handle2
);
102 return Java_CoreImpl_newNativeCreationResult(env
, result
, handle1
, handle2
)
106 static jobject
CreateSharedBuffer(JNIEnv
* env
,
108 jobject options_buffer
,
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
);
120 MojoResult result
= MojoCreateSharedBuffer(options
, num_bytes
, &handle
);
121 return Java_CoreImpl_newNativeCreationResult(env
, result
, handle
, 0)
125 static jint
Close(JNIEnv
* env
, jobject jcaller
, jint mojo_handle
) {
126 return MojoClose(mojo_handle
);
129 static jint
Wait(JNIEnv
* env
,
134 return MojoWait(mojo_handle
, flags
, deadline
);
137 static jint
WriteMessage(JNIEnv
* env
,
142 jobject handles_buffer
,
144 const void* buffer_start
= 0;
145 uint32_t buffer_size
= 0;
147 buffer_start
= env
->GetDirectBufferAddress(bytes
);
148 DCHECK(buffer_start
);
149 DCHECK(env
->GetDirectBufferCapacity(bytes
) >= num_bytes
);
150 buffer_size
= num_bytes
;
152 const MojoHandle
* handles
= 0;
153 uint32_t num_handles
= 0;
154 if (handles_buffer
) {
156 static_cast<MojoHandle
*>(env
->GetDirectBufferAddress(handles_buffer
));
157 num_handles
= env
->GetDirectBufferCapacity(handles_buffer
) / 4;
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
);
164 static jobject
ReadMessage(JNIEnv
* env
,
168 jobject handles_buffer
,
170 void* buffer_start
= 0;
171 uint32_t buffer_size
= 0;
173 buffer_start
= env
->GetDirectBufferAddress(bytes
);
174 DCHECK(buffer_start
);
175 buffer_size
= env
->GetDirectBufferCapacity(bytes
);
177 MojoHandle
* handles
= 0;
178 uint32_t num_handles
= 0;
179 if (handles_buffer
) {
181 static_cast<MojoHandle
*>(env
->GetDirectBufferAddress(handles_buffer
));
182 num_handles
= env
->GetDirectBufferCapacity(handles_buffer
) / 4;
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();
191 static jint
ReadData(JNIEnv
* env
,
195 jint elements_capacity
,
197 void* buffer_start
= 0;
198 uint32_t buffer_size
= elements_capacity
;
200 buffer_start
= env
->GetDirectBufferAddress(elements
);
201 DCHECK(buffer_start
);
202 DCHECK(elements_capacity
<= env
->GetDirectBufferCapacity(elements
));
205 MojoReadData(mojo_handle
, buffer_start
, &buffer_size
, flags
);
212 static jobject
BeginReadData(JNIEnv
* env
,
217 void const* buffer
= 0;
218 uint32_t buffer_size
= num_bytes
;
220 MojoBeginReadData(mojo_handle
, &buffer
, &buffer_size
, flags
);
221 jobject byte_buffer
= 0;
222 if (result
== MOJO_RESULT_OK
) {
224 env
->NewDirectByteBuffer(const_cast<void*>(buffer
), buffer_size
);
226 return Java_CoreImpl_newNativeCodeAndBufferResult(env
, result
, byte_buffer
)
230 static jint
EndReadData(JNIEnv
* env
,
233 jint num_bytes_read
) {
234 return MojoEndReadData(mojo_handle
, num_bytes_read
);
237 static jint
WriteData(JNIEnv
* env
,
243 void* buffer_start
= env
->GetDirectBufferAddress(elements
);
244 DCHECK(buffer_start
);
245 DCHECK(limit
<= env
->GetDirectBufferCapacity(elements
));
246 uint32_t buffer_size
= limit
;
248 MojoWriteData(mojo_handle
, buffer_start
, &buffer_size
, flags
);
255 static jobject
BeginWriteData(JNIEnv
* env
,
261 uint32_t buffer_size
= num_bytes
;
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
);
268 return Java_CoreImpl_newNativeCodeAndBufferResult(env
, result
, byte_buffer
)
272 static jint
EndWriteData(JNIEnv
* env
,
275 jint num_bytes_written
) {
276 return MojoEndWriteData(mojo_handle
, num_bytes_written
);
279 static jobject
Duplicate(JNIEnv
* env
,
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
));
290 static_cast<const MojoDuplicateBufferHandleOptions
*>(buffer_start
);
291 DCHECK_EQ(options
->struct_size
, buffer_size
);
294 MojoResult result
= MojoDuplicateBufferHandle(mojo_handle
, options
, &handle
);
295 return Java_CoreImpl_newNativeCreationResult(env
, result
, handle
, 0)
299 static jobject
Map(JNIEnv
* env
,
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
);
312 return Java_CoreImpl_newNativeCodeAndBufferResult(env
, result
, byte_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
);
322 static jobject
AsyncWait(JNIEnv
* env
,
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 MojoAsyncWaiter
* async_waiter
= mojo::GetDefaultAsyncWaiter();
333 cancel_id
= async_waiter
->AsyncWait(async_waiter
,
340 cancel_id
= kInvalidHandleCancelID
;
341 base::MessageLoop::current()->PostTask(
344 &AsyncWaitCallback
, callback_data
, MOJO_RESULT_INVALID_ARGUMENT
));
346 base::android::ScopedJavaLocalRef
<jobject
> cancellable
=
347 Java_CoreImpl_newAsyncWaiterCancellableImpl(
348 env
, jcaller
, cancel_id
, reinterpret_cast<intptr_t>(callback_data
));
349 callback_data
->cancellable
.Reset(env
, cancellable
.obj());
350 return cancellable
.Release();
353 static void CancelAsyncWait(JNIEnv
* env
,
358 // If |id| is |kInvalidHandleCancelID|, the async wait was done on an
359 // invalid handle, so the AsyncWaitCallback will be called and will clear
363 scoped_ptr
<AsyncWaitCallbackData
> deleter(
364 reinterpret_cast<AsyncWaitCallbackData
*>(data_ptr
));
365 MojoAsyncWaiter
* async_waiter
= mojo::GetDefaultAsyncWaiter();
366 async_waiter
->CancelWait(async_waiter
, id
);
369 bool RegisterCoreImpl(JNIEnv
* env
) {
370 return RegisterNativesImpl(env
);
373 } // namespace android