1 /*
2 * Copyright (C) 2023 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/file_descriptor_jni.h>
18 #include <jni.h>
19
20 #include "berberis/base/logging.h"
21 #include "berberis/guest_abi/function_wrappers.h"
22 #include "berberis/guest_abi/guest_params.h"
23 #include "berberis/jni/jni_trampolines.h"
24 #include "berberis/proxy_loader/proxy_library_builder.h"
25
26 namespace berberis {
27
28 namespace {
29
30 // jobject AFileDescriptor_create(JNIEnv* env);
DoCustomTrampoline_AFileDescriptor_create(HostCode,ProcessState * state)31 void DoCustomTrampoline_AFileDescriptor_create(HostCode /* callee */, ProcessState* state) {
32 auto [guest_env] = GuestParamsValues<decltype(AFileDescriptor_create)>(state);
33 auto&& [ret] = GuestReturnReference<decltype(AFileDescriptor_create)>(state);
34 ret = AFileDescriptor_create(ToHostJNIEnv(guest_env));
35 }
36
37 // int AFileDescriptor_getFd(JNIEnv* env, jobject fileDescriptor);
DoCustomTrampoline_AFileDescriptor_getFd(HostCode,ProcessState * state)38 void DoCustomTrampoline_AFileDescriptor_getFd(HostCode /* callee */, ProcessState* state) {
39 auto [guest_env, fileDescriptor] = GuestParamsValues<decltype(AFileDescriptor_getFd)>(state);
40 auto&& [ret] = GuestReturnReference<decltype(AFileDescriptor_getFd)>(state);
41 ret = AFileDescriptor_getFd(ToHostJNIEnv(guest_env), fileDescriptor);
42 }
43
44 // void AFileDescriptor_setFd(JNIEnv* env, jobject fileDescriptor, int fd);
DoCustomTrampoline_AFileDescriptor_setFd(HostCode,ProcessState * state)45 void DoCustomTrampoline_AFileDescriptor_setFd(HostCode /* callee */, ProcessState* state) {
46 auto [guest_env, fileDescriptor, fd] = GuestParamsValues<decltype(AFileDescriptor_setFd)>(state);
47 AFileDescriptor_setFd(ToHostJNIEnv(guest_env), fileDescriptor, fd);
48 }
49
50 // jint JNI_CreateJavaVM(JavaVM**, JNIEnv**, void*);
DoCustomTrampoline_JNI_CreateJavaVM(HostCode,ProcessState * state)51 void DoCustomTrampoline_JNI_CreateJavaVM(HostCode /* callee */, ProcessState* state) {
52 auto [guest_vm, guest_env, init_info] = GuestParamsValues<decltype(JNI_CreateJavaVM)>(state);
53 auto&& [ret] = GuestReturnReference<decltype(JNI_CreateJavaVM)>(state);
54 JavaVM* host_vm;
55 JNIEnv* host_env;
56
57 ret = JNI_CreateJavaVM(&host_vm, &host_env, init_info);
58 // Android only supports a single runtime, this is already running so no more
59 // can be created. Thus we don't need to convert the returned objects to guest.
60 CHECK(ret == JNI_ERR);
61 }
62
63 // jint JNI_GetCreatedJavaVMs(JavaVM**, jsize, jsize*);
DoCustomTrampoline_JNI_GetCreatedJavaVMs(HostCode,ProcessState * state)64 void DoCustomTrampoline_JNI_GetCreatedJavaVMs(HostCode /* callee */, ProcessState* state) {
65 auto [guest_vm, input_size, output_size] =
66 GuestParamsValues<decltype(JNI_GetCreatedJavaVMs)>(state);
67 auto&& [ret] = GuestReturnReference<decltype(JNI_GetCreatedJavaVMs)>(state);
68
69 // There could be only one VM in Android.
70 JavaVM* host_vm;
71 ret = JNI_GetCreatedJavaVMs(&host_vm, 1, output_size);
72
73 if (ret == JNI_ERR) {
74 return;
75 }
76
77 CHECK(*output_size == 1u);
78 *ToHostAddr<GuestType<JavaVM*>>(ToGuestAddr(guest_vm)) = ToGuestJavaVM(host_vm);
79 }
80
81 #if defined(NATIVE_BRIDGE_GUEST_ARCH_ARM) && defined(__i386__)
82
83 #include "trampolines_arm_to_x86-inl.h" // generated file NOLINT [build/include]
84
85 #elif defined(NATIVE_BRIDGE_GUEST_ARCH_ARM64) && defined(__x86_64__)
86
87 #include "trampolines_arm64_to_x86_64-inl.h" // generated file NOLINT [build/include]
88
89 #elif defined(NATIVE_BRIDGE_GUEST_ARCH_RISCV64) && defined(__x86_64__)
90
91 #include "trampolines_riscv64_to_x86_64-inl.h" // generated file NOLINT [build/include]
92
93 #else
94
95 #error "Unknown guest/host arch combination"
96
97 #endif
98
99 DEFINE_INIT_PROXY_LIBRARY("libnativehelper.so")
100
101 } // namespace
102
103 } // namespace berberis
104