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"
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 jlong
GetTimeTicksNow(JNIEnv
* env
, jobject jcaller
) {
53 return MojoGetTimeTicksNow();
56 static jint
WaitMany(JNIEnv
* env
,
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
65 // space for output: The result index (uint32_t, 4 bytes)
66 uint8_t* buffer_start
=
67 static_cast<uint8_t*>(env
->GetDirectBufferAddress(buffer
));
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
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 jobject
CreateMessagePipe(JNIEnv
* env
,
93 jobject options_buffer
) {
94 const MojoCreateMessagePipeOptions
* options
= NULL
;
96 const void* buffer_start
= env
->GetDirectBufferAddress(options_buffer
);
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
);
106 MojoResult result
= MojoCreateMessagePipe(options
, &handle1
, &handle2
);
107 return Java_CoreImpl_newNativeCreationResult(env
, result
, handle1
, handle2
)
111 static jobject
CreateDataPipe(JNIEnv
* env
,
113 jobject options_buffer
) {
114 const MojoCreateDataPipeOptions
* options
= NULL
;
115 if (options_buffer
) {
116 const void* buffer_start
= env
->GetDirectBufferAddress(options_buffer
);
117 DCHECK(buffer_start
);
118 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start
) % 8, 0u);
119 const size_t buffer_size
= env
->GetDirectBufferCapacity(options_buffer
);
120 DCHECK_EQ(buffer_size
, sizeof(MojoCreateDataPipeOptions
));
121 options
= static_cast<const MojoCreateDataPipeOptions
*>(buffer_start
);
122 DCHECK_EQ(options
->struct_size
, buffer_size
);
126 MojoResult result
= MojoCreateDataPipe(options
, &handle1
, &handle2
);
127 return Java_CoreImpl_newNativeCreationResult(env
, result
, handle1
, handle2
)
131 static jobject
CreateSharedBuffer(JNIEnv
* env
,
133 jobject options_buffer
,
135 const MojoCreateSharedBufferOptions
* options
= 0;
136 if (options_buffer
) {
137 const void* buffer_start
= env
->GetDirectBufferAddress(options_buffer
);
138 DCHECK(buffer_start
);
139 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start
) % 8, 0u);
140 const size_t buffer_size
= env
->GetDirectBufferCapacity(options_buffer
);
141 DCHECK_EQ(buffer_size
, sizeof(MojoCreateSharedBufferOptions
));
142 options
= static_cast<const MojoCreateSharedBufferOptions
*>(buffer_start
);
143 DCHECK_EQ(options
->struct_size
, buffer_size
);
146 MojoResult result
= MojoCreateSharedBuffer(options
, num_bytes
, &handle
);
147 return Java_CoreImpl_newNativeCreationResult(env
, result
, handle
, 0)
151 static jint
Close(JNIEnv
* env
, jobject jcaller
, jint mojo_handle
) {
152 return MojoClose(mojo_handle
);
155 static jint
Wait(JNIEnv
* env
,
161 // Buffer contains space for the MojoHandleSignalsState
162 void* buffer_start
= env
->GetDirectBufferAddress(buffer
);
163 DCHECK(buffer_start
);
164 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start
) % 8, 0u);
165 DCHECK_EQ(sizeof(struct MojoHandleSignalsState
),
166 static_cast<size_t>(env
->GetDirectBufferCapacity(buffer
)));
167 struct MojoHandleSignalsState
* signals_state
=
168 static_cast<struct MojoHandleSignalsState
*>(buffer_start
);
169 return MojoWait(mojo_handle
, signals
, deadline
, signals_state
);
172 static jint
WriteMessage(JNIEnv
* env
,
177 jobject handles_buffer
,
179 const void* buffer_start
= 0;
180 uint32_t buffer_size
= 0;
182 buffer_start
= env
->GetDirectBufferAddress(bytes
);
183 DCHECK(buffer_start
);
184 DCHECK(env
->GetDirectBufferCapacity(bytes
) >= num_bytes
);
185 buffer_size
= num_bytes
;
187 const MojoHandle
* handles
= 0;
188 uint32_t num_handles
= 0;
189 if (handles_buffer
) {
191 static_cast<MojoHandle
*>(env
->GetDirectBufferAddress(handles_buffer
));
192 num_handles
= env
->GetDirectBufferCapacity(handles_buffer
) / 4;
194 // Java code will handle invalidating handles if the write succeeded.
195 return MojoWriteMessage(
196 mojo_handle
, buffer_start
, buffer_size
, handles
, num_handles
, flags
);
199 static jobject
ReadMessage(JNIEnv
* env
,
203 jobject handles_buffer
,
205 void* buffer_start
= 0;
206 uint32_t buffer_size
= 0;
208 buffer_start
= env
->GetDirectBufferAddress(bytes
);
209 DCHECK(buffer_start
);
210 buffer_size
= env
->GetDirectBufferCapacity(bytes
);
212 MojoHandle
* handles
= 0;
213 uint32_t num_handles
= 0;
214 if (handles_buffer
) {
216 static_cast<MojoHandle
*>(env
->GetDirectBufferAddress(handles_buffer
));
217 num_handles
= env
->GetDirectBufferCapacity(handles_buffer
) / 4;
219 MojoResult result
= MojoReadMessage(
220 mojo_handle
, buffer_start
, &buffer_size
, handles
, &num_handles
, flags
);
221 // Jave code will handle taking ownership of any received handle.
222 return Java_CoreImpl_newReadMessageResult(
223 env
, result
, buffer_size
, num_handles
).Release();
226 static jint
ReadData(JNIEnv
* env
,
230 jint elements_capacity
,
232 void* buffer_start
= 0;
233 uint32_t buffer_size
= elements_capacity
;
235 buffer_start
= env
->GetDirectBufferAddress(elements
);
236 DCHECK(buffer_start
);
237 DCHECK(elements_capacity
<= env
->GetDirectBufferCapacity(elements
));
240 MojoReadData(mojo_handle
, buffer_start
, &buffer_size
, flags
);
247 static jobject
BeginReadData(JNIEnv
* env
,
252 void const* buffer
= 0;
253 uint32_t buffer_size
= num_bytes
;
255 MojoBeginReadData(mojo_handle
, &buffer
, &buffer_size
, flags
);
256 jobject byte_buffer
= 0;
257 if (result
== MOJO_RESULT_OK
) {
259 env
->NewDirectByteBuffer(const_cast<void*>(buffer
), buffer_size
);
261 return Java_CoreImpl_newNativeCodeAndBufferResult(env
, result
, byte_buffer
)
265 static jint
EndReadData(JNIEnv
* env
,
268 jint num_bytes_read
) {
269 return MojoEndReadData(mojo_handle
, num_bytes_read
);
272 static jint
WriteData(JNIEnv
* env
,
278 void* buffer_start
= env
->GetDirectBufferAddress(elements
);
279 DCHECK(buffer_start
);
280 DCHECK(limit
<= env
->GetDirectBufferCapacity(elements
));
281 uint32_t buffer_size
= limit
;
283 MojoWriteData(mojo_handle
, buffer_start
, &buffer_size
, flags
);
290 static jobject
BeginWriteData(JNIEnv
* env
,
296 uint32_t buffer_size
= num_bytes
;
298 MojoBeginWriteData(mojo_handle
, &buffer
, &buffer_size
, flags
);
299 jobject byte_buffer
= 0;
300 if (result
== MOJO_RESULT_OK
) {
301 byte_buffer
= env
->NewDirectByteBuffer(buffer
, buffer_size
);
303 return Java_CoreImpl_newNativeCodeAndBufferResult(env
, result
, byte_buffer
)
307 static jint
EndWriteData(JNIEnv
* env
,
310 jint num_bytes_written
) {
311 return MojoEndWriteData(mojo_handle
, num_bytes_written
);
314 static jobject
Duplicate(JNIEnv
* env
,
317 jobject options_buffer
) {
318 const MojoDuplicateBufferHandleOptions
* options
= 0;
319 if (options_buffer
) {
320 const void* buffer_start
= env
->GetDirectBufferAddress(options_buffer
);
321 DCHECK(buffer_start
);
322 const size_t buffer_size
= env
->GetDirectBufferCapacity(options_buffer
);
323 DCHECK_EQ(buffer_size
, sizeof(MojoDuplicateBufferHandleOptions
));
325 static_cast<const MojoDuplicateBufferHandleOptions
*>(buffer_start
);
326 DCHECK_EQ(options
->struct_size
, buffer_size
);
329 MojoResult result
= MojoDuplicateBufferHandle(mojo_handle
, options
, &handle
);
330 return Java_CoreImpl_newNativeCreationResult(env
, result
, handle
, 0)
334 static jobject
Map(JNIEnv
* env
,
342 MojoMapBuffer(mojo_handle
, offset
, num_bytes
, &buffer
, flags
);
343 jobject byte_buffer
= 0;
344 if (result
== MOJO_RESULT_OK
) {
345 byte_buffer
= env
->NewDirectByteBuffer(buffer
, num_bytes
);
347 return Java_CoreImpl_newNativeCodeAndBufferResult(env
, result
, byte_buffer
)
351 static int Unmap(JNIEnv
* env
, jobject jcaller
, jobject buffer
) {
352 void* buffer_start
= env
->GetDirectBufferAddress(buffer
);
353 DCHECK(buffer_start
);
354 return MojoUnmapBuffer(buffer_start
);
357 static jobject
AsyncWait(JNIEnv
* env
,
363 AsyncWaitCallbackData
* callback_data
=
364 new AsyncWaitCallbackData(env
, jcaller
, callback
);
365 MojoAsyncWaitID cancel_id
;
366 if (static_cast<MojoHandle
>(mojo_handle
) != MOJO_HANDLE_INVALID
) {
367 cancel_id
= Environment::GetDefaultAsyncWaiter()->AsyncWait(
368 mojo_handle
, signals
, deadline
, AsyncWaitCallback
, callback_data
);
370 cancel_id
= kInvalidHandleCancelID
;
371 base::MessageLoop::current()->PostTask(
374 &AsyncWaitCallback
, callback_data
, MOJO_RESULT_INVALID_ARGUMENT
));
376 base::android::ScopedJavaLocalRef
<jobject
> cancellable
=
377 Java_CoreImpl_newAsyncWaiterCancellableImpl(
378 env
, jcaller
, cancel_id
, reinterpret_cast<intptr_t>(callback_data
));
379 callback_data
->cancellable
.Reset(env
, cancellable
.obj());
380 return cancellable
.Release();
383 static void CancelAsyncWait(JNIEnv
* env
,
388 // If |id| is |kInvalidHandleCancelID|, the async wait was done on an
389 // invalid handle, so the AsyncWaitCallback will be called and will clear
393 scoped_ptr
<AsyncWaitCallbackData
> deleter(
394 reinterpret_cast<AsyncWaitCallbackData
*>(data_ptr
));
395 Environment::GetDefaultAsyncWaiter()->CancelWait(id
);
398 bool RegisterCoreImpl(JNIEnv
* env
) {
399 return RegisterNativesImpl(env
);
402 } // namespace android