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 "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" 19 20 namespace { 21 22 // |AsyncWait| is guaranteed never to return 0. 23 const MojoAsyncWaitID kInvalidHandleCancelID = 0; 24 25 struct AsyncWaitCallbackData { 26 base::android::ScopedJavaGlobalRef<jobject> core_impl; 27 base::android::ScopedJavaGlobalRef<jobject> callback; 28 base::android::ScopedJavaGlobalRef<jobject> cancellable; 29 30 AsyncWaitCallbackData(JNIEnv* env, jobject core_impl, jobject callback) { 31 this->core_impl.Reset(env, core_impl); 32 this->callback.Reset(env, callback); 33 } 34 }; 35 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()); 45 } 46 47 } // namespace 48 49 namespace mojo { 50 namespace android { 51 52 static jlong GetTimeTicksNow(JNIEnv* env, jobject jcaller) { 53 return MojoGetTimeTicksNow(); 54 } 55 56 static jint WaitMany(JNIEnv* env, 57 jobject jcaller, 58 jobject buffer, 59 jlong deadline) { 60 // Buffer contains first the list of handles, then the list of signals. 61 const void* buffer_start = env->GetDirectBufferAddress(buffer); 62 DCHECK(buffer_start); 63 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u); 64 const size_t record_size = 8; 65 const size_t buffer_size = env->GetDirectBufferCapacity(buffer); 66 DCHECK_EQ(buffer_size % record_size, 0u); 67 68 const size_t nb_handles = buffer_size / record_size; 69 const MojoHandle* handle_start = static_cast<const MojoHandle*>(buffer_start); 70 const MojoHandleSignals* signals_start = 71 static_cast<const MojoHandleSignals*>(handle_start + nb_handles); 72 return MojoWaitMany(handle_start, signals_start, nb_handles, deadline); 73 } 74 75 static jobject CreateMessagePipe(JNIEnv* env, 76 jobject jcaller, 77 jobject options_buffer) { 78 const MojoCreateMessagePipeOptions* options = NULL; 79 if (options_buffer) { 80 const void* buffer_start = env->GetDirectBufferAddress(options_buffer); 81 DCHECK(buffer_start); 82 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u); 83 const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer); 84 DCHECK_EQ(buffer_size, sizeof(MojoCreateMessagePipeOptions)); 85 options = static_cast<const MojoCreateMessagePipeOptions*>(buffer_start); 86 DCHECK_EQ(options->struct_size, buffer_size); 87 } 88 MojoHandle handle1; 89 MojoHandle handle2; 90 MojoResult result = MojoCreateMessagePipe(options, &handle1, &handle2); 91 return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2) 92 .Release(); 93 } 94 95 static jobject CreateDataPipe(JNIEnv* env, 96 jobject jcaller, 97 jobject options_buffer) { 98 const MojoCreateDataPipeOptions* options = NULL; 99 if (options_buffer) { 100 const void* buffer_start = env->GetDirectBufferAddress(options_buffer); 101 DCHECK(buffer_start); 102 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u); 103 const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer); 104 DCHECK_EQ(buffer_size, sizeof(MojoCreateDataPipeOptions)); 105 options = static_cast<const MojoCreateDataPipeOptions*>(buffer_start); 106 DCHECK_EQ(options->struct_size, buffer_size); 107 } 108 MojoHandle handle1; 109 MojoHandle handle2; 110 MojoResult result = MojoCreateDataPipe(options, &handle1, &handle2); 111 return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2) 112 .Release(); 113 } 114 115 static jobject CreateSharedBuffer(JNIEnv* env, 116 jobject jcaller, 117 jobject options_buffer, 118 jlong num_bytes) { 119 const MojoCreateSharedBufferOptions* options = 0; 120 if (options_buffer) { 121 const void* buffer_start = env->GetDirectBufferAddress(options_buffer); 122 DCHECK(buffer_start); 123 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u); 124 const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer); 125 DCHECK_EQ(buffer_size, sizeof(MojoCreateSharedBufferOptions)); 126 options = static_cast<const MojoCreateSharedBufferOptions*>(buffer_start); 127 DCHECK_EQ(options->struct_size, buffer_size); 128 } 129 MojoHandle handle; 130 MojoResult result = MojoCreateSharedBuffer(options, num_bytes, &handle); 131 return Java_CoreImpl_newNativeCreationResult(env, result, handle, 0) 132 .Release(); 133 } 134 135 static jint Close(JNIEnv* env, jobject jcaller, jint mojo_handle) { 136 return MojoClose(mojo_handle); 137 } 138 139 static jint Wait(JNIEnv* env, 140 jobject jcaller, 141 jint mojo_handle, 142 jint signals, 143 jlong deadline) { 144 return MojoWait(mojo_handle, signals, deadline); 145 } 146 147 static jint WriteMessage(JNIEnv* env, 148 jobject jcaller, 149 jint mojo_handle, 150 jobject bytes, 151 jint num_bytes, 152 jobject handles_buffer, 153 jint flags) { 154 const void* buffer_start = 0; 155 uint32_t buffer_size = 0; 156 if (bytes) { 157 buffer_start = env->GetDirectBufferAddress(bytes); 158 DCHECK(buffer_start); 159 DCHECK(env->GetDirectBufferCapacity(bytes) >= num_bytes); 160 buffer_size = num_bytes; 161 } 162 const MojoHandle* handles = 0; 163 uint32_t num_handles = 0; 164 if (handles_buffer) { 165 handles = 166 static_cast<MojoHandle*>(env->GetDirectBufferAddress(handles_buffer)); 167 num_handles = env->GetDirectBufferCapacity(handles_buffer) / 4; 168 } 169 // Java code will handle invalidating handles if the write succeeded. 170 return MojoWriteMessage( 171 mojo_handle, buffer_start, buffer_size, handles, num_handles, flags); 172 } 173 174 static jobject ReadMessage(JNIEnv* env, 175 jobject jcaller, 176 jint mojo_handle, 177 jobject bytes, 178 jobject handles_buffer, 179 jint flags) { 180 void* buffer_start = 0; 181 uint32_t buffer_size = 0; 182 if (bytes) { 183 buffer_start = env->GetDirectBufferAddress(bytes); 184 DCHECK(buffer_start); 185 buffer_size = env->GetDirectBufferCapacity(bytes); 186 } 187 MojoHandle* handles = 0; 188 uint32_t num_handles = 0; 189 if (handles_buffer) { 190 handles = 191 static_cast<MojoHandle*>(env->GetDirectBufferAddress(handles_buffer)); 192 num_handles = env->GetDirectBufferCapacity(handles_buffer) / 4; 193 } 194 MojoResult result = MojoReadMessage( 195 mojo_handle, buffer_start, &buffer_size, handles, &num_handles, flags); 196 // Jave code will handle taking ownership of any received handle. 197 return Java_CoreImpl_newReadMessageResult( 198 env, result, buffer_size, num_handles).Release(); 199 } 200 201 static jint ReadData(JNIEnv* env, 202 jobject jcaller, 203 jint mojo_handle, 204 jobject elements, 205 jint elements_capacity, 206 jint flags) { 207 void* buffer_start = 0; 208 uint32_t buffer_size = elements_capacity; 209 if (elements) { 210 buffer_start = env->GetDirectBufferAddress(elements); 211 DCHECK(buffer_start); 212 DCHECK(elements_capacity <= env->GetDirectBufferCapacity(elements)); 213 } 214 MojoResult result = 215 MojoReadData(mojo_handle, buffer_start, &buffer_size, flags); 216 if (result < 0) { 217 return result; 218 } 219 return buffer_size; 220 } 221 222 static jobject BeginReadData(JNIEnv* env, 223 jobject jcaller, 224 jint mojo_handle, 225 jint num_bytes, 226 jint flags) { 227 void const* buffer = 0; 228 uint32_t buffer_size = num_bytes; 229 MojoResult result = 230 MojoBeginReadData(mojo_handle, &buffer, &buffer_size, flags); 231 jobject byte_buffer = 0; 232 if (result == MOJO_RESULT_OK) { 233 byte_buffer = 234 env->NewDirectByteBuffer(const_cast<void*>(buffer), buffer_size); 235 } 236 return Java_CoreImpl_newNativeCodeAndBufferResult(env, result, byte_buffer) 237 .Release(); 238 } 239 240 static jint EndReadData(JNIEnv* env, 241 jobject jcaller, 242 jint mojo_handle, 243 jint num_bytes_read) { 244 return MojoEndReadData(mojo_handle, num_bytes_read); 245 } 246 247 static jint WriteData(JNIEnv* env, 248 jobject jcaller, 249 jint mojo_handle, 250 jobject elements, 251 jint limit, 252 jint flags) { 253 void* buffer_start = env->GetDirectBufferAddress(elements); 254 DCHECK(buffer_start); 255 DCHECK(limit <= env->GetDirectBufferCapacity(elements)); 256 uint32_t buffer_size = limit; 257 MojoResult result = 258 MojoWriteData(mojo_handle, buffer_start, &buffer_size, flags); 259 if (result < 0) { 260 return result; 261 } 262 return buffer_size; 263 } 264 265 static jobject BeginWriteData(JNIEnv* env, 266 jobject jcaller, 267 jint mojo_handle, 268 jint num_bytes, 269 jint flags) { 270 void* buffer = 0; 271 uint32_t buffer_size = num_bytes; 272 MojoResult result = 273 MojoBeginWriteData(mojo_handle, &buffer, &buffer_size, flags); 274 jobject byte_buffer = 0; 275 if (result == MOJO_RESULT_OK) { 276 byte_buffer = env->NewDirectByteBuffer(buffer, buffer_size); 277 } 278 return Java_CoreImpl_newNativeCodeAndBufferResult(env, result, byte_buffer) 279 .Release(); 280 } 281 282 static jint EndWriteData(JNIEnv* env, 283 jobject jcaller, 284 jint mojo_handle, 285 jint num_bytes_written) { 286 return MojoEndWriteData(mojo_handle, num_bytes_written); 287 } 288 289 static jobject Duplicate(JNIEnv* env, 290 jobject jcaller, 291 jint mojo_handle, 292 jobject options_buffer) { 293 const MojoDuplicateBufferHandleOptions* options = 0; 294 if (options_buffer) { 295 const void* buffer_start = env->GetDirectBufferAddress(options_buffer); 296 DCHECK(buffer_start); 297 const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer); 298 DCHECK_EQ(buffer_size, sizeof(MojoDuplicateBufferHandleOptions)); 299 options = 300 static_cast<const MojoDuplicateBufferHandleOptions*>(buffer_start); 301 DCHECK_EQ(options->struct_size, buffer_size); 302 } 303 MojoHandle handle; 304 MojoResult result = MojoDuplicateBufferHandle(mojo_handle, options, &handle); 305 return Java_CoreImpl_newNativeCreationResult(env, result, handle, 0) 306 .Release(); 307 } 308 309 static jobject Map(JNIEnv* env, 310 jobject jcaller, 311 jint mojo_handle, 312 jlong offset, 313 jlong num_bytes, 314 jint flags) { 315 void* buffer = 0; 316 MojoResult result = 317 MojoMapBuffer(mojo_handle, offset, num_bytes, &buffer, flags); 318 jobject byte_buffer = 0; 319 if (result == MOJO_RESULT_OK) { 320 byte_buffer = env->NewDirectByteBuffer(buffer, num_bytes); 321 } 322 return Java_CoreImpl_newNativeCodeAndBufferResult(env, result, byte_buffer) 323 .Release(); 324 } 325 326 static int Unmap(JNIEnv* env, jobject jcaller, jobject buffer) { 327 void* buffer_start = env->GetDirectBufferAddress(buffer); 328 DCHECK(buffer_start); 329 return MojoUnmapBuffer(buffer_start); 330 } 331 332 static jobject AsyncWait(JNIEnv* env, 333 jobject jcaller, 334 jint mojo_handle, 335 jint signals, 336 jlong deadline, 337 jobject callback) { 338 AsyncWaitCallbackData* callback_data = 339 new AsyncWaitCallbackData(env, jcaller, callback); 340 MojoAsyncWaitID cancel_id; 341 if (static_cast<MojoHandle>(mojo_handle) != MOJO_HANDLE_INVALID) { 342 cancel_id = Environment::GetDefaultAsyncWaiter()->AsyncWait( 343 mojo_handle, signals, deadline, AsyncWaitCallback, callback_data); 344 } else { 345 cancel_id = kInvalidHandleCancelID; 346 base::MessageLoop::current()->PostTask( 347 FROM_HERE, 348 base::Bind( 349 &AsyncWaitCallback, callback_data, MOJO_RESULT_INVALID_ARGUMENT)); 350 } 351 base::android::ScopedJavaLocalRef<jobject> cancellable = 352 Java_CoreImpl_newAsyncWaiterCancellableImpl( 353 env, jcaller, cancel_id, reinterpret_cast<intptr_t>(callback_data)); 354 callback_data->cancellable.Reset(env, cancellable.obj()); 355 return cancellable.Release(); 356 } 357 358 static void CancelAsyncWait(JNIEnv* env, 359 jobject jcaller, 360 jlong id, 361 jlong data_ptr) { 362 if (id == 0) { 363 // If |id| is |kInvalidHandleCancelID|, the async wait was done on an 364 // invalid handle, so the AsyncWaitCallback will be called and will clear 365 // the data_ptr. 366 return; 367 } 368 scoped_ptr<AsyncWaitCallbackData> deleter( 369 reinterpret_cast<AsyncWaitCallbackData*>(data_ptr)); 370 Environment::GetDefaultAsyncWaiter()->CancelWait(id); 371 } 372 373 bool RegisterCoreImpl(JNIEnv* env) { 374 return RegisterNativesImpl(env); 375 } 376 377 } // namespace android 378 } // namespace mojo 379