Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / mojo / android / system / core_impl.cc
blob0a80e60b1a2909ab5dd757bae669759e34dedc5a
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"
20 namespace {
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(),
42 result,
43 callback_data->callback.obj(),
44 callback_data->cancellable.obj());
47 } // namespace
49 namespace mojo {
50 namespace android {
52 static jlong GetTimeTicksNow(JNIEnv* env, jobject jcaller) {
53 return MojoGetTimeTicksNow();
56 static jint WaitMany(JNIEnv* env,
57 jobject jcaller,
58 jobject buffer,
59 jlong deadline) {
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
64 // bytes each)
65 // space for output: The result index (uint32_t, 4 bytes)
66 uint8_t* buffer_start =
67 static_cast<uint8_t*>(env->GetDirectBufferAddress(buffer));
68 DCHECK(buffer_start);
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
72 // the buffer.
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,
92 jobject jcaller,
93 jobject options_buffer) {
94 const MojoCreateMessagePipeOptions* options = NULL;
95 if (options_buffer) {
96 const void* buffer_start = env->GetDirectBufferAddress(options_buffer);
97 DCHECK(buffer_start);
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);
104 MojoHandle handle1;
105 MojoHandle handle2;
106 MojoResult result = MojoCreateMessagePipe(options, &handle1, &handle2);
107 return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2)
108 .Release();
111 static jobject CreateDataPipe(JNIEnv* env,
112 jobject jcaller,
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);
124 MojoHandle handle1;
125 MojoHandle handle2;
126 MojoResult result = MojoCreateDataPipe(options, &handle1, &handle2);
127 return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2)
128 .Release();
131 static jobject CreateSharedBuffer(JNIEnv* env,
132 jobject jcaller,
133 jobject options_buffer,
134 jlong num_bytes) {
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);
145 MojoHandle handle;
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,
155 jobject jcaller,
156 jobject buffer,
157 jint mojo_handle,
158 jint signals,
159 jlong deadline) {
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,
172 jobject jcaller,
173 jint mojo_handle,
174 jobject bytes,
175 jint num_bytes,
176 jobject handles_buffer,
177 jint flags) {
178 const void* buffer_start = 0;
179 uint32_t buffer_size = 0;
180 if (bytes) {
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) {
189 handles =
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,
199 jobject jcaller,
200 jint mojo_handle,
201 jobject bytes,
202 jobject handles_buffer,
203 jint flags) {
204 void* buffer_start = 0;
205 uint32_t buffer_size = 0;
206 if (bytes) {
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) {
214 handles =
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,
226 jobject jcaller,
227 jint mojo_handle,
228 jobject elements,
229 jint elements_capacity,
230 jint flags) {
231 void* buffer_start = 0;
232 uint32_t buffer_size = elements_capacity;
233 if (elements) {
234 buffer_start = env->GetDirectBufferAddress(elements);
235 DCHECK(buffer_start);
236 DCHECK(elements_capacity <= env->GetDirectBufferCapacity(elements));
238 MojoResult result =
239 MojoReadData(mojo_handle, buffer_start, &buffer_size, flags);
240 return Java_CoreImpl_newResultAndInteger(
241 env, result, (result == MOJO_RESULT_OK) ? buffer_size : 0)
242 .Release();
245 static jobject BeginReadData(JNIEnv* env,
246 jobject jcaller,
247 jint mojo_handle,
248 jint num_bytes,
249 jint flags) {
250 void const* buffer = 0;
251 uint32_t buffer_size = num_bytes;
252 MojoResult result =
253 MojoBeginReadData(mojo_handle, &buffer, &buffer_size, flags);
254 jobject byte_buffer = 0;
255 if (result == MOJO_RESULT_OK) {
256 byte_buffer =
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,
263 jobject jcaller,
264 jint mojo_handle,
265 jint num_bytes_read) {
266 return MojoEndReadData(mojo_handle, num_bytes_read);
269 static jobject WriteData(JNIEnv* env,
270 jobject jcaller,
271 jint mojo_handle,
272 jobject elements,
273 jint limit,
274 jint flags) {
275 void* buffer_start = env->GetDirectBufferAddress(elements);
276 DCHECK(buffer_start);
277 DCHECK(limit <= env->GetDirectBufferCapacity(elements));
278 uint32_t buffer_size = limit;
279 MojoResult result =
280 MojoWriteData(mojo_handle, buffer_start, &buffer_size, flags);
281 return Java_CoreImpl_newResultAndInteger(
282 env, result, (result == MOJO_RESULT_OK) ? buffer_size : 0)
283 .Release();
286 static jobject BeginWriteData(JNIEnv* env,
287 jobject jcaller,
288 jint mojo_handle,
289 jint num_bytes,
290 jint flags) {
291 void* buffer = 0;
292 uint32_t buffer_size = num_bytes;
293 MojoResult result =
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,
303 jobject jcaller,
304 jint mojo_handle,
305 jint num_bytes_written) {
306 return MojoEndWriteData(mojo_handle, num_bytes_written);
309 static jobject Duplicate(JNIEnv* env,
310 jobject jcaller,
311 jint mojo_handle,
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));
319 options =
320 static_cast<const MojoDuplicateBufferHandleOptions*>(buffer_start);
321 DCHECK_EQ(options->struct_size, buffer_size);
323 MojoHandle handle;
324 MojoResult result = MojoDuplicateBufferHandle(mojo_handle, options, &handle);
325 return Java_CoreImpl_newResultAndInteger(env, result, handle).Release();
328 static jobject Map(JNIEnv* env,
329 jobject jcaller,
330 jint mojo_handle,
331 jlong offset,
332 jlong num_bytes,
333 jint flags) {
334 void* buffer = 0;
335 MojoResult result =
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,
351 jobject jcaller,
352 jint mojo_handle,
353 jint signals,
354 jlong deadline,
355 jobject callback) {
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);
362 } else {
363 cancel_id = kInvalidHandleCancelID;
364 base::MessageLoop::current()->PostTask(
365 FROM_HERE,
366 base::Bind(
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,
377 jobject jcaller,
378 jlong id,
379 jlong data_ptr) {
380 if (id == 0) {
381 // If |id| is |kInvalidHandleCancelID|, the async wait was done on an
382 // invalid handle, so the AsyncWaitCallback will be called and will clear
383 // the data_ptr.
384 return;
386 scoped_ptr<AsyncWaitCallbackData> deleter(
387 reinterpret_cast<AsyncWaitCallbackData*>(data_ptr));
388 Environment::GetDefaultAsyncWaiter()->CancelWait(id);
391 static jint GetNativeBufferOffset(JNIEnv* env,
392 jobject jcaller,
393 jobject buffer,
394 jint alignment) {
395 jint offset =
396 reinterpret_cast<uintptr_t>(env->GetDirectBufferAddress(buffer)) %
397 alignment;
398 if (offset == 0)
399 return 0;
400 return alignment - offset;
403 bool RegisterCoreImpl(JNIEnv* env) {
404 return RegisterNativesImpl(env);
407 } // namespace android
408 } // namespace mojo