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
JNI_CoreImpl_GetTimeTicksNow(JNIEnv * env,const JavaParamRef<jobject> & jcaller)21 static jlong JNI_CoreImpl_GetTimeTicksNow(
22 JNIEnv* env,
23 const JavaParamRef<jobject>& jcaller) {
24 return MojoGetTimeTicksNow();
25 }
26
JNI_CoreImpl_CreateMessagePipe(JNIEnv * env,const JavaParamRef<jobject> & jcaller,const JavaParamRef<jobject> & options_buffer)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
JNI_CoreImpl_CreateDataPipe(JNIEnv * env,const JavaParamRef<jobject> & jcaller,const JavaParamRef<jobject> & options_buffer)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
JNI_CoreImpl_CreateSharedBuffer(JNIEnv * env,const JavaParamRef<jobject> & jcaller,const JavaParamRef<jobject> & options_buffer,jlong num_bytes)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
JNI_CoreImpl_Close(JNIEnv * env,const JavaParamRef<jobject> & jcaller,jint mojo_handle)87 static jint JNI_CoreImpl_Close(JNIEnv* env,
88 const JavaParamRef<jobject>& jcaller,
89 jint mojo_handle) {
90 return MojoClose(mojo_handle);
91 }
92
JNI_CoreImpl_QueryHandleSignalsState(JNIEnv * env,const JavaParamRef<jobject> & jcaller,jint mojo_handle,const JavaParamRef<jobject> & buffer)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
JNI_CoreImpl_WriteMessage(JNIEnv * env,const JavaParamRef<jobject> & jcaller,jint mojo_handle,const JavaParamRef<jobject> & bytes,jint num_bytes,const JavaParamRef<jobject> & handles_buffer,jint flags)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
JNI_CoreImpl_ReadMessage(JNIEnv * env,const JavaParamRef<jobject> & jcaller,jint mojo_handle,jint flags)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
JNI_CoreImpl_ReadData(JNIEnv * env,const JavaParamRef<jobject> & jcaller,jint mojo_handle,const JavaParamRef<jobject> & elements,jint elements_capacity,jint flags)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
JNI_CoreImpl_BeginReadData(JNIEnv * env,const JavaParamRef<jobject> & jcaller,jint mojo_handle,jint num_bytes,jint flags)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
JNI_CoreImpl_EndReadData(JNIEnv * env,const JavaParamRef<jobject> & jcaller,jint mojo_handle,jint num_bytes_read)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
JNI_CoreImpl_WriteData(JNIEnv * env,const JavaParamRef<jobject> & jcaller,jint mojo_handle,const JavaParamRef<jobject> & elements,jint limit,jint flags)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
JNI_CoreImpl_BeginWriteData(JNIEnv * env,const JavaParamRef<jobject> & jcaller,jint mojo_handle,jint num_bytes,jint flags)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
JNI_CoreImpl_EndWriteData(JNIEnv * env,const JavaParamRef<jobject> & jcaller,jint mojo_handle,jint num_bytes_written)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
JNI_CoreImpl_Duplicate(JNIEnv * env,const JavaParamRef<jobject> & jcaller,jint mojo_handle,const JavaParamRef<jobject> & options_buffer)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
JNI_CoreImpl_Map(JNIEnv * env,const JavaParamRef<jobject> & jcaller,jint mojo_handle,jlong offset,jlong num_bytes,jint flags)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
JNI_CoreImpl_Unmap(JNIEnv * env,const JavaParamRef<jobject> & jcaller,const JavaParamRef<jobject> & buffer)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
JNI_CoreImpl_GetNativeBufferOffset(JNIEnv * env,const JavaParamRef<jobject> & jcaller,const JavaParamRef<jobject> & buffer,jint alignment)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