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
,
53 const JavaParamRef
<jobject
>& jcaller
) {
54 return MojoGetTimeTicksNow();
57 static jint
WaitMany(JNIEnv
* env
,
58 const JavaParamRef
<jobject
>& jcaller
,
59 const JavaParamRef
<jobject
>& buffer
,
61 // |buffer| contains, in this order
62 // input: The array of N handles (MojoHandle, 4 bytes each)
63 // input: The array of N signals (MojoHandleSignals, 4 bytes each)
64 // space for output: The array of N handle states (MojoHandleSignalsState, 8
66 // space for output: The result index (uint32_t, 4 bytes)
67 uint8_t* buffer_start
=
68 static_cast<uint8_t*>(env
->GetDirectBufferAddress(buffer
));
70 DCHECK_EQ(reinterpret_cast<uintptr_t>(buffer_start
) % 8, 0u);
71 // Each handle of the input array contributes 4 (MojoHandle) + 4
72 // (MojoHandleSignals) + 8 (MojoHandleSignalsState) = 16 bytes to the size of
74 const size_t size_per_handle
= 16;
75 const size_t buffer_size
= env
->GetDirectBufferCapacity(buffer
);
76 DCHECK_EQ((buffer_size
- 4) % size_per_handle
, 0u);
78 const size_t nb_handles
= (buffer_size
- 4) / size_per_handle
;
79 const MojoHandle
* handle_start
=
80 reinterpret_cast<const MojoHandle
*>(buffer_start
);
81 const MojoHandleSignals
* signals_start
=
82 reinterpret_cast<const MojoHandleSignals
*>(buffer_start
+ 4 * nb_handles
);
83 MojoHandleSignalsState
* states_start
=
84 reinterpret_cast<MojoHandleSignalsState
*>(buffer_start
+ 8 * nb_handles
);
85 uint32_t* result_index
=
86 reinterpret_cast<uint32_t*>(buffer_start
+ 16 * nb_handles
);
87 *result_index
= static_cast<uint32_t>(-1);
88 return MojoWaitMany(handle_start
, signals_start
, nb_handles
, deadline
,
89 result_index
, states_start
);
92 static ScopedJavaLocalRef
<jobject
> CreateMessagePipe(
94 const JavaParamRef
<jobject
>& jcaller
,
95 const JavaParamRef
<jobject
>& options_buffer
) {
96 const MojoCreateMessagePipeOptions
* options
= NULL
;
98 const void* buffer_start
= env
->GetDirectBufferAddress(options_buffer
);
100 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start
) % 8, 0u);
101 const size_t buffer_size
= env
->GetDirectBufferCapacity(options_buffer
);
102 DCHECK_EQ(buffer_size
, sizeof(MojoCreateMessagePipeOptions
));
103 options
= static_cast<const MojoCreateMessagePipeOptions
*>(buffer_start
);
104 DCHECK_EQ(options
->struct_size
, buffer_size
);
108 MojoResult result
= MojoCreateMessagePipe(options
, &handle1
, &handle2
);
109 return Java_CoreImpl_newNativeCreationResult(env
, result
, handle1
, handle2
);
112 static ScopedJavaLocalRef
<jobject
> CreateDataPipe(
114 const JavaParamRef
<jobject
>& jcaller
,
115 const JavaParamRef
<jobject
>& options_buffer
) {
116 const MojoCreateDataPipeOptions
* options
= NULL
;
117 if (options_buffer
) {
118 const void* buffer_start
= env
->GetDirectBufferAddress(options_buffer
);
119 DCHECK(buffer_start
);
120 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start
) % 8, 0u);
121 const size_t buffer_size
= env
->GetDirectBufferCapacity(options_buffer
);
122 DCHECK_EQ(buffer_size
, sizeof(MojoCreateDataPipeOptions
));
123 options
= static_cast<const MojoCreateDataPipeOptions
*>(buffer_start
);
124 DCHECK_EQ(options
->struct_size
, buffer_size
);
128 MojoResult result
= MojoCreateDataPipe(options
, &handle1
, &handle2
);
129 return Java_CoreImpl_newNativeCreationResult(env
, result
, handle1
, handle2
);
132 static ScopedJavaLocalRef
<jobject
> CreateSharedBuffer(
134 const JavaParamRef
<jobject
>& jcaller
,
135 const JavaParamRef
<jobject
>& options_buffer
,
137 const MojoCreateSharedBufferOptions
* options
= 0;
138 if (options_buffer
) {
139 const void* buffer_start
= env
->GetDirectBufferAddress(options_buffer
);
140 DCHECK(buffer_start
);
141 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start
) % 8, 0u);
142 const size_t buffer_size
= env
->GetDirectBufferCapacity(options_buffer
);
143 DCHECK_EQ(buffer_size
, sizeof(MojoCreateSharedBufferOptions
));
144 options
= static_cast<const MojoCreateSharedBufferOptions
*>(buffer_start
);
145 DCHECK_EQ(options
->struct_size
, buffer_size
);
148 MojoResult result
= MojoCreateSharedBuffer(options
, num_bytes
, &handle
);
149 return Java_CoreImpl_newResultAndInteger(env
, result
, handle
);
152 static jint
Close(JNIEnv
* env
,
153 const JavaParamRef
<jobject
>& jcaller
,
155 return MojoClose(mojo_handle
);
158 static jint
Wait(JNIEnv
* env
,
159 const JavaParamRef
<jobject
>& jcaller
,
160 const JavaParamRef
<jobject
>& buffer
,
164 // Buffer contains space for the MojoHandleSignalsState
165 void* buffer_start
= env
->GetDirectBufferAddress(buffer
);
166 DCHECK(buffer_start
);
167 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start
) % 8, 0u);
168 DCHECK_EQ(sizeof(struct MojoHandleSignalsState
),
169 static_cast<size_t>(env
->GetDirectBufferCapacity(buffer
)));
170 struct MojoHandleSignalsState
* signals_state
=
171 static_cast<struct MojoHandleSignalsState
*>(buffer_start
);
172 return MojoWait(mojo_handle
, signals
, deadline
, signals_state
);
175 static jint
WriteMessage(JNIEnv
* env
,
176 const JavaParamRef
<jobject
>& jcaller
,
178 const JavaParamRef
<jobject
>& bytes
,
180 const JavaParamRef
<jobject
>& handles_buffer
,
182 const void* buffer_start
= 0;
183 uint32_t buffer_size
= 0;
185 buffer_start
= env
->GetDirectBufferAddress(bytes
);
186 DCHECK(buffer_start
);
187 DCHECK(env
->GetDirectBufferCapacity(bytes
) >= num_bytes
);
188 buffer_size
= num_bytes
;
190 const MojoHandle
* handles
= 0;
191 uint32_t num_handles
= 0;
192 if (handles_buffer
) {
194 static_cast<MojoHandle
*>(env
->GetDirectBufferAddress(handles_buffer
));
195 num_handles
= env
->GetDirectBufferCapacity(handles_buffer
) / 4;
197 // Java code will handle invalidating handles if the write succeeded.
198 return MojoWriteMessage(
199 mojo_handle
, buffer_start
, buffer_size
, handles
, num_handles
, flags
);
202 static ScopedJavaLocalRef
<jobject
> ReadMessage(
204 const JavaParamRef
<jobject
>& jcaller
,
206 const JavaParamRef
<jobject
>& bytes
,
207 const JavaParamRef
<jobject
>& handles_buffer
,
209 void* buffer_start
= 0;
210 uint32_t buffer_size
= 0;
212 buffer_start
= env
->GetDirectBufferAddress(bytes
);
213 DCHECK(buffer_start
);
214 buffer_size
= env
->GetDirectBufferCapacity(bytes
);
216 MojoHandle
* handles
= 0;
217 uint32_t num_handles
= 0;
218 if (handles_buffer
) {
220 static_cast<MojoHandle
*>(env
->GetDirectBufferAddress(handles_buffer
));
221 num_handles
= env
->GetDirectBufferCapacity(handles_buffer
) / 4;
223 MojoResult result
= MojoReadMessage(
224 mojo_handle
, buffer_start
, &buffer_size
, handles
, &num_handles
, flags
);
225 // Jave code will handle taking ownership of any received handle.
226 return Java_CoreImpl_newReadMessageResult(env
, result
, buffer_size
,
230 static ScopedJavaLocalRef
<jobject
> ReadData(
232 const JavaParamRef
<jobject
>& jcaller
,
234 const JavaParamRef
<jobject
>& elements
,
235 jint elements_capacity
,
237 void* buffer_start
= 0;
238 uint32_t buffer_size
= elements_capacity
;
240 buffer_start
= env
->GetDirectBufferAddress(elements
);
241 DCHECK(buffer_start
);
242 DCHECK(elements_capacity
<= env
->GetDirectBufferCapacity(elements
));
245 MojoReadData(mojo_handle
, buffer_start
, &buffer_size
, flags
);
246 return Java_CoreImpl_newResultAndInteger(
247 env
, result
, (result
== MOJO_RESULT_OK
) ? buffer_size
: 0);
250 static ScopedJavaLocalRef
<jobject
> BeginReadData(
252 const JavaParamRef
<jobject
>& jcaller
,
256 void const* buffer
= 0;
257 uint32_t buffer_size
= num_bytes
;
259 MojoBeginReadData(mojo_handle
, &buffer
, &buffer_size
, flags
);
260 jobject byte_buffer
= 0;
261 if (result
== MOJO_RESULT_OK
) {
263 env
->NewDirectByteBuffer(const_cast<void*>(buffer
), buffer_size
);
265 return Java_CoreImpl_newResultAndBuffer(env
, result
, byte_buffer
);
268 static jint
EndReadData(JNIEnv
* env
,
269 const JavaParamRef
<jobject
>& jcaller
,
271 jint num_bytes_read
) {
272 return MojoEndReadData(mojo_handle
, num_bytes_read
);
275 static ScopedJavaLocalRef
<jobject
> WriteData(
277 const JavaParamRef
<jobject
>& jcaller
,
279 const JavaParamRef
<jobject
>& elements
,
282 void* buffer_start
= env
->GetDirectBufferAddress(elements
);
283 DCHECK(buffer_start
);
284 DCHECK(limit
<= env
->GetDirectBufferCapacity(elements
));
285 uint32_t buffer_size
= limit
;
287 MojoWriteData(mojo_handle
, buffer_start
, &buffer_size
, flags
);
288 return Java_CoreImpl_newResultAndInteger(
289 env
, result
, (result
== MOJO_RESULT_OK
) ? buffer_size
: 0);
292 static ScopedJavaLocalRef
<jobject
> BeginWriteData(
294 const JavaParamRef
<jobject
>& jcaller
,
299 uint32_t buffer_size
= num_bytes
;
301 MojoBeginWriteData(mojo_handle
, &buffer
, &buffer_size
, flags
);
302 jobject byte_buffer
= 0;
303 if (result
== MOJO_RESULT_OK
) {
304 byte_buffer
= env
->NewDirectByteBuffer(buffer
, buffer_size
);
306 return Java_CoreImpl_newResultAndBuffer(env
, result
, byte_buffer
);
309 static jint
EndWriteData(JNIEnv
* env
,
310 const JavaParamRef
<jobject
>& jcaller
,
312 jint num_bytes_written
) {
313 return MojoEndWriteData(mojo_handle
, num_bytes_written
);
316 static ScopedJavaLocalRef
<jobject
> Duplicate(
318 const JavaParamRef
<jobject
>& jcaller
,
320 const JavaParamRef
<jobject
>& options_buffer
) {
321 const MojoDuplicateBufferHandleOptions
* options
= 0;
322 if (options_buffer
) {
323 const void* buffer_start
= env
->GetDirectBufferAddress(options_buffer
);
324 DCHECK(buffer_start
);
325 const size_t buffer_size
= env
->GetDirectBufferCapacity(options_buffer
);
326 DCHECK_EQ(buffer_size
, sizeof(MojoDuplicateBufferHandleOptions
));
328 static_cast<const MojoDuplicateBufferHandleOptions
*>(buffer_start
);
329 DCHECK_EQ(options
->struct_size
, buffer_size
);
332 MojoResult result
= MojoDuplicateBufferHandle(mojo_handle
, options
, &handle
);
333 return Java_CoreImpl_newResultAndInteger(env
, result
, handle
);
336 static ScopedJavaLocalRef
<jobject
> Map(JNIEnv
* env
,
337 const JavaParamRef
<jobject
>& jcaller
,
344 MojoMapBuffer(mojo_handle
, offset
, num_bytes
, &buffer
, flags
);
345 jobject byte_buffer
= 0;
346 if (result
== MOJO_RESULT_OK
) {
347 byte_buffer
= env
->NewDirectByteBuffer(buffer
, num_bytes
);
349 return Java_CoreImpl_newResultAndBuffer(env
, result
, byte_buffer
);
352 static int Unmap(JNIEnv
* env
,
353 const JavaParamRef
<jobject
>& jcaller
,
354 const JavaParamRef
<jobject
>& buffer
) {
355 void* buffer_start
= env
->GetDirectBufferAddress(buffer
);
356 DCHECK(buffer_start
);
357 return MojoUnmapBuffer(buffer_start
);
360 static ScopedJavaLocalRef
<jobject
> AsyncWait(
362 const JavaParamRef
<jobject
>& jcaller
,
366 const JavaParamRef
<jobject
>& callback
) {
367 AsyncWaitCallbackData
* callback_data
=
368 new AsyncWaitCallbackData(env
, jcaller
, callback
);
369 MojoAsyncWaitID cancel_id
;
370 if (static_cast<MojoHandle
>(mojo_handle
) != MOJO_HANDLE_INVALID
) {
371 cancel_id
= Environment::GetDefaultAsyncWaiter()->AsyncWait(
372 mojo_handle
, signals
, deadline
, AsyncWaitCallback
, callback_data
);
374 cancel_id
= kInvalidHandleCancelID
;
375 base::MessageLoop::current()->PostTask(
378 &AsyncWaitCallback
, callback_data
, MOJO_RESULT_INVALID_ARGUMENT
));
380 base::android::ScopedJavaLocalRef
<jobject
> cancellable
=
381 Java_CoreImpl_newAsyncWaiterCancellableImpl(
382 env
, jcaller
, cancel_id
, reinterpret_cast<intptr_t>(callback_data
));
383 callback_data
->cancellable
.Reset(env
, cancellable
.obj());
387 static void CancelAsyncWait(JNIEnv
* env
,
388 const JavaParamRef
<jobject
>& jcaller
,
392 // If |id| is |kInvalidHandleCancelID|, the async wait was done on an
393 // invalid handle, so the AsyncWaitCallback will be called and will clear
397 scoped_ptr
<AsyncWaitCallbackData
> deleter(
398 reinterpret_cast<AsyncWaitCallbackData
*>(data_ptr
));
399 Environment::GetDefaultAsyncWaiter()->CancelWait(id
);
402 static jint
GetNativeBufferOffset(JNIEnv
* env
,
403 const JavaParamRef
<jobject
>& jcaller
,
404 const JavaParamRef
<jobject
>& buffer
,
407 reinterpret_cast<uintptr_t>(env
->GetDirectBufferAddress(buffer
)) %
411 return alignment
- offset
;
414 bool RegisterCoreImpl(JNIEnv
* env
) {
415 return RegisterNativesImpl(env
);
418 } // namespace android