1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker * Copyright (C) 2017 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker *
4*d57664e9SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker *
8*d57664e9SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker *
10*d57664e9SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker */
16*d57664e9SAndroid Build Coastguard Worker
17*d57664e9SAndroid Build Coastguard Worker #include <jni.h>
18*d57664e9SAndroid Build Coastguard Worker
19*d57664e9SAndroid Build Coastguard Worker #include <fcntl.h>
20*d57664e9SAndroid Build Coastguard Worker #include <unistd.h>
21*d57664e9SAndroid Build Coastguard Worker
22*d57664e9SAndroid Build Coastguard Worker #include <android/sharedmem.h>
23*d57664e9SAndroid Build Coastguard Worker #include <android/sharedmem_jni.h>
24*d57664e9SAndroid Build Coastguard Worker #include <cutils/ashmem.h>
25*d57664e9SAndroid Build Coastguard Worker #include <log/log.h>
26*d57664e9SAndroid Build Coastguard Worker #include <utils/Errors.h>
27*d57664e9SAndroid Build Coastguard Worker
28*d57664e9SAndroid Build Coastguard Worker #include <mutex>
29*d57664e9SAndroid Build Coastguard Worker
30*d57664e9SAndroid Build Coastguard Worker static struct {
31*d57664e9SAndroid Build Coastguard Worker jclass clazz;
32*d57664e9SAndroid Build Coastguard Worker jmethodID getFd;
33*d57664e9SAndroid Build Coastguard Worker } sSharedMemory;
34*d57664e9SAndroid Build Coastguard Worker
jniInit(JNIEnv * env)35*d57664e9SAndroid Build Coastguard Worker static void jniInit(JNIEnv* env) {
36*d57664e9SAndroid Build Coastguard Worker static std::once_flag sJniInitialized;
37*d57664e9SAndroid Build Coastguard Worker std::call_once(sJniInitialized, [](JNIEnv* env) {
38*d57664e9SAndroid Build Coastguard Worker jclass clazz = env->FindClass("android/os/SharedMemory");
39*d57664e9SAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(clazz == nullptr, "Failed to find android.os.SharedMemory");
40*d57664e9SAndroid Build Coastguard Worker sSharedMemory.clazz = (jclass) env->NewGlobalRef(clazz);
41*d57664e9SAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(sSharedMemory.clazz == nullptr,
42*d57664e9SAndroid Build Coastguard Worker "Failed to create global ref of android.os.SharedMemory");
43*d57664e9SAndroid Build Coastguard Worker sSharedMemory.getFd = env->GetMethodID(sSharedMemory.clazz, "getFd", "()I");
44*d57664e9SAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(sSharedMemory.getFd == nullptr,
45*d57664e9SAndroid Build Coastguard Worker "Failed to find method SharedMemory#getFd()");
46*d57664e9SAndroid Build Coastguard Worker }, env);
47*d57664e9SAndroid Build Coastguard Worker }
48*d57664e9SAndroid Build Coastguard Worker
ASharedMemory_create(const char * name,size_t size)49*d57664e9SAndroid Build Coastguard Worker int ASharedMemory_create(const char *name, size_t size) {
50*d57664e9SAndroid Build Coastguard Worker if (size == 0) {
51*d57664e9SAndroid Build Coastguard Worker return android::BAD_VALUE;
52*d57664e9SAndroid Build Coastguard Worker }
53*d57664e9SAndroid Build Coastguard Worker return ashmem_create_region(name, size);
54*d57664e9SAndroid Build Coastguard Worker }
55*d57664e9SAndroid Build Coastguard Worker
ASharedMemory_getSize(int fd)56*d57664e9SAndroid Build Coastguard Worker size_t ASharedMemory_getSize(int fd) {
57*d57664e9SAndroid Build Coastguard Worker return ashmem_valid(fd) ? ashmem_get_size_region(fd) : 0;
58*d57664e9SAndroid Build Coastguard Worker }
59*d57664e9SAndroid Build Coastguard Worker
ASharedMemory_setProt(int fd,int prot)60*d57664e9SAndroid Build Coastguard Worker int ASharedMemory_setProt(int fd, int prot) {
61*d57664e9SAndroid Build Coastguard Worker return ashmem_set_prot_region(fd, prot);
62*d57664e9SAndroid Build Coastguard Worker }
63*d57664e9SAndroid Build Coastguard Worker
ASharedMemory_dupFromJava(JNIEnv * env,jobject javaSharedMemory)64*d57664e9SAndroid Build Coastguard Worker int ASharedMemory_dupFromJava(JNIEnv* env, jobject javaSharedMemory) {
65*d57664e9SAndroid Build Coastguard Worker if (env == nullptr || javaSharedMemory == nullptr) {
66*d57664e9SAndroid Build Coastguard Worker return -1;
67*d57664e9SAndroid Build Coastguard Worker }
68*d57664e9SAndroid Build Coastguard Worker jniInit(env);
69*d57664e9SAndroid Build Coastguard Worker if (!env->IsInstanceOf(javaSharedMemory, sSharedMemory.clazz)) {
70*d57664e9SAndroid Build Coastguard Worker ALOGW("ASharedMemory_dupFromJava called with object "
71*d57664e9SAndroid Build Coastguard Worker "that's not an instanceof android.os.SharedMemory");
72*d57664e9SAndroid Build Coastguard Worker return -1;
73*d57664e9SAndroid Build Coastguard Worker }
74*d57664e9SAndroid Build Coastguard Worker int fd = env->CallIntMethod(javaSharedMemory, sSharedMemory.getFd);
75*d57664e9SAndroid Build Coastguard Worker if (fd != -1) {
76*d57664e9SAndroid Build Coastguard Worker fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
77*d57664e9SAndroid Build Coastguard Worker }
78*d57664e9SAndroid Build Coastguard Worker return fd;
79*d57664e9SAndroid Build Coastguard Worker }
80