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 ScopedJavaLocalRef
<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
);
110 static ScopedJavaLocalRef
<jobject
> CreateDataPipe(JNIEnv
* env
,
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
);
125 MojoResult result
= MojoCreateDataPipe(options
, &handle1
, &handle2
);
126 return Java_CoreImpl_newNativeCreationResult(env
, result
, handle1
, handle2
);
129 static ScopedJavaLocalRef
<jobject
> CreateSharedBuffer(JNIEnv
* env
,
131 jobject options_buffer
,
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
);
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
,
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
,
174 jobject handles_buffer
,
176 const void* buffer_start
= 0;
177 uint32_t buffer_size
= 0;
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
) {
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
,
200 jobject handles_buffer
,
202 void* buffer_start
= 0;
203 uint32_t buffer_size
= 0;
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
) {
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
,
223 static ScopedJavaLocalRef
<jobject
> ReadData(JNIEnv
* env
,
227 jint elements_capacity
,
229 void* buffer_start
= 0;
230 uint32_t buffer_size
= elements_capacity
;
232 buffer_start
= env
->GetDirectBufferAddress(elements
);
233 DCHECK(buffer_start
);
234 DCHECK(elements_capacity
<= env
->GetDirectBufferCapacity(elements
));
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
,
247 void const* buffer
= 0;
248 uint32_t buffer_size
= num_bytes
;
250 MojoBeginReadData(mojo_handle
, &buffer
, &buffer_size
, flags
);
251 jobject byte_buffer
= 0;
252 if (result
== MOJO_RESULT_OK
) {
254 env
->NewDirectByteBuffer(const_cast<void*>(buffer
), buffer_size
);
256 return Java_CoreImpl_newResultAndBuffer(env
, result
, byte_buffer
);
259 static jint
EndReadData(JNIEnv
* env
,
262 jint num_bytes_read
) {
263 return MojoEndReadData(mojo_handle
, num_bytes_read
);
266 static ScopedJavaLocalRef
<jobject
> WriteData(JNIEnv
* env
,
272 void* buffer_start
= env
->GetDirectBufferAddress(elements
);
273 DCHECK(buffer_start
);
274 DCHECK(limit
<= env
->GetDirectBufferCapacity(elements
));
275 uint32_t buffer_size
= limit
;
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
,
288 uint32_t buffer_size
= num_bytes
;
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
,
301 jint num_bytes_written
) {
302 return MojoEndWriteData(mojo_handle
, num_bytes_written
);
305 static ScopedJavaLocalRef
<jobject
> Duplicate(JNIEnv
* env
,
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
));
316 static_cast<const MojoDuplicateBufferHandleOptions
*>(buffer_start
);
317 DCHECK_EQ(options
->struct_size
, buffer_size
);
320 MojoResult result
= MojoDuplicateBufferHandle(mojo_handle
, options
, &handle
);
321 return Java_CoreImpl_newResultAndInteger(env
, result
, handle
);
324 static ScopedJavaLocalRef
<jobject
> Map(JNIEnv
* env
,
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
,
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
);
359 cancel_id
= kInvalidHandleCancelID
;
360 base::MessageLoop::current()->PostTask(
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());
372 static void CancelAsyncWait(JNIEnv
* env
,
377 // If |id| is |kInvalidHandleCancelID|, the async wait was done on an
378 // invalid handle, so the AsyncWaitCallback will be called and will clear
382 scoped_ptr
<AsyncWaitCallbackData
> deleter(
383 reinterpret_cast<AsyncWaitCallbackData
*>(data_ptr
));
384 Environment::GetDefaultAsyncWaiter()->CancelWait(id
);
387 static jint
GetNativeBufferOffset(JNIEnv
* env
,
392 reinterpret_cast<uintptr_t>(env
->GetDirectBufferAddress(buffer
)) %
396 return alignment
- offset
;
399 bool RegisterCoreImpl(JNIEnv
* env
) {
400 return RegisterNativesImpl(env
);
403 } // namespace android