John Reck | dea6a02 | 2017-05-25 17:09:33 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2017 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 | #define LOG_TAG "SharedMemory" |
| 18 | |
| 19 | #include "core_jni_helpers.h" |
| 20 | |
| 21 | #include <cutils/ashmem.h> |
| 22 | #include <utils/Log.h> |
Orion Hodson | 24b3605 | 2018-11-21 10:59:19 +0000 | [diff] [blame] | 23 | |
| 24 | #include <nativehelper/jni_macros.h> |
Steven Moreland | 60cc6c0 | 2017-08-25 15:49:25 -0700 | [diff] [blame] | 25 | #include <nativehelper/JNIHelp.h> |
Steven Moreland | e33e014 | 2017-07-27 11:30:34 -0700 | [diff] [blame] | 26 | #include <nativehelper/ScopedLocalRef.h> |
John Reck | dea6a02 | 2017-05-25 17:09:33 -0700 | [diff] [blame] | 27 | |
| 28 | #include <algorithm> |
| 29 | #include <errno.h> |
| 30 | #include <limits> |
| 31 | #include <unistd.h> |
| 32 | |
| 33 | namespace { |
| 34 | |
Orion Hodson | 24b3605 | 2018-11-21 10:59:19 +0000 | [diff] [blame] | 35 | jclass errnoExceptionClass; |
| 36 | jmethodID errnoExceptionCtor; // MethodID for ErrnoException.<init>(String,I) |
John Reck | dea6a02 | 2017-05-25 17:09:33 -0700 | [diff] [blame] | 37 | |
Orion Hodson | 24b3605 | 2018-11-21 10:59:19 +0000 | [diff] [blame] | 38 | void throwErrnoException(JNIEnv* env, const char* functionName, int error) { |
John Reck | dea6a02 | 2017-05-25 17:09:33 -0700 | [diff] [blame] | 39 | ScopedLocalRef<jstring> detailMessage(env, env->NewStringUTF(functionName)); |
| 40 | if (detailMessage.get() == NULL) { |
| 41 | // Not really much we can do here. We're probably dead in the water, |
| 42 | // but let's try to stumble on... |
| 43 | env->ExceptionClear(); |
| 44 | } |
| 45 | |
Orion Hodson | 24b3605 | 2018-11-21 10:59:19 +0000 | [diff] [blame] | 46 | jobject exception = env->NewObject(errnoExceptionClass, |
| 47 | errnoExceptionCtor, |
| 48 | detailMessage.get(), |
| 49 | error); |
John Reck | dea6a02 | 2017-05-25 17:09:33 -0700 | [diff] [blame] | 50 | env->Throw(reinterpret_cast<jthrowable>(exception)); |
| 51 | } |
| 52 | |
Orion Hodson | 24b3605 | 2018-11-21 10:59:19 +0000 | [diff] [blame] | 53 | jobject SharedMemory_nCreate(JNIEnv* env, jobject, jstring jname, jint size) { |
John Reck | dea6a02 | 2017-05-25 17:09:33 -0700 | [diff] [blame] | 54 | |
| 55 | // Name is optional so we can't use ScopedUtfChars for this as it throws NPE on null |
| 56 | const char* name = jname ? env->GetStringUTFChars(jname, nullptr) : nullptr; |
| 57 | |
| 58 | int fd = ashmem_create_region(name, size); |
| 59 | |
| 60 | // Capture the error, if there is one, before calling ReleaseStringUTFChars |
| 61 | int err = fd < 0 ? errno : 0; |
| 62 | |
| 63 | if (name) { |
| 64 | env->ReleaseStringUTFChars(jname, name); |
| 65 | } |
| 66 | |
| 67 | if (fd < 0) { |
| 68 | throwErrnoException(env, "SharedMemory_create", err); |
| 69 | return nullptr; |
| 70 | } |
| 71 | |
| 72 | return jniCreateFileDescriptor(env, fd); |
| 73 | } |
| 74 | |
Orion Hodson | 24b3605 | 2018-11-21 10:59:19 +0000 | [diff] [blame] | 75 | jint SharedMemory_nGetSize(JNIEnv* env, jobject, jobject fileDescriptor) { |
John Reck | dea6a02 | 2017-05-25 17:09:33 -0700 | [diff] [blame] | 76 | int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); |
| 77 | if (!ashmem_valid(fd)) { |
| 78 | return -1; |
| 79 | } |
| 80 | size_t size = ashmem_get_size_region(fd); |
| 81 | return static_cast<jint>(std::min(size, static_cast<size_t>(std::numeric_limits<jint>::max()))); |
| 82 | } |
| 83 | |
Orion Hodson | 24b3605 | 2018-11-21 10:59:19 +0000 | [diff] [blame] | 84 | jint SharedMemory_nSetProt(JNIEnv* env, jobject, jobject fileDescriptor, jint prot) { |
John Reck | dea6a02 | 2017-05-25 17:09:33 -0700 | [diff] [blame] | 85 | int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); |
| 86 | int err = 0; |
| 87 | if (ashmem_set_prot_region(fd, prot)) { |
| 88 | err = errno; |
| 89 | } |
| 90 | return err; |
| 91 | } |
| 92 | |
Orion Hodson | 24b3605 | 2018-11-21 10:59:19 +0000 | [diff] [blame] | 93 | const JNINativeMethod methods[] = { |
| 94 | NATIVE_METHOD(SharedMemory, nCreate, "(Ljava/lang/String;I)Ljava/io/FileDescriptor;"), |
| 95 | NATIVE_METHOD(SharedMemory, nGetSize, "(Ljava/io/FileDescriptor;)I"), |
| 96 | NATIVE_METHOD(SharedMemory, nSetProt, "(Ljava/io/FileDescriptor;I)I") |
John Reck | dea6a02 | 2017-05-25 17:09:33 -0700 | [diff] [blame] | 97 | }; |
| 98 | |
| 99 | } // anonymous namespace |
| 100 | |
| 101 | namespace android { |
| 102 | |
Orion Hodson | 24b3605 | 2018-11-21 10:59:19 +0000 | [diff] [blame] | 103 | int register_android_os_SharedMemory(JNIEnv* env) { |
| 104 | errnoExceptionClass = |
| 105 | MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/system/ErrnoException")); |
| 106 | errnoExceptionCtor = |
| 107 | GetMethodIDOrDie(env, errnoExceptionClass, "<init>", "(Ljava/lang/String;I)V"); |
John Reck | dea6a02 | 2017-05-25 17:09:33 -0700 | [diff] [blame] | 108 | return RegisterMethodsOrDie(env, "android/os/SharedMemory", methods, NELEM(methods)); |
| 109 | } |
| 110 | |
| 111 | } // namespace android |