xref: /aosp_15_r20/external/libchrome/mojo/public/java/system/core_impl.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
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