/* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "android_os_NativeHandle.h" #include #include #include "core_jni_helpers.h" #define PACKAGE_PATH "android/os" #define CLASS_NAME "NativeHandle" #define CLASS_PATH PACKAGE_PATH "/" CLASS_NAME namespace android { static struct { jclass clazz; jmethodID constructID; // NativeHandle(int[] fds, int[] ints, boolean owns) jmethodID getFdsID; // int[] NativeHandle.getFds() jmethodID getIntsID; // int[] NativeHandle.getInts() } gNativeHandleFields; jobject JNativeHandle::MakeJavaNativeHandleObj( JNIEnv *env, const native_handle_t *handle) { if (handle == nullptr) { return nullptr; } const int numFds = handle->numFds; ScopedLocalRef fds(env, env->NewIntArray(numFds)); env->SetIntArrayRegion(fds.get(), 0, numFds, &(handle->data[0])); const int numInts = handle->numInts; ScopedLocalRef ints(env, env->NewIntArray(numInts)); env->SetIntArrayRegion(ints.get(), 0, numInts, &(handle->data[numFds])); return env->NewObject(gNativeHandleFields.clazz, gNativeHandleFields.constructID, fds.get(), ints.get(), false /*own*/); } native_handle_t *JNativeHandle::MakeCppNativeHandle( JNIEnv *env, jobject jHandle, EphemeralStorage *storage) { if (jHandle == nullptr) { return nullptr; } if (!env->IsInstanceOf(jHandle, gNativeHandleFields.clazz)) { jniThrowException(env, "java/lang/ClassCastException", "jHandle must be an instance of NativeHandle."); return nullptr; } ScopedLocalRef fds(env, (jintArray) env->CallObjectMethod( jHandle, gNativeHandleFields.getFdsID)); ScopedLocalRef ints(env, (jintArray) env->CallObjectMethod( jHandle, gNativeHandleFields.getIntsID)); const int numFds = (int) env->GetArrayLength(fds.get()); const int numInts = (int) env->GetArrayLength(ints.get()); native_handle_t *handle = (storage == nullptr) ? native_handle_create(numFds, numInts) : storage->allocTemporaryNativeHandle(numFds, numInts); if (handle != nullptr) { env->GetIntArrayRegion(fds.get(), 0, numFds, &(handle->data[0])); env->GetIntArrayRegion(ints.get(), 0, numInts, &(handle->data[numFds])); } else { jniThrowException(env, "java/lang/OutOfMemoryError", "Failed to allocate memory for native_handle_t."); } return handle; } jobjectArray JNativeHandle::AllocJavaNativeHandleObjArray(JNIEnv *env, jsize length) { return env->NewObjectArray(length, gNativeHandleFields.clazz, nullptr); } int register_android_os_NativeHandle(JNIEnv *env) { jclass clazz = FindClassOrDie(env, CLASS_PATH); gNativeHandleFields.clazz = MakeGlobalRefOrDie(env, clazz); gNativeHandleFields.constructID = GetMethodIDOrDie(env, clazz, "", "([I[IZ)V"); gNativeHandleFields.getFdsID = GetMethodIDOrDie(env, clazz, "getFdsAsIntArray", "()[I"); gNativeHandleFields.getIntsID = GetMethodIDOrDie(env, clazz, "getInts", "()[I"); return 0; } }