15f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu/*
25f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu * Copyright (C) 2017 The Android Open Source Project
35f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu *
45f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu * Licensed under the Apache License, Version 2.0 (the "License");
55f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu * you may not use this file except in compliance with the License.
65f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu * You may obtain a copy of the License at
75f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu *
85f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu *      http://www.apache.org/licenses/LICENSE-2.0
95f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu *
105f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu * Unless required by applicable law or agreed to in writing, software
115f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu * distributed under the License is distributed on an "AS IS" BASIS,
125f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu * See the License for the specific language governing permissions and
145f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu * limitations under the License.
155f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu */
165f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu
17e4f60cce8552a565efacf4907242574b9e00492dJohn Reck#include <jni.h>
18e4f60cce8552a565efacf4907242574b9e00492dJohn Reck
195f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu#include <android/sharedmem.h>
20e4f60cce8552a565efacf4907242574b9e00492dJohn Reck#include <android/sharedmem_jni.h>
215f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu#include <cutils/ashmem.h>
22e4f60cce8552a565efacf4907242574b9e00492dJohn Reck#include <log/log.h>
235f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu#include <utils/Errors.h>
245f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu
25e4f60cce8552a565efacf4907242574b9e00492dJohn Reck#include <mutex>
26e4f60cce8552a565efacf4907242574b9e00492dJohn Reck#include <unistd.h>
27e4f60cce8552a565efacf4907242574b9e00492dJohn Reck
28e4f60cce8552a565efacf4907242574b9e00492dJohn Reckstatic struct {
29e4f60cce8552a565efacf4907242574b9e00492dJohn Reck    jclass clazz;
30e4f60cce8552a565efacf4907242574b9e00492dJohn Reck    jmethodID getFd;
31e4f60cce8552a565efacf4907242574b9e00492dJohn Reck} sSharedMemory;
32e4f60cce8552a565efacf4907242574b9e00492dJohn Reck
33e4f60cce8552a565efacf4907242574b9e00492dJohn Reckstatic void jniInit(JNIEnv* env) {
34e4f60cce8552a565efacf4907242574b9e00492dJohn Reck    static std::once_flag sJniInitialized;
35e4f60cce8552a565efacf4907242574b9e00492dJohn Reck    std::call_once(sJniInitialized, [](JNIEnv* env) {
36e4f60cce8552a565efacf4907242574b9e00492dJohn Reck        jclass clazz = env->FindClass("android/os/SharedMemory");
37e4f60cce8552a565efacf4907242574b9e00492dJohn Reck        LOG_ALWAYS_FATAL_IF(clazz == nullptr, "Failed to find android.os.SharedMemory");
38e4f60cce8552a565efacf4907242574b9e00492dJohn Reck        sSharedMemory.clazz = (jclass) env->NewGlobalRef(clazz);
39e4f60cce8552a565efacf4907242574b9e00492dJohn Reck        LOG_ALWAYS_FATAL_IF(sSharedMemory.clazz == nullptr,
40e4f60cce8552a565efacf4907242574b9e00492dJohn Reck                "Failed to create global ref of android.os.SharedMemory");
41e4f60cce8552a565efacf4907242574b9e00492dJohn Reck        sSharedMemory.getFd = env->GetMethodID(sSharedMemory.clazz, "getFd", "()I");
42e4f60cce8552a565efacf4907242574b9e00492dJohn Reck        LOG_ALWAYS_FATAL_IF(sSharedMemory.getFd == nullptr,
43e4f60cce8552a565efacf4907242574b9e00492dJohn Reck                "Failed to find method SharedMemory#getFd()");
44e4f60cce8552a565efacf4907242574b9e00492dJohn Reck    }, env);
45e4f60cce8552a565efacf4907242574b9e00492dJohn Reck}
46e4f60cce8552a565efacf4907242574b9e00492dJohn Reck
475f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xuint ASharedMemory_create(const char *name, size_t size) {
485f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu    if (size == 0) {
495f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu        return android::BAD_VALUE;
505f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu    }
515f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu    return ashmem_create_region(name, size);
525f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu}
535f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu
545f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xusize_t ASharedMemory_getSize(int fd) {
555f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu    return ashmem_valid(fd) ? ashmem_get_size_region(fd) : 0;
565f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu}
575f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu
585f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xuint ASharedMemory_setProt(int fd, int prot) {
595f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu    return ashmem_set_prot_region(fd, prot);
605f88ac5ccef78203c62e32e0503f18dd46102c5ePeng Xu}
61e4f60cce8552a565efacf4907242574b9e00492dJohn Reck
62e4f60cce8552a565efacf4907242574b9e00492dJohn Reckint ASharedMemory_dupFromJava(JNIEnv* env, jobject javaSharedMemory) {
63e4f60cce8552a565efacf4907242574b9e00492dJohn Reck    if (env == nullptr || javaSharedMemory == nullptr) {
64e4f60cce8552a565efacf4907242574b9e00492dJohn Reck        return -1;
65e4f60cce8552a565efacf4907242574b9e00492dJohn Reck    }
66e4f60cce8552a565efacf4907242574b9e00492dJohn Reck    jniInit(env);
67e4f60cce8552a565efacf4907242574b9e00492dJohn Reck    if (!env->IsInstanceOf(javaSharedMemory, sSharedMemory.clazz)) {
68e4f60cce8552a565efacf4907242574b9e00492dJohn Reck        ALOGW("ASharedMemory_dupFromJava called with object "
69e4f60cce8552a565efacf4907242574b9e00492dJohn Reck                "that's not an instanceof android.os.SharedMemory");
70e4f60cce8552a565efacf4907242574b9e00492dJohn Reck        return -1;
71e4f60cce8552a565efacf4907242574b9e00492dJohn Reck    }
72e4f60cce8552a565efacf4907242574b9e00492dJohn Reck    int fd = env->CallIntMethod(javaSharedMemory, sSharedMemory.getFd);
73e4f60cce8552a565efacf4907242574b9e00492dJohn Reck    if (fd != -1) {
74e4f60cce8552a565efacf4907242574b9e00492dJohn Reck        fd = dup(fd);
75e4f60cce8552a565efacf4907242574b9e00492dJohn Reck    }
76e4f60cce8552a565efacf4907242574b9e00492dJohn Reck    return fd;
77e4f60cce8552a565efacf4907242574b9e00492dJohn Reck}
78