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. 4 5 #include "mojo/android/system/core_impl.h" 6 7 #include <stddef.h> 8 #include <stdint.h> 9 10 #include <memory> 11 12 #include "base/android/base_jni_registrar.h" 13 #include "base/android/jni_android.h" 14 #include "base/android/jni_registrar.h" 15 #include "base/android/library_loader/library_loader_hooks.h" 16 #include "base/android/scoped_java_ref.h" 17 #include "base/bind.h" 18 #include "base/location.h" 19 #include "base/single_thread_task_runner.h" 20 #include "base/threading/thread_task_runner_handle.h" 21 #include "jni/CoreImpl_jni.h" 22 #include "mojo/message_pump/handle_watcher.h" 23 #include "mojo/public/c/system/core.h" 24 25 namespace { 26 27 using MojoAsyncWaitID = uintptr_t; 28 const MojoAsyncWaitID kInvalidHandleCancelID = 0; 29 30 struct AsyncWaitCallbackData { 31 base::android::ScopedJavaGlobalRef<jobject> core_impl; 32 base::android::ScopedJavaGlobalRef<jobject> callback; 33 base::android::ScopedJavaGlobalRef<jobject> cancellable; 34 35 AsyncWaitCallbackData(JNIEnv* env, jobject core_impl, jobject callback) { 36 this->core_impl.Reset(env, core_impl); 37 this->callback.Reset(env, callback); 38 } 39 }; 40 41 void AsyncWaitCallback(mojo::common::HandleWatcher* watcher, 42 void* data, 43 MojoResult result) { 44 delete watcher; 45 std::unique_ptr<AsyncWaitCallbackData> callback_data( 46 static_cast<AsyncWaitCallbackData*>(data)); 47 mojo::android::Java_CoreImpl_onAsyncWaitResult( 48 base::android::AttachCurrentThread(), 49 callback_data->core_impl.obj(), 50 result, 51 callback_data->callback.obj(), 52 callback_data->cancellable.obj()); 53 } 54 55 } // namespace 56 57 namespace mojo { 58 namespace android { 59 60 static jlong GetTimeTicksNow(JNIEnv* env, 61 const JavaParamRef<jobject>& jcaller) { 62 return MojoGetTimeTicksNow(); 63 } 64 65 static jint WaitMany(JNIEnv* env, 66 const JavaParamRef<jobject>& jcaller, 67 const JavaParamRef<jobject>& buffer, 68 jlong deadline) { 69 // |buffer| contains, in this order 70 // input: The array of N handles (MojoHandle, 4 bytes each) 71 // input: The array of N signals (MojoHandleSignals, 4 bytes each) 72 // space for output: The array of N handle states (MojoHandleSignalsState, 8 73 // bytes each) 74 // space for output: The result index (uint32_t, 4 bytes) 75 uint8_t* buffer_start = 76 static_cast<uint8_t*>(env->GetDirectBufferAddress(buffer)); 77 DCHECK(buffer_start); 78 DCHECK_EQ(reinterpret_cast<uintptr_t>(buffer_start) % 8, 0u); 79 // Each handle of the input array contributes 4 (MojoHandle) + 4 80 // (MojoHandleSignals) + 8 (MojoHandleSignalsState) = 16 bytes to the size of 81 // the buffer. 82 const size_t size_per_handle = 16; 83 const size_t buffer_size = env->GetDirectBufferCapacity(buffer); 84 DCHECK_EQ((buffer_size - 4) % size_per_handle, 0u); 85 86 const size_t nb_handles = (buffer_size - 4) / size_per_handle; 87 const MojoHandle* handle_start = 88 reinterpret_cast<const MojoHandle*>(buffer_start); 89 const MojoHandleSignals* signals_start = 90 reinterpret_cast<const MojoHandleSignals*>(buffer_start + 4 * nb_handles); 91 MojoHandleSignalsState* states_start = 92 reinterpret_cast<MojoHandleSignalsState*>(buffer_start + 8 * nb_handles); 93 uint32_t* result_index = 94 reinterpret_cast<uint32_t*>(buffer_start + 16 * nb_handles); 95 *result_index = static_cast<uint32_t>(-1); 96 return MojoWaitMany(handle_start, signals_start, nb_handles, deadline, 97 result_index, states_start); 98 } 99 100 static ScopedJavaLocalRef<jobject> CreateMessagePipe( 101 JNIEnv* env, 102 const JavaParamRef<jobject>& jcaller, 103 const JavaParamRef<jobject>& options_buffer) { 104 const MojoCreateMessagePipeOptions* options = NULL; 105 if (options_buffer) { 106 const void* buffer_start = env->GetDirectBufferAddress(options_buffer); 107 DCHECK(buffer_start); 108 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u); 109 const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer); 110 DCHECK_EQ(buffer_size, sizeof(MojoCreateMessagePipeOptions)); 111 options = static_cast<const MojoCreateMessagePipeOptions*>(buffer_start); 112 DCHECK_EQ(options->struct_size, buffer_size); 113 } 114 MojoHandle handle1; 115 MojoHandle handle2; 116 MojoResult result = MojoCreateMessagePipe(options, &handle1, &handle2); 117 return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2); 118 } 119 120 static ScopedJavaLocalRef<jobject> CreateDataPipe( 121 JNIEnv* env, 122 const JavaParamRef<jobject>& jcaller, 123 const JavaParamRef<jobject>& options_buffer) { 124 const MojoCreateDataPipeOptions* options = NULL; 125 if (options_buffer) { 126 const void* buffer_start = env->GetDirectBufferAddress(options_buffer); 127 DCHECK(buffer_start); 128 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u); 129 const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer); 130 DCHECK_EQ(buffer_size, sizeof(MojoCreateDataPipeOptions)); 131 options = static_cast<const MojoCreateDataPipeOptions*>(buffer_start); 132 DCHECK_EQ(options->struct_size, buffer_size); 133 } 134 MojoHandle handle1; 135 MojoHandle handle2; 136 MojoResult result = MojoCreateDataPipe(options, &handle1, &handle2); 137 return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2); 138 } 139 140 static ScopedJavaLocalRef<jobject> CreateSharedBuffer( 141 JNIEnv* env, 142 const JavaParamRef<jobject>& jcaller, 143 const JavaParamRef<jobject>& options_buffer, 144 jlong num_bytes) { 145 const MojoCreateSharedBufferOptions* options = 0; 146 if (options_buffer) { 147 const void* buffer_start = env->GetDirectBufferAddress(options_buffer); 148 DCHECK(buffer_start); 149 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u); 150 const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer); 151 DCHECK_EQ(buffer_size, sizeof(MojoCreateSharedBufferOptions)); 152 options = static_cast<const MojoCreateSharedBufferOptions*>(buffer_start); 153 DCHECK_EQ(options->struct_size, buffer_size); 154 } 155 MojoHandle handle; 156 MojoResult result = MojoCreateSharedBuffer(options, num_bytes, &handle); 157 return Java_CoreImpl_newResultAndInteger(env, result, handle); 158 } 159 160 static jint Close(JNIEnv* env, 161 const JavaParamRef<jobject>& jcaller, 162 jint mojo_handle) { 163 return MojoClose(mojo_handle); 164 } 165 166 static jint Wait(JNIEnv* env, 167 const JavaParamRef<jobject>& jcaller, 168 const JavaParamRef<jobject>& buffer, 169 jint mojo_handle, 170 jint signals, 171 jlong deadline) { 172 // Buffer contains space for the MojoHandleSignalsState 173 void* buffer_start = env->GetDirectBufferAddress(buffer); 174 DCHECK(buffer_start); 175 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u); 176 DCHECK_EQ(sizeof(struct MojoHandleSignalsState), 177 static_cast<size_t>(env->GetDirectBufferCapacity(buffer))); 178 struct MojoHandleSignalsState* signals_state = 179 static_cast<struct MojoHandleSignalsState*>(buffer_start); 180 return MojoWait(mojo_handle, signals, deadline, signals_state); 181 } 182 183 static jint WriteMessage(JNIEnv* env, 184 const JavaParamRef<jobject>& jcaller, 185 jint mojo_handle, 186 const JavaParamRef<jobject>& bytes, 187 jint num_bytes, 188 const JavaParamRef<jobject>& handles_buffer, 189 jint flags) { 190 const void* buffer_start = 0; 191 uint32_t buffer_size = 0; 192 if (bytes) { 193 buffer_start = env->GetDirectBufferAddress(bytes); 194 DCHECK(buffer_start); 195 DCHECK(env->GetDirectBufferCapacity(bytes) >= num_bytes); 196 buffer_size = num_bytes; 197 } 198 const MojoHandle* handles = 0; 199 uint32_t num_handles = 0; 200 if (handles_buffer) { 201 handles = 202 static_cast<MojoHandle*>(env->GetDirectBufferAddress(handles_buffer)); 203 num_handles = env->GetDirectBufferCapacity(handles_buffer) / 4; 204 } 205 // Java code will handle invalidating handles if the write succeeded. 206 return MojoWriteMessage( 207 mojo_handle, buffer_start, buffer_size, handles, num_handles, flags); 208 } 209 210 static ScopedJavaLocalRef<jobject> ReadMessage( 211 JNIEnv* env, 212 const JavaParamRef<jobject>& jcaller, 213 jint mojo_handle, 214 const JavaParamRef<jobject>& bytes, 215 const JavaParamRef<jobject>& handles_buffer, 216 jint flags) { 217 void* buffer_start = 0; 218 uint32_t buffer_size = 0; 219 if (bytes) { 220 buffer_start = env->GetDirectBufferAddress(bytes); 221 DCHECK(buffer_start); 222 buffer_size = env->GetDirectBufferCapacity(bytes); 223 } 224 MojoHandle* handles = 0; 225 uint32_t num_handles = 0; 226 if (handles_buffer) { 227 handles = 228 static_cast<MojoHandle*>(env->GetDirectBufferAddress(handles_buffer)); 229 num_handles = env->GetDirectBufferCapacity(handles_buffer) / 4; 230 } 231 MojoResult result = MojoReadMessage( 232 mojo_handle, buffer_start, &buffer_size, handles, &num_handles, flags); 233 // Jave code will handle taking ownership of any received handle. 234 return Java_CoreImpl_newReadMessageResult(env, result, buffer_size, 235 num_handles); 236 } 237 238 static ScopedJavaLocalRef<jobject> ReadData( 239 JNIEnv* env, 240 const JavaParamRef<jobject>& jcaller, 241 jint mojo_handle, 242 const JavaParamRef<jobject>& elements, 243 jint elements_capacity, 244 jint flags) { 245 void* buffer_start = 0; 246 uint32_t buffer_size = elements_capacity; 247 if (elements) { 248 buffer_start = env->GetDirectBufferAddress(elements); 249 DCHECK(buffer_start); 250 DCHECK(elements_capacity <= env->GetDirectBufferCapacity(elements)); 251 } 252 MojoResult result = 253 MojoReadData(mojo_handle, buffer_start, &buffer_size, flags); 254 return Java_CoreImpl_newResultAndInteger( 255 env, result, (result == MOJO_RESULT_OK) ? buffer_size : 0); 256 } 257 258 static ScopedJavaLocalRef<jobject> BeginReadData( 259 JNIEnv* env, 260 const JavaParamRef<jobject>& jcaller, 261 jint mojo_handle, 262 jint num_bytes, 263 jint flags) { 264 void const* buffer = 0; 265 uint32_t buffer_size = num_bytes; 266 MojoResult result = 267 MojoBeginReadData(mojo_handle, &buffer, &buffer_size, flags); 268 jobject byte_buffer = 0; 269 if (result == MOJO_RESULT_OK) { 270 byte_buffer = 271 env->NewDirectByteBuffer(const_cast<void*>(buffer), buffer_size); 272 } 273 return Java_CoreImpl_newResultAndBuffer(env, result, byte_buffer); 274 } 275 276 static jint EndReadData(JNIEnv* env, 277 const JavaParamRef<jobject>& jcaller, 278 jint mojo_handle, 279 jint num_bytes_read) { 280 return MojoEndReadData(mojo_handle, num_bytes_read); 281 } 282 283 static ScopedJavaLocalRef<jobject> WriteData( 284 JNIEnv* env, 285 const JavaParamRef<jobject>& jcaller, 286 jint mojo_handle, 287 const JavaParamRef<jobject>& elements, 288 jint limit, 289 jint flags) { 290 void* buffer_start = env->GetDirectBufferAddress(elements); 291 DCHECK(buffer_start); 292 DCHECK(limit <= env->GetDirectBufferCapacity(elements)); 293 uint32_t buffer_size = limit; 294 MojoResult result = 295 MojoWriteData(mojo_handle, buffer_start, &buffer_size, flags); 296 return Java_CoreImpl_newResultAndInteger( 297 env, result, (result == MOJO_RESULT_OK) ? buffer_size : 0); 298 } 299 300 static ScopedJavaLocalRef<jobject> BeginWriteData( 301 JNIEnv* env, 302 const JavaParamRef<jobject>& jcaller, 303 jint mojo_handle, 304 jint num_bytes, 305 jint flags) { 306 void* buffer = 0; 307 uint32_t buffer_size = num_bytes; 308 MojoResult result = 309 MojoBeginWriteData(mojo_handle, &buffer, &buffer_size, flags); 310 jobject byte_buffer = 0; 311 if (result == MOJO_RESULT_OK) { 312 byte_buffer = env->NewDirectByteBuffer(buffer, buffer_size); 313 } 314 return Java_CoreImpl_newResultAndBuffer(env, result, byte_buffer); 315 } 316 317 static jint EndWriteData(JNIEnv* env, 318 const JavaParamRef<jobject>& jcaller, 319 jint mojo_handle, 320 jint num_bytes_written) { 321 return MojoEndWriteData(mojo_handle, num_bytes_written); 322 } 323 324 static ScopedJavaLocalRef<jobject> Duplicate( 325 JNIEnv* env, 326 const JavaParamRef<jobject>& jcaller, 327 jint mojo_handle, 328 const JavaParamRef<jobject>& options_buffer) { 329 const MojoDuplicateBufferHandleOptions* options = 0; 330 if (options_buffer) { 331 const void* buffer_start = env->GetDirectBufferAddress(options_buffer); 332 DCHECK(buffer_start); 333 const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer); 334 DCHECK_EQ(buffer_size, sizeof(MojoDuplicateBufferHandleOptions)); 335 options = 336 static_cast<const MojoDuplicateBufferHandleOptions*>(buffer_start); 337 DCHECK_EQ(options->struct_size, buffer_size); 338 } 339 MojoHandle handle; 340 MojoResult result = MojoDuplicateBufferHandle(mojo_handle, options, &handle); 341 return Java_CoreImpl_newResultAndInteger(env, result, handle); 342 } 343 344 static ScopedJavaLocalRef<jobject> Map(JNIEnv* env, 345 const JavaParamRef<jobject>& jcaller, 346 jint mojo_handle, 347 jlong offset, 348 jlong num_bytes, 349 jint flags) { 350 void* buffer = 0; 351 MojoResult result = 352 MojoMapBuffer(mojo_handle, offset, num_bytes, &buffer, flags); 353 jobject byte_buffer = 0; 354 if (result == MOJO_RESULT_OK) { 355 byte_buffer = env->NewDirectByteBuffer(buffer, num_bytes); 356 } 357 return Java_CoreImpl_newResultAndBuffer(env, result, byte_buffer); 358 } 359 360 static int Unmap(JNIEnv* env, 361 const JavaParamRef<jobject>& jcaller, 362 const JavaParamRef<jobject>& buffer) { 363 void* buffer_start = env->GetDirectBufferAddress(buffer); 364 DCHECK(buffer_start); 365 return MojoUnmapBuffer(buffer_start); 366 } 367 368 static ScopedJavaLocalRef<jobject> AsyncWait( 369 JNIEnv* env, 370 const JavaParamRef<jobject>& jcaller, 371 jint mojo_handle, 372 jint signals, 373 jlong deadline, 374 const JavaParamRef<jobject>& callback) { 375 AsyncWaitCallbackData* callback_data = 376 new AsyncWaitCallbackData(env, jcaller, callback); 377 MojoAsyncWaitID cancel_id; 378 if (static_cast<MojoHandle>(mojo_handle) != MOJO_HANDLE_INVALID) { 379 common::HandleWatcher* watcher = new common::HandleWatcher(); 380 cancel_id = reinterpret_cast<MojoAsyncWaitID>(watcher); 381 watcher->Start(Handle(static_cast<MojoHandle>(mojo_handle)), signals, 382 deadline, 383 base::Bind(&AsyncWaitCallback, watcher, callback_data)); 384 } else { 385 cancel_id = kInvalidHandleCancelID; 386 base::ThreadTaskRunnerHandle::Get()->PostTask( 387 FROM_HERE, base::Bind(&AsyncWaitCallback, nullptr, callback_data, 388 MOJO_RESULT_INVALID_ARGUMENT)); 389 } 390 base::android::ScopedJavaLocalRef<jobject> cancellable = 391 Java_CoreImpl_newAsyncWaiterCancellableImpl( 392 env, jcaller, cancel_id, reinterpret_cast<intptr_t>(callback_data)); 393 callback_data->cancellable.Reset(env, cancellable.obj()); 394 return cancellable; 395 } 396 397 static void CancelAsyncWait(JNIEnv* env, 398 const JavaParamRef<jobject>& jcaller, 399 jlong id, 400 jlong data_ptr) { 401 if (id == 0) { 402 // If |id| is |kInvalidHandleCancelID|, the async wait was done on an 403 // invalid handle, so the AsyncWaitCallback will be called and will clear 404 // the data_ptr. 405 return; 406 } 407 std::unique_ptr<AsyncWaitCallbackData> deleter( 408 reinterpret_cast<AsyncWaitCallbackData*>(data_ptr)); 409 delete reinterpret_cast<common::HandleWatcher*>( 410 static_cast<MojoAsyncWaitID>(id)); 411 } 412 413 static jint GetNativeBufferOffset(JNIEnv* env, 414 const JavaParamRef<jobject>& jcaller, 415 const JavaParamRef<jobject>& buffer, 416 jint alignment) { 417 jint offset = 418 reinterpret_cast<uintptr_t>(env->GetDirectBufferAddress(buffer)) % 419 alignment; 420 if (offset == 0) 421 return 0; 422 return alignment - offset; 423 } 424 425 bool RegisterCoreImpl(JNIEnv* env) { 426 return RegisterNativesImpl(env); 427 } 428 429 } // namespace android 430 } // namespace mojo 431