ronnie
2022-10-23 371e654b8658a1ee7621498a93778ca5c7b8e0d9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/*
 * 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;
}
 
}