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