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 "base/android/base_jni_registrar.h" 11 #include "base/android/jni_android.h" 12 #include "base/android/jni_registrar.h" 13 #include "base/android/library_loader/library_loader_hooks.h" 14 #include "base/android/scoped_java_ref.h" 15 #include "jni/CoreImpl_jni.h" 16 #include "mojo/public/c/system/core.h" 17 18 namespace mojo { 19 namespace android { 20 21 using base::android::JavaParamRef; 22 using base::android::ScopedJavaLocalRef; 23 24 static jlong GetTimeTicksNow(JNIEnv* env, 25 const JavaParamRef<jobject>& jcaller) { 26 return MojoGetTimeTicksNow(); 27 } 28 29 static jint WaitMany(JNIEnv* env, 30 const JavaParamRef<jobject>& jcaller, 31 const JavaParamRef<jobject>& buffer, 32 jlong deadline) { 33 // |buffer| contains, in this order 34 // input: The array of N handles (MojoHandle, 4 bytes each) 35 // input: The array of N signals (MojoHandleSignals, 4 bytes each) 36 // space for output: The array of N handle states (MojoHandleSignalsState, 8 37 // bytes each) 38 // space for output: The result index (uint32_t, 4 bytes) 39 uint8_t* buffer_start = 40 static_cast<uint8_t*>(env->GetDirectBufferAddress(buffer)); 41 DCHECK(buffer_start); 42 DCHECK_EQ(reinterpret_cast<uintptr_t>(buffer_start) % 8, 0u); 43 // Each handle of the input array contributes 4 (MojoHandle) + 4 44 // (MojoHandleSignals) + 8 (MojoHandleSignalsState) = 16 bytes to the size of 45 // the buffer. 46 const size_t size_per_handle = 16; 47 const size_t buffer_size = env->GetDirectBufferCapacity(buffer); 48 DCHECK_EQ((buffer_size - 4) % size_per_handle, 0u); 49 50 const size_t nb_handles = (buffer_size - 4) / size_per_handle; 51 const MojoHandle* handle_start = 52 reinterpret_cast<const MojoHandle*>(buffer_start); 53 const MojoHandleSignals* signals_start = 54 reinterpret_cast<const MojoHandleSignals*>(buffer_start + 4 * nb_handles); 55 MojoHandleSignalsState* states_start = 56 reinterpret_cast<MojoHandleSignalsState*>(buffer_start + 8 * nb_handles); 57 uint32_t* result_index = 58 reinterpret_cast<uint32_t*>(buffer_start + 16 * nb_handles); 59 *result_index = static_cast<uint32_t>(-1); 60 return MojoWaitMany(handle_start, signals_start, nb_handles, deadline, 61 result_index, states_start); 62 } 63 64 static ScopedJavaLocalRef<jobject> CreateMessagePipe( 65 JNIEnv* env, 66 const JavaParamRef<jobject>& jcaller, 67 const JavaParamRef<jobject>& options_buffer) { 68 const MojoCreateMessagePipeOptions* options = NULL; 69 if (options_buffer) { 70 const void* buffer_start = env->GetDirectBufferAddress(options_buffer); 71 DCHECK(buffer_start); 72 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u); 73 const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer); 74 DCHECK_EQ(buffer_size, sizeof(MojoCreateMessagePipeOptions)); 75 options = static_cast<const MojoCreateMessagePipeOptions*>(buffer_start); 76 DCHECK_EQ(options->struct_size, buffer_size); 77 } 78 MojoHandle handle1; 79 MojoHandle handle2; 80 MojoResult result = MojoCreateMessagePipe(options, &handle1, &handle2); 81 return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2); 82 } 83 84 static ScopedJavaLocalRef<jobject> CreateDataPipe( 85 JNIEnv* env, 86 const JavaParamRef<jobject>& jcaller, 87 const JavaParamRef<jobject>& options_buffer) { 88 const MojoCreateDataPipeOptions* options = NULL; 89 if (options_buffer) { 90 const void* buffer_start = env->GetDirectBufferAddress(options_buffer); 91 DCHECK(buffer_start); 92 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u); 93 const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer); 94 DCHECK_EQ(buffer_size, sizeof(MojoCreateDataPipeOptions)); 95 options = static_cast<const MojoCreateDataPipeOptions*>(buffer_start); 96 DCHECK_EQ(options->struct_size, buffer_size); 97 } 98 MojoHandle handle1; 99 MojoHandle handle2; 100 MojoResult result = MojoCreateDataPipe(options, &handle1, &handle2); 101 return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2); 102 } 103 104 static ScopedJavaLocalRef<jobject> CreateSharedBuffer( 105 JNIEnv* env, 106 const JavaParamRef<jobject>& jcaller, 107 const JavaParamRef<jobject>& options_buffer, 108 jlong num_bytes) { 109 const MojoCreateSharedBufferOptions* options = 0; 110 if (options_buffer) { 111 const void* buffer_start = env->GetDirectBufferAddress(options_buffer); 112 DCHECK(buffer_start); 113 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u); 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_newResultAndInteger(env, result, handle); 122 } 123 124 static jint Close(JNIEnv* env, 125 const JavaParamRef<jobject>& jcaller, 126 jint mojo_handle) { 127 return MojoClose(mojo_handle); 128 } 129 130 static jint Wait(JNIEnv* env, 131 const JavaParamRef<jobject>& jcaller, 132 const JavaParamRef<jobject>& buffer, 133 jint mojo_handle, 134 jint signals, 135 jlong deadline) { 136 // Buffer contains space for the MojoHandleSignalsState 137 void* buffer_start = env->GetDirectBufferAddress(buffer); 138 DCHECK(buffer_start); 139 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u); 140 DCHECK_EQ(sizeof(struct MojoHandleSignalsState), 141 static_cast<size_t>(env->GetDirectBufferCapacity(buffer))); 142 struct MojoHandleSignalsState* signals_state = 143 static_cast<struct MojoHandleSignalsState*>(buffer_start); 144 return MojoWait(mojo_handle, signals, deadline, signals_state); 145 } 146 147 static jint WriteMessage(JNIEnv* env, 148 const JavaParamRef<jobject>& jcaller, 149 jint mojo_handle, 150 const JavaParamRef<jobject>& bytes, 151 jint num_bytes, 152 const JavaParamRef<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 ScopedJavaLocalRef<jobject> ReadMessage( 175 JNIEnv* env, 176 const JavaParamRef<jobject>& jcaller, 177 jint mojo_handle, 178 const JavaParamRef<jobject>& bytes, 179 const JavaParamRef<jobject>& handles_buffer, 180 jint flags) { 181 void* buffer_start = 0; 182 uint32_t buffer_size = 0; 183 if (bytes) { 184 buffer_start = env->GetDirectBufferAddress(bytes); 185 DCHECK(buffer_start); 186 buffer_size = env->GetDirectBufferCapacity(bytes); 187 } 188 MojoHandle* handles = 0; 189 uint32_t num_handles = 0; 190 if (handles_buffer) { 191 handles = 192 static_cast<MojoHandle*>(env->GetDirectBufferAddress(handles_buffer)); 193 num_handles = env->GetDirectBufferCapacity(handles_buffer) / 4; 194 } 195 MojoResult result = MojoReadMessage( 196 mojo_handle, buffer_start, &buffer_size, handles, &num_handles, flags); 197 // Jave code will handle taking ownership of any received handle. 198 return Java_CoreImpl_newReadMessageResult(env, result, buffer_size, 199 num_handles); 200 } 201 202 static ScopedJavaLocalRef<jobject> ReadData( 203 JNIEnv* env, 204 const JavaParamRef<jobject>& jcaller, 205 jint mojo_handle, 206 const JavaParamRef<jobject>& elements, 207 jint elements_capacity, 208 jint flags) { 209 void* buffer_start = 0; 210 uint32_t buffer_size = elements_capacity; 211 if (elements) { 212 buffer_start = env->GetDirectBufferAddress(elements); 213 DCHECK(buffer_start); 214 DCHECK(elements_capacity <= env->GetDirectBufferCapacity(elements)); 215 } 216 MojoResult result = 217 MojoReadData(mojo_handle, buffer_start, &buffer_size, flags); 218 return Java_CoreImpl_newResultAndInteger( 219 env, result, (result == MOJO_RESULT_OK) ? buffer_size : 0); 220 } 221 222 static ScopedJavaLocalRef<jobject> BeginReadData( 223 JNIEnv* env, 224 const JavaParamRef<jobject>& jcaller, 225 jint mojo_handle, 226 jint num_bytes, 227 jint flags) { 228 void const* buffer = 0; 229 uint32_t buffer_size = num_bytes; 230 MojoResult result = 231 MojoBeginReadData(mojo_handle, &buffer, &buffer_size, flags); 232 jobject byte_buffer = 0; 233 if (result == MOJO_RESULT_OK) { 234 byte_buffer = 235 env->NewDirectByteBuffer(const_cast<void*>(buffer), buffer_size); 236 } 237 return Java_CoreImpl_newResultAndBuffer(env, result, byte_buffer); 238 } 239 240 static jint EndReadData(JNIEnv* env, 241 const JavaParamRef<jobject>& jcaller, 242 jint mojo_handle, 243 jint num_bytes_read) { 244 return MojoEndReadData(mojo_handle, num_bytes_read); 245 } 246 247 static ScopedJavaLocalRef<jobject> WriteData( 248 JNIEnv* env, 249 const JavaParamRef<jobject>& jcaller, 250 jint mojo_handle, 251 const JavaParamRef<jobject>& elements, 252 jint limit, 253 jint flags) { 254 void* buffer_start = env->GetDirectBufferAddress(elements); 255 DCHECK(buffer_start); 256 DCHECK(limit <= env->GetDirectBufferCapacity(elements)); 257 uint32_t buffer_size = limit; 258 MojoResult result = 259 MojoWriteData(mojo_handle, buffer_start, &buffer_size, flags); 260 return Java_CoreImpl_newResultAndInteger( 261 env, result, (result == MOJO_RESULT_OK) ? buffer_size : 0); 262 } 263 264 static ScopedJavaLocalRef<jobject> BeginWriteData( 265 JNIEnv* env, 266 const JavaParamRef<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_newResultAndBuffer(env, result, byte_buffer); 279 } 280 281 static jint EndWriteData(JNIEnv* env, 282 const JavaParamRef<jobject>& jcaller, 283 jint mojo_handle, 284 jint num_bytes_written) { 285 return MojoEndWriteData(mojo_handle, num_bytes_written); 286 } 287 288 static ScopedJavaLocalRef<jobject> Duplicate( 289 JNIEnv* env, 290 const JavaParamRef<jobject>& jcaller, 291 jint mojo_handle, 292 const JavaParamRef<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_newResultAndInteger(env, result, handle); 306 } 307 308 static ScopedJavaLocalRef<jobject> Map(JNIEnv* env, 309 const JavaParamRef<jobject>& jcaller, 310 jint mojo_handle, 311 jlong offset, 312 jlong num_bytes, 313 jint flags) { 314 void* buffer = 0; 315 MojoResult result = 316 MojoMapBuffer(mojo_handle, offset, num_bytes, &buffer, flags); 317 jobject byte_buffer = 0; 318 if (result == MOJO_RESULT_OK) { 319 byte_buffer = env->NewDirectByteBuffer(buffer, num_bytes); 320 } 321 return Java_CoreImpl_newResultAndBuffer(env, result, byte_buffer); 322 } 323 324 static int Unmap(JNIEnv* env, 325 const JavaParamRef<jobject>& jcaller, 326 const JavaParamRef<jobject>& buffer) { 327 void* buffer_start = env->GetDirectBufferAddress(buffer); 328 DCHECK(buffer_start); 329 return MojoUnmapBuffer(buffer_start); 330 } 331 332 static jint GetNativeBufferOffset(JNIEnv* env, 333 const JavaParamRef<jobject>& jcaller, 334 const JavaParamRef<jobject>& buffer, 335 jint alignment) { 336 jint offset = 337 reinterpret_cast<uintptr_t>(env->GetDirectBufferAddress(buffer)) % 338 alignment; 339 if (offset == 0) 340 return 0; 341 return alignment - offset; 342 } 343 344 bool RegisterCoreImpl(JNIEnv* env) { 345 return RegisterNativesImpl(env); 346 } 347 348 } // namespace android 349 } // namespace mojo 350