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_newResultAndInteger(env
, result
, handle
).Release();
150 static jint
Close(JNIEnv
* env
, jobject jcaller
, jint mojo_handle
) {
151 return MojoClose(mojo_handle
);
154 static jint
Wait(JNIEnv
* env
,
160 // Buffer contains space for the MojoHandleSignalsState
161 void* buffer_start
= env
->GetDirectBufferAddress(buffer
);
162 DCHECK(buffer_start
);
163 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start
) % 8, 0u);
164 DCHECK_EQ(sizeof(struct MojoHandleSignalsState
),
165 static_cast<size_t>(env
->GetDirectBufferCapacity(buffer
)));
166 struct MojoHandleSignalsState
* signals_state
=
167 static_cast<struct MojoHandleSignalsState
*>(buffer_start
);
168 return MojoWait(mojo_handle
, signals
, deadline
, signals_state
);
171 static jint
WriteMessage(JNIEnv
* env
,
176 jobject handles_buffer
,
178 const void* buffer_start
= 0;
179 uint32_t buffer_size
= 0;
181 buffer_start
= env
->GetDirectBufferAddress(bytes
);
182 DCHECK(buffer_start
);
183 DCHECK(env
->GetDirectBufferCapacity(bytes
) >= num_bytes
);
184 buffer_size
= num_bytes
;
186 const MojoHandle
* handles
= 0;
187 uint32_t num_handles
= 0;
188 if (handles_buffer
) {
190 static_cast<MojoHandle
*>(env
->GetDirectBufferAddress(handles_buffer
));
191 num_handles
= env
->GetDirectBufferCapacity(handles_buffer
) / 4;
193 // Java code will handle invalidating handles if the write succeeded.
194 return MojoWriteMessage(
195 mojo_handle
, buffer_start
, buffer_size
, handles
, num_handles
, flags
);
198 static jobject
ReadMessage(JNIEnv
* env
,
202 jobject handles_buffer
,
204 void* buffer_start
= 0;
205 uint32_t buffer_size
= 0;
207 buffer_start
= env
->GetDirectBufferAddress(bytes
);
208 DCHECK(buffer_start
);
209 buffer_size
= env
->GetDirectBufferCapacity(bytes
);
211 MojoHandle
* handles
= 0;
212 uint32_t num_handles
= 0;
213 if (handles_buffer
) {
215 static_cast<MojoHandle
*>(env
->GetDirectBufferAddress(handles_buffer
));
216 num_handles
= env
->GetDirectBufferCapacity(handles_buffer
) / 4;
218 MojoResult result
= MojoReadMessage(
219 mojo_handle
, buffer_start
, &buffer_size
, handles
, &num_handles
, flags
);
220 // Jave code will handle taking ownership of any received handle.
221 return Java_CoreImpl_newReadMessageResult(
222 env
, result
, buffer_size
, num_handles
).Release();
225 static jobject
ReadData(JNIEnv
* env
,
229 jint elements_capacity
,
231 void* buffer_start
= 0;
232 uint32_t buffer_size
= elements_capacity
;
234 buffer_start
= env
->GetDirectBufferAddress(elements
);
235 DCHECK(buffer_start
);
236 DCHECK(elements_capacity
<= env
->GetDirectBufferCapacity(elements
));
239 MojoReadData(mojo_handle
, buffer_start
, &buffer_size
, flags
);
240 return Java_CoreImpl_newResultAndInteger(
241 env
, result
, (result
== MOJO_RESULT_OK
) ? buffer_size
: 0)
245 static jobject
BeginReadData(JNIEnv
* env
,
250 void const* buffer
= 0;
251 uint32_t buffer_size
= num_bytes
;
253 MojoBeginReadData(mojo_handle
, &buffer
, &buffer_size
, flags
);
254 jobject byte_buffer
= 0;
255 if (result
== MOJO_RESULT_OK
) {
257 env
->NewDirectByteBuffer(const_cast<void*>(buffer
), buffer_size
);
259 return Java_CoreImpl_newResultAndBuffer(env
, result
, byte_buffer
).Release();
262 static jint
EndReadData(JNIEnv
* env
,
265 jint num_bytes_read
) {
266 return MojoEndReadData(mojo_handle
, num_bytes_read
);
269 static jobject
WriteData(JNIEnv
* env
,
275 void* buffer_start
= env
->GetDirectBufferAddress(elements
);
276 DCHECK(buffer_start
);
277 DCHECK(limit
<= env
->GetDirectBufferCapacity(elements
));
278 uint32_t buffer_size
= limit
;
280 MojoWriteData(mojo_handle
, buffer_start
, &buffer_size
, flags
);
281 return Java_CoreImpl_newResultAndInteger(
282 env
, result
, (result
== MOJO_RESULT_OK
) ? buffer_size
: 0)
286 static jobject
BeginWriteData(JNIEnv
* env
,
292 uint32_t buffer_size
= num_bytes
;
294 MojoBeginWriteData(mojo_handle
, &buffer
, &buffer_size
, flags
);
295 jobject byte_buffer
= 0;
296 if (result
== MOJO_RESULT_OK
) {
297 byte_buffer
= env
->NewDirectByteBuffer(buffer
, buffer_size
);
299 return Java_CoreImpl_newResultAndBuffer(env
, result
, byte_buffer
).Release();
302 static jint
EndWriteData(JNIEnv
* env
,
305 jint num_bytes_written
) {
306 return MojoEndWriteData(mojo_handle
, num_bytes_written
);
309 static jobject
Duplicate(JNIEnv
* env
,
312 jobject options_buffer
) {
313 const MojoDuplicateBufferHandleOptions
* options
= 0;
314 if (options_buffer
) {
315 const void* buffer_start
= env
->GetDirectBufferAddress(options_buffer
);
316 DCHECK(buffer_start
);
317 const size_t buffer_size
= env
->GetDirectBufferCapacity(options_buffer
);
318 DCHECK_EQ(buffer_size
, sizeof(MojoDuplicateBufferHandleOptions
));
320 static_cast<const MojoDuplicateBufferHandleOptions
*>(buffer_start
);
321 DCHECK_EQ(options
->struct_size
, buffer_size
);
324 MojoResult result
= MojoDuplicateBufferHandle(mojo_handle
, options
, &handle
);
325 return Java_CoreImpl_newResultAndInteger(env
, result
, handle
).Release();
328 static jobject
Map(JNIEnv
* env
,
336 MojoMapBuffer(mojo_handle
, offset
, num_bytes
, &buffer
, flags
);
337 jobject byte_buffer
= 0;
338 if (result
== MOJO_RESULT_OK
) {
339 byte_buffer
= env
->NewDirectByteBuffer(buffer
, num_bytes
);
341 return Java_CoreImpl_newResultAndBuffer(env
, result
, byte_buffer
).Release();
344 static int Unmap(JNIEnv
* env
, jobject jcaller
, jobject buffer
) {
345 void* buffer_start
= env
->GetDirectBufferAddress(buffer
);
346 DCHECK(buffer_start
);
347 return MojoUnmapBuffer(buffer_start
);
350 static jobject
AsyncWait(JNIEnv
* env
,
356 AsyncWaitCallbackData
* callback_data
=
357 new AsyncWaitCallbackData(env
, jcaller
, callback
);
358 MojoAsyncWaitID cancel_id
;
359 if (static_cast<MojoHandle
>(mojo_handle
) != MOJO_HANDLE_INVALID
) {
360 cancel_id
= Environment::GetDefaultAsyncWaiter()->AsyncWait(
361 mojo_handle
, signals
, deadline
, AsyncWaitCallback
, callback_data
);
363 cancel_id
= kInvalidHandleCancelID
;
364 base::MessageLoop::current()->PostTask(
367 &AsyncWaitCallback
, callback_data
, MOJO_RESULT_INVALID_ARGUMENT
));
369 base::android::ScopedJavaLocalRef
<jobject
> cancellable
=
370 Java_CoreImpl_newAsyncWaiterCancellableImpl(
371 env
, jcaller
, cancel_id
, reinterpret_cast<intptr_t>(callback_data
));
372 callback_data
->cancellable
.Reset(env
, cancellable
.obj());
373 return cancellable
.Release();
376 static void CancelAsyncWait(JNIEnv
* env
,
381 // If |id| is |kInvalidHandleCancelID|, the async wait was done on an
382 // invalid handle, so the AsyncWaitCallback will be called and will clear
386 scoped_ptr
<AsyncWaitCallbackData
> deleter(
387 reinterpret_cast<AsyncWaitCallbackData
*>(data_ptr
));
388 Environment::GetDefaultAsyncWaiter()->CancelWait(id
);
391 static jint
GetNativeBufferOffset(JNIEnv
* env
,
396 reinterpret_cast<uintptr_t>(env
->GetDirectBufferAddress(buffer
)) %
400 return alignment
- offset
;
403 bool RegisterCoreImpl(JNIEnv
* env
) {
404 return RegisterNativesImpl(env
);
407 } // namespace android