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 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 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 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 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 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