/*
|
* 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 <nativehelper/JNIHelp.h>
|
#include <nativehelper/ScopedLocalRef.h>
|
|
#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<jintArray> fds(env, env->NewIntArray(numFds));
|
env->SetIntArrayRegion(fds.get(), 0, numFds, &(handle->data[0]));
|
|
const int numInts = handle->numInts;
|
ScopedLocalRef<jintArray> 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<jintArray> fds(env, (jintArray) env->CallObjectMethod(
|
jHandle, gNativeHandleFields.getFdsID));
|
|
ScopedLocalRef<jintArray> 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, "<init>", "([I[IZ)V");
|
gNativeHandleFields.getFdsID = GetMethodIDOrDie(env, clazz, "getFdsAsIntArray", "()[I");
|
gNativeHandleFields.getIntsID = GetMethodIDOrDie(env, clazz, "getInts", "()[I");
|
|
return 0;
|
}
|
|
}
|