1 /*
2 * Copyright 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18 #define LOG_TAG "SyncTest"
19
20 #include <errno.h>
21 #include <poll.h>
22 #include <unistd.h>
23
24 #include <array>
25 #include <memory>
26
27 #include <jni.h>
28
29 #include <android/sync.h>
30
31 namespace {
32
33 enum {
34 STATUS_ERROR = -1,
35 STATUS_UNSIGNALED = 0,
36 STATUS_SIGNALED = 1,
37 };
38
syncPoll(JNIEnv * env,jclass,jintArray fds_array,jintArray status_array)39 jboolean syncPoll(JNIEnv* env, jclass /*clazz*/, jintArray fds_array, jintArray status_array) {
40 jsize n = env->GetArrayLength(fds_array);
41 if (env->GetArrayLength(status_array) != n)
42 return JNI_FALSE;
43 std::unique_ptr<pollfd[]> pollfds = std::make_unique<pollfd[]>(n);
44
45 jint* fds = static_cast<jint*>(env->GetPrimitiveArrayCritical(fds_array, nullptr));
46 for (jsize i = 0; i < n; i++) {
47 pollfds[i].fd = fds[i];
48 pollfds[i].events = POLLIN;
49 }
50 env->ReleasePrimitiveArrayCritical(fds_array, fds, 0);
51
52 int ret;
53 do {
54 ret = poll(pollfds.get(), n, -1 /* infinite timeout */);
55 } while (ret == -1 && errno == EINTR);
56 if (ret == -1)
57 return JNI_FALSE;
58
59 jint* status = static_cast<jint*>(env->GetPrimitiveArrayCritical(status_array, nullptr));
60 for (jsize i = 0; i < n; i++) {
61 if (pollfds[i].fd < 0)
62 continue;
63 if ((pollfds[i].revents & (POLLERR | POLLNVAL)) != 0)
64 status[i] = STATUS_ERROR;
65 else if ((pollfds[i].revents & POLLIN) != 0)
66 status[i] = STATUS_SIGNALED;
67 else
68 status[i] = STATUS_UNSIGNALED;
69 }
70 env->ReleasePrimitiveArrayCritical(status_array, status, 0);
71
72 return JNI_TRUE;
73 }
74
syncMerge(JNIEnv * env,jclass,jstring nameStr,jint fd1,jint fd2)75 jint syncMerge(JNIEnv* env, jclass /*clazz*/, jstring nameStr, jint fd1, jint fd2) {
76 const char* name = env->GetStringUTFChars(nameStr, nullptr);
77 int32_t result_fd = sync_merge(name, fd1, fd2);
78 env->ReleaseStringUTFChars(nameStr, name);
79 return result_fd;
80 }
81
syncFileInfo(JNIEnv *,jclass,jint fd)82 jobject syncFileInfo(JNIEnv* /*env*/, jclass /*clazz*/, jint fd) {
83 auto info = sync_file_info(fd);
84 if (!info) return nullptr;
85 // TODO: convert to SyncFileInfo
86 sync_file_info_free(info);
87 return nullptr;
88 }
89
syncClose(int fd)90 void syncClose(int fd) {
91 close(fd);
92 }
93
94 const std::array<JNINativeMethod, 4> JNI_METHODS = {{
95 { "nSyncPoll", "([I[I)Z", (void*)syncPoll },
96 { "nSyncMerge", "(Ljava/lang/String;II)I", (void*)syncMerge },
97 { "nSyncFileInfo", "(I)Landroid/graphics/cts/SyncTest/SyncFileInfo;", (void*)syncFileInfo },
98 { "nSyncClose", "(I)V", (void*)syncClose },
99 }};
100
101 }
102
register_android_graphics_cts_SyncTest(JNIEnv * env)103 int register_android_graphics_cts_SyncTest(JNIEnv* env) {
104 jclass clazz = env->FindClass("android/graphics/cts/SyncTest");
105 return env->RegisterNatives(clazz, JNI_METHODS.data(), JNI_METHODS.size());
106 }
107