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 <stddef.h> 6 #include <stdint.h> 7 8 #include "base/android/jni_android.h" 9 #include "base/android/jni_array.h" 10 #include "base/android/scoped_java_ref.h" 11 #include "jni/CoreImpl_jni.h" 12 #include "mojo/public/c/system/core.h" 13 #include "mojo/public/cpp/system/message_pipe.h" 14 15 namespace mojo { 16 namespace android { 17 18 using base::android::JavaParamRef; 19 using base::android::ScopedJavaLocalRef; 20 21 static jlong JNI_CoreImpl_GetTimeTicksNow( 22 JNIEnv* env, 23 const JavaParamRef<jobject>& jcaller) { 24 return MojoGetTimeTicksNow(); 25 } 26 27 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_CreateMessagePipe( 28 JNIEnv* env, 29 const JavaParamRef<jobject>& jcaller, 30 const JavaParamRef<jobject>& options_buffer) { 31 const MojoCreateMessagePipeOptions* options = NULL; 32 if (options_buffer) { 33 const void* buffer_start = env->GetDirectBufferAddress(options_buffer); 34 DCHECK(buffer_start); 35 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u); 36 const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer); 37 DCHECK_EQ(buffer_size, sizeof(MojoCreateMessagePipeOptions)); 38 options = static_cast<const MojoCreateMessagePipeOptions*>(buffer_start); 39 DCHECK_EQ(options->struct_size, buffer_size); 40 } 41 MojoHandle handle1; 42 MojoHandle handle2; 43 MojoResult result = MojoCreateMessagePipe(options, &handle1, &handle2); 44 return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2); 45 } 46 47 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_CreateDataPipe( 48 JNIEnv* env, 49 const JavaParamRef<jobject>& jcaller, 50 const JavaParamRef<jobject>& options_buffer) { 51 const MojoCreateDataPipeOptions* options = NULL; 52 if (options_buffer) { 53 const void* buffer_start = env->GetDirectBufferAddress(options_buffer); 54 DCHECK(buffer_start); 55 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u); 56 const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer); 57 DCHECK_EQ(buffer_size, sizeof(MojoCreateDataPipeOptions)); 58 options = static_cast<const MojoCreateDataPipeOptions*>(buffer_start); 59 DCHECK_EQ(options->struct_size, buffer_size); 60 } 61 MojoHandle handle1; 62 MojoHandle handle2; 63 MojoResult result = MojoCreateDataPipe(options, &handle1, &handle2); 64 return Java_CoreImpl_newNativeCreationResult(env, result, handle1, handle2); 65 } 66 67 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_CreateSharedBuffer( 68 JNIEnv* env, 69 const JavaParamRef<jobject>& jcaller, 70 const JavaParamRef<jobject>& options_buffer, 71 jlong num_bytes) { 72 const MojoCreateSharedBufferOptions* options = 0; 73 if (options_buffer) { 74 const void* buffer_start = env->GetDirectBufferAddress(options_buffer); 75 DCHECK(buffer_start); 76 DCHECK_EQ(reinterpret_cast<const uintptr_t>(buffer_start) % 8, 0u); 77 const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer); 78 DCHECK_EQ(buffer_size, sizeof(MojoCreateSharedBufferOptions)); 79 options = static_cast<const MojoCreateSharedBufferOptions*>(buffer_start); 80 DCHECK_EQ(options->struct_size, buffer_size); 81 } 82 MojoHandle handle; 83 MojoResult result = MojoCreateSharedBuffer(num_bytes, options, &handle); 84 return Java_CoreImpl_newResultAndInteger(env, result, handle); 85 } 86 87 static jint JNI_CoreImpl_Close(JNIEnv* env, 88 const JavaParamRef<jobject>& jcaller, 89 jint mojo_handle) { 90 return MojoClose(mojo_handle); 91 } 92 93 static jint JNI_CoreImpl_QueryHandleSignalsState( 94 JNIEnv* env, 95 const JavaParamRef<jobject>& jcaller, 96 jint mojo_handle, 97 const JavaParamRef<jobject>& buffer) { 98 MojoHandleSignalsState* signals_state = 99 static_cast<MojoHandleSignalsState*>(env->GetDirectBufferAddress(buffer)); 100 DCHECK(signals_state); 101 DCHECK_EQ(sizeof(MojoHandleSignalsState), 102 static_cast<size_t>(env->GetDirectBufferCapacity(buffer))); 103 return MojoQueryHandleSignalsState(mojo_handle, signals_state); 104 } 105 106 static jint JNI_CoreImpl_WriteMessage( 107 JNIEnv* env, 108 const JavaParamRef<jobject>& jcaller, 109 jint mojo_handle, 110 const JavaParamRef<jobject>& bytes, 111 jint num_bytes, 112 const JavaParamRef<jobject>& handles_buffer, 113 jint flags) { 114 const void* buffer_start = 0; 115 uint32_t buffer_size = 0; 116 if (bytes) { 117 buffer_start = env->GetDirectBufferAddress(bytes); 118 DCHECK(buffer_start); 119 DCHECK(env->GetDirectBufferCapacity(bytes) >= num_bytes); 120 buffer_size = num_bytes; 121 } 122 const MojoHandle* handles = 0; 123 uint32_t num_handles = 0; 124 if (handles_buffer) { 125 handles = 126 static_cast<MojoHandle*>(env->GetDirectBufferAddress(handles_buffer)); 127 num_handles = env->GetDirectBufferCapacity(handles_buffer) / 4; 128 } 129 // Java code will handle invalidating handles if the write succeeded. 130 return WriteMessageRaw( 131 MessagePipeHandle(static_cast<MojoHandle>(mojo_handle)), buffer_start, 132 buffer_size, handles, num_handles, flags); 133 } 134 135 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_ReadMessage( 136 JNIEnv* env, 137 const JavaParamRef<jobject>& jcaller, 138 jint mojo_handle, 139 jint flags) { 140 ScopedMessageHandle message; 141 MojoResult result = 142 ReadMessageNew(MessagePipeHandle(mojo_handle), &message, flags); 143 if (result != MOJO_RESULT_OK) 144 return Java_CoreImpl_newReadMessageResult(env, result, nullptr, nullptr); 145 DCHECK(message.is_valid()); 146 147 result = MojoSerializeMessage(message->value(), nullptr); 148 if (result != MOJO_RESULT_OK && result != MOJO_RESULT_FAILED_PRECONDITION) { 149 return Java_CoreImpl_newReadMessageResult(env, MOJO_RESULT_ABORTED, nullptr, 150 nullptr); 151 } 152 153 uint32_t num_bytes; 154 void* buffer; 155 uint32_t num_handles = 0; 156 std::vector<MojoHandle> handles; 157 result = MojoGetMessageData(message->value(), nullptr, &buffer, &num_bytes, 158 nullptr, &num_handles); 159 if (result == MOJO_RESULT_RESOURCE_EXHAUSTED) { 160 handles.resize(num_handles); 161 result = MojoGetMessageData(message->value(), nullptr, &buffer, &num_bytes, 162 handles.data(), &num_handles); 163 } 164 165 if (result != MOJO_RESULT_OK) 166 return Java_CoreImpl_newReadMessageResult(env, result, nullptr, nullptr); 167 168 return Java_CoreImpl_newReadMessageResult( 169 env, result, 170 base::android::ToJavaByteArray(env, static_cast<uint8_t*>(buffer), 171 num_bytes), 172 base::android::ToJavaIntArray( 173 env, reinterpret_cast<jint*>(handles.data()), num_handles)); 174 } 175 176 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_ReadData( 177 JNIEnv* env, 178 const JavaParamRef<jobject>& jcaller, 179 jint mojo_handle, 180 const JavaParamRef<jobject>& elements, 181 jint elements_capacity, 182 jint flags) { 183 void* buffer_start = 0; 184 uint32_t buffer_size = elements_capacity; 185 if (elements) { 186 buffer_start = env->GetDirectBufferAddress(elements); 187 DCHECK(buffer_start); 188 DCHECK(elements_capacity <= env->GetDirectBufferCapacity(elements)); 189 } 190 MojoReadDataOptions options; 191 options.struct_size = sizeof(options); 192 options.flags = flags; 193 MojoResult result = 194 MojoReadData(mojo_handle, &options, buffer_start, &buffer_size); 195 return Java_CoreImpl_newResultAndInteger( 196 env, result, (result == MOJO_RESULT_OK) ? buffer_size : 0); 197 } 198 199 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_BeginReadData( 200 JNIEnv* env, 201 const JavaParamRef<jobject>& jcaller, 202 jint mojo_handle, 203 jint num_bytes, 204 jint flags) { 205 void const* buffer = 0; 206 uint32_t buffer_size = num_bytes; 207 208 MojoBeginReadDataOptions options; 209 options.struct_size = sizeof(options); 210 options.flags = flags; 211 MojoResult result = 212 MojoBeginReadData(mojo_handle, &options, &buffer, &buffer_size); 213 if (result == MOJO_RESULT_OK) { 214 ScopedJavaLocalRef<jobject> byte_buffer( 215 env, env->NewDirectByteBuffer(const_cast<void*>(buffer), buffer_size)); 216 return Java_CoreImpl_newResultAndBuffer(env, result, byte_buffer); 217 } else { 218 return Java_CoreImpl_newResultAndBuffer(env, result, nullptr); 219 } 220 } 221 222 static jint JNI_CoreImpl_EndReadData(JNIEnv* env, 223 const JavaParamRef<jobject>& jcaller, 224 jint mojo_handle, 225 jint num_bytes_read) { 226 return MojoEndReadData(mojo_handle, num_bytes_read, nullptr); 227 } 228 229 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_WriteData( 230 JNIEnv* env, 231 const JavaParamRef<jobject>& jcaller, 232 jint mojo_handle, 233 const JavaParamRef<jobject>& elements, 234 jint limit, 235 jint flags) { 236 void* buffer_start = env->GetDirectBufferAddress(elements); 237 DCHECK(buffer_start); 238 DCHECK(limit <= env->GetDirectBufferCapacity(elements)); 239 uint32_t buffer_size = limit; 240 241 MojoWriteDataOptions options; 242 options.struct_size = sizeof(options); 243 options.flags = flags; 244 MojoResult result = 245 MojoWriteData(mojo_handle, buffer_start, &buffer_size, &options); 246 return Java_CoreImpl_newResultAndInteger( 247 env, result, (result == MOJO_RESULT_OK) ? buffer_size : 0); 248 } 249 250 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_BeginWriteData( 251 JNIEnv* env, 252 const JavaParamRef<jobject>& jcaller, 253 jint mojo_handle, 254 jint num_bytes, 255 jint flags) { 256 void* buffer = 0; 257 uint32_t buffer_size = num_bytes; 258 MojoBeginWriteDataOptions options; 259 options.struct_size = sizeof(options); 260 options.flags = flags; 261 MojoResult result = 262 MojoBeginWriteData(mojo_handle, &options, &buffer, &buffer_size); 263 if (result == MOJO_RESULT_OK) { 264 ScopedJavaLocalRef<jobject> byte_buffer( 265 env, env->NewDirectByteBuffer(buffer, buffer_size)); 266 return Java_CoreImpl_newResultAndBuffer(env, result, byte_buffer); 267 } else { 268 return Java_CoreImpl_newResultAndBuffer(env, result, nullptr); 269 } 270 } 271 272 static jint JNI_CoreImpl_EndWriteData(JNIEnv* env, 273 const JavaParamRef<jobject>& jcaller, 274 jint mojo_handle, 275 jint num_bytes_written) { 276 return MojoEndWriteData(mojo_handle, num_bytes_written, nullptr); 277 } 278 279 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_Duplicate( 280 JNIEnv* env, 281 const JavaParamRef<jobject>& jcaller, 282 jint mojo_handle, 283 const JavaParamRef<jobject>& options_buffer) { 284 const MojoDuplicateBufferHandleOptions* options = 0; 285 if (options_buffer) { 286 const void* buffer_start = env->GetDirectBufferAddress(options_buffer); 287 DCHECK(buffer_start); 288 const size_t buffer_size = env->GetDirectBufferCapacity(options_buffer); 289 DCHECK_EQ(buffer_size, sizeof(MojoDuplicateBufferHandleOptions)); 290 options = 291 static_cast<const MojoDuplicateBufferHandleOptions*>(buffer_start); 292 DCHECK_EQ(options->struct_size, buffer_size); 293 } 294 MojoHandle handle; 295 MojoResult result = MojoDuplicateBufferHandle(mojo_handle, options, &handle); 296 return Java_CoreImpl_newResultAndInteger(env, result, handle); 297 } 298 299 static ScopedJavaLocalRef<jobject> JNI_CoreImpl_Map( 300 JNIEnv* env, 301 const JavaParamRef<jobject>& jcaller, 302 jint mojo_handle, 303 jlong offset, 304 jlong num_bytes, 305 jint flags) { 306 void* buffer = 0; 307 MojoMapBufferOptions options; 308 options.struct_size = sizeof(options); 309 options.flags = flags; 310 MojoResult result = 311 MojoMapBuffer(mojo_handle, offset, num_bytes, &options, &buffer); 312 if (result == MOJO_RESULT_OK) { 313 ScopedJavaLocalRef<jobject> byte_buffer( 314 env, env->NewDirectByteBuffer(buffer, num_bytes)); 315 return Java_CoreImpl_newResultAndBuffer(env, result, byte_buffer); 316 } else { 317 return Java_CoreImpl_newResultAndBuffer(env, result, nullptr); 318 } 319 } 320 321 static int JNI_CoreImpl_Unmap(JNIEnv* env, 322 const JavaParamRef<jobject>& jcaller, 323 const JavaParamRef<jobject>& buffer) { 324 void* buffer_start = env->GetDirectBufferAddress(buffer); 325 DCHECK(buffer_start); 326 return MojoUnmapBuffer(buffer_start); 327 } 328 329 static jint JNI_CoreImpl_GetNativeBufferOffset( 330 JNIEnv* env, 331 const JavaParamRef<jobject>& jcaller, 332 const JavaParamRef<jobject>& buffer, 333 jint alignment) { 334 jint offset = 335 reinterpret_cast<uintptr_t>(env->GetDirectBufferAddress(buffer)) % 336 alignment; 337 if (offset == 0) 338 return 0; 339 return alignment - offset; 340 } 341 342 } // namespace android 343 } // namespace mojo 344