1 /* 2 * Copyright (C) 2018 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 #include "android_os_NativeHandle.h" 18 19 #include <nativehelper/JNIHelp.h> 20 #include <nativehelper/ScopedLocalRef.h> 21 22 #include "core_jni_helpers.h" 23 24 #define PACKAGE_PATH "android/os" 25 #define CLASS_NAME "NativeHandle" 26 #define CLASS_PATH PACKAGE_PATH "/" CLASS_NAME 27 28 namespace android { 29 30 static struct { 31 jclass clazz; 32 jmethodID constructID; // NativeHandle(int[] fds, int[] ints, boolean owns) 33 34 jmethodID getFdsID; // int[] NativeHandle.getFds() 35 jmethodID getIntsID; // int[] NativeHandle.getInts() 36 } gNativeHandleFields; 37 38 jobject JNativeHandle::MakeJavaNativeHandleObj( 39 JNIEnv *env, const native_handle_t *handle) { 40 if (handle == nullptr) { return nullptr; } 41 42 const int numFds = handle->numFds; 43 ScopedLocalRef<jintArray> fds(env, env->NewIntArray(numFds)); 44 env->SetIntArrayRegion(fds.get(), 0, numFds, &(handle->data[0])); 45 46 const int numInts = handle->numInts; 47 ScopedLocalRef<jintArray> ints(env, env->NewIntArray(numInts)); 48 env->SetIntArrayRegion(ints.get(), 0, numInts, &(handle->data[numFds])); 49 50 return env->NewObject(gNativeHandleFields.clazz, 51 gNativeHandleFields.constructID, fds.get(), ints.get(), false /*own*/); 52 } 53 54 native_handle_t *JNativeHandle::MakeCppNativeHandle( 55 JNIEnv *env, jobject jHandle, EphemeralStorage *storage) { 56 if (jHandle == nullptr) { return nullptr; } 57 58 if (!env->IsInstanceOf(jHandle, gNativeHandleFields.clazz)) { 59 jniThrowException(env, "java/lang/ClassCastException", 60 "jHandle must be an instance of NativeHandle."); 61 return nullptr; 62 } 63 64 ScopedLocalRef<jintArray> fds(env, (jintArray) env->CallObjectMethod( 65 jHandle, gNativeHandleFields.getFdsID)); 66 67 ScopedLocalRef<jintArray> ints(env, (jintArray) env->CallObjectMethod( 68 jHandle, gNativeHandleFields.getIntsID)); 69 70 const int numFds = (int) env->GetArrayLength(fds.get()); 71 const int numInts = (int) env->GetArrayLength(ints.get()); 72 73 native_handle_t *handle = (storage == nullptr) 74 ? native_handle_create(numFds, numInts) 75 : storage->allocTemporaryNativeHandle(numFds, numInts); 76 77 if (handle != nullptr) { 78 env->GetIntArrayRegion(fds.get(), 0, numFds, &(handle->data[0])); 79 env->GetIntArrayRegion(ints.get(), 0, numInts, &(handle->data[numFds])); 80 } else { 81 jniThrowException(env, "java/lang/OutOfMemoryError", 82 "Failed to allocate memory for native_handle_t."); 83 } 84 85 return handle; 86 } 87 88 jobjectArray JNativeHandle::AllocJavaNativeHandleObjArray(JNIEnv *env, jsize length) { 89 return env->NewObjectArray(length, gNativeHandleFields.clazz, nullptr); 90 } 91 92 int register_android_os_NativeHandle(JNIEnv *env) { 93 jclass clazz = FindClassOrDie(env, CLASS_PATH); 94 gNativeHandleFields.clazz = MakeGlobalRefOrDie(env, clazz); 95 96 gNativeHandleFields.constructID = GetMethodIDOrDie(env, clazz, "<init>", "([I[IZ)V"); 97 gNativeHandleFields.getFdsID = GetMethodIDOrDie(env, clazz, "getFdsAsIntArray", "()[I"); 98 gNativeHandleFields.getIntsID = GetMethodIDOrDie(env, clazz, "getInts", "()[I"); 99 100 return 0; 101 } 102 103 } 104