blob: c198a733103dda9476472c5d4763c9d403beff8b [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 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 "MemoryFile"
18#include <utils/Log.h>
19
20#include <cutils/ashmem.h>
Andreas Gampeed6b9df2014-11-20 22:02:20 -080021#include "core_jni_helpers.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022#include "JNIHelp.h"
23#include <unistd.h>
24#include <sys/mman.h>
25
26
27namespace android {
28
Bjorn Bringert761e0912009-05-29 11:46:12 +010029static jobject android_os_MemoryFile_open(JNIEnv* env, jobject clazz, jstring name, jint length)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030{
31 const char* namestr = (name ? env->GetStringUTFChars(name, NULL) : NULL);
32
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033 int result = ashmem_create_region(namestr, length);
34
35 if (name)
36 env->ReleaseStringUTFChars(name, namestr);
37
Bjorn Bringert761e0912009-05-29 11:46:12 +010038 if (result < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039 jniThrowException(env, "java/io/IOException", "ashmem_create_region failed");
Bjorn Bringert963cd0062009-05-29 14:05:12 +010040 return NULL;
Bjorn Bringert761e0912009-05-29 11:46:12 +010041 }
42
43 return jniCreateFileDescriptor(env, result);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044}
45
Ashok Bhatc20cadb2014-01-10 13:40:47 +000046static jlong android_os_MemoryFile_mmap(JNIEnv* env, jobject clazz, jobject fileDescriptor,
Bjorn Bringert963cd0062009-05-29 14:05:12 +010047 jint length, jint prot)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048{
Bjorn Bringert761e0912009-05-29 11:46:12 +010049 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
Narayan Kamath6ffb0912014-01-16 13:17:03 +000050 void* result = mmap(NULL, length, prot, MAP_SHARED, fd, 0);
51 if (result == MAP_FAILED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052 jniThrowException(env, "java/io/IOException", "mmap failed");
Narayan Kamath6ffb0912014-01-16 13:17:03 +000053 }
54 return reinterpret_cast<jlong>(result);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055}
56
Ashok Bhatc20cadb2014-01-10 13:40:47 +000057static void android_os_MemoryFile_munmap(JNIEnv* env, jobject clazz, jlong addr, jint length)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058{
Narayan Kamath6ffb0912014-01-16 13:17:03 +000059 int result = munmap(reinterpret_cast<void *>(addr), length);
Bjorn Bringert761e0912009-05-29 11:46:12 +010060 if (result < 0)
61 jniThrowException(env, "java/io/IOException", "munmap failed");
62}
63
64static void android_os_MemoryFile_close(JNIEnv* env, jobject clazz, jobject fileDescriptor)
65{
66 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
67 if (fd >= 0) {
68 jniSetFileDescriptorOfFD(env, fileDescriptor, -1);
69 close(fd);
70 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071}
72
73static jint android_os_MemoryFile_read(JNIEnv* env, jobject clazz,
Ashok Bhatc20cadb2014-01-10 13:40:47 +000074 jobject fileDescriptor, jlong address, jbyteArray buffer, jint srcOffset, jint destOffset,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075 jint count, jboolean unpinned)
76{
Bjorn Bringert761e0912009-05-29 11:46:12 +010077 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078 if (unpinned && ashmem_pin_region(fd, 0, 0) == ASHMEM_WAS_PURGED) {
79 ashmem_unpin_region(fd, 0, 0);
80 jniThrowException(env, "java/io/IOException", "ashmem region was purged");
81 return -1;
82 }
83
Bjorn Bringertad984f12009-06-01 18:33:33 +010084 env->SetByteArrayRegion(buffer, destOffset, count, (const jbyte *)address + srcOffset);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085
86 if (unpinned) {
87 ashmem_unpin_region(fd, 0, 0);
88 }
89 return count;
90}
91
92static jint android_os_MemoryFile_write(JNIEnv* env, jobject clazz,
Ashok Bhatc20cadb2014-01-10 13:40:47 +000093 jobject fileDescriptor, jlong address, jbyteArray buffer, jint srcOffset, jint destOffset,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094 jint count, jboolean unpinned)
95{
Bjorn Bringert761e0912009-05-29 11:46:12 +010096 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097 if (unpinned && ashmem_pin_region(fd, 0, 0) == ASHMEM_WAS_PURGED) {
98 ashmem_unpin_region(fd, 0, 0);
99 jniThrowException(env, "java/io/IOException", "ashmem region was purged");
100 return -1;
101 }
102
Bjorn Bringertad984f12009-06-01 18:33:33 +0100103 env->GetByteArrayRegion(buffer, srcOffset, count, (jbyte *)address + destOffset);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104
105 if (unpinned) {
106 ashmem_unpin_region(fd, 0, 0);
107 }
108 return count;
109}
110
Bjorn Bringert761e0912009-05-29 11:46:12 +0100111static void android_os_MemoryFile_pin(JNIEnv* env, jobject clazz, jobject fileDescriptor, jboolean pin)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112{
Bjorn Bringert761e0912009-05-29 11:46:12 +0100113 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114 int result = (pin ? ashmem_pin_region(fd, 0, 0) : ashmem_unpin_region(fd, 0, 0));
115 if (result < 0) {
116 jniThrowException(env, "java/io/IOException", NULL);
117 }
118}
119
Marco Nelissen7bcbd512009-06-23 10:34:55 -0700120static jint android_os_MemoryFile_get_size(JNIEnv* env, jobject clazz,
Bjorn Bringert963cd0062009-05-29 14:05:12 +0100121 jobject fileDescriptor) {
122 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
123 // Use ASHMEM_GET_SIZE to find out if the fd refers to an ashmem region.
124 // ASHMEM_GET_SIZE should succeed for all ashmem regions, and the kernel
125 // should return ENOTTY for all other valid file descriptors
126 int result = ashmem_get_size_region(fd);
127 if (result < 0) {
128 if (errno == ENOTTY) {
129 // ENOTTY means that the ioctl does not apply to this object,
130 // i.e., it is not an ashmem region.
Marco Nelissenec100902009-06-17 08:56:59 -0700131 return (jint) -1;
Bjorn Bringert963cd0062009-05-29 14:05:12 +0100132 }
133 // Some other error, throw exception
134 jniThrowIOException(env, errno);
Marco Nelissenec100902009-06-17 08:56:59 -0700135 return (jint) -1;
Bjorn Bringert963cd0062009-05-29 14:05:12 +0100136 }
Marco Nelissenec100902009-06-17 08:56:59 -0700137 return (jint) result;
Bjorn Bringert963cd0062009-05-29 14:05:12 +0100138}
139
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140static const JNINativeMethod methods[] = {
Bjorn Bringert761e0912009-05-29 11:46:12 +0100141 {"native_open", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_MemoryFile_open},
Ashok Bhatc20cadb2014-01-10 13:40:47 +0000142 {"native_mmap", "(Ljava/io/FileDescriptor;II)J", (void*)android_os_MemoryFile_mmap},
143 {"native_munmap", "(JI)V", (void*)android_os_MemoryFile_munmap},
Bjorn Bringert761e0912009-05-29 11:46:12 +0100144 {"native_close", "(Ljava/io/FileDescriptor;)V", (void*)android_os_MemoryFile_close},
Ashok Bhatc20cadb2014-01-10 13:40:47 +0000145 {"native_read", "(Ljava/io/FileDescriptor;J[BIIIZ)I", (void*)android_os_MemoryFile_read},
146 {"native_write", "(Ljava/io/FileDescriptor;J[BIIIZ)V", (void*)android_os_MemoryFile_write},
Bjorn Bringert761e0912009-05-29 11:46:12 +0100147 {"native_pin", "(Ljava/io/FileDescriptor;Z)V", (void*)android_os_MemoryFile_pin},
Marco Nelissen7bcbd512009-06-23 10:34:55 -0700148 {"native_get_size", "(Ljava/io/FileDescriptor;)I",
149 (void*)android_os_MemoryFile_get_size}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150};
151
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152int register_android_os_MemoryFile(JNIEnv* env)
153{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800154 return RegisterMethodsOrDie(env, "android/os/MemoryFile", methods, NELEM(methods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155}
156
157}