2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #define LOG_TAG "MemoryFile"
18 #include <utils/Log.h>
20 #include <cutils/ashmem.h>
21 #include <android_runtime/AndroidRuntime.h>
29 static jobject android_os_MemoryFile_open(JNIEnv* env, jobject clazz, jstring name, jint length)
31 const char* namestr = (name ? env->GetStringUTFChars(name, NULL) : NULL);
33 int result = ashmem_create_region(namestr, length);
36 env->ReleaseStringUTFChars(name, namestr);
39 jniThrowException(env, "java/io/IOException", "ashmem_create_region failed");
43 return jniCreateFileDescriptor(env, result);
46 static jint android_os_MemoryFile_mmap(JNIEnv* env, jobject clazz, jobject fileDescriptor,
47 jint length, jint prot)
49 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
50 jint result = (jint)mmap(NULL, length, prot, MAP_SHARED, fd, 0);
52 jniThrowException(env, "java/io/IOException", "mmap failed");
56 static void android_os_MemoryFile_munmap(JNIEnv* env, jobject clazz, jint addr, jint length)
58 int result = munmap((void *)addr, length);
60 jniThrowException(env, "java/io/IOException", "munmap failed");
63 static void android_os_MemoryFile_close(JNIEnv* env, jobject clazz, jobject fileDescriptor)
65 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
67 jniSetFileDescriptorOfFD(env, fileDescriptor, -1);
72 static jint android_os_MemoryFile_read(JNIEnv* env, jobject clazz,
73 jobject fileDescriptor, jint address, jbyteArray buffer, jint srcOffset, jint destOffset,
74 jint count, jboolean unpinned)
76 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
77 if (unpinned && ashmem_pin_region(fd, 0, 0) == ASHMEM_WAS_PURGED) {
78 ashmem_unpin_region(fd, 0, 0);
79 jniThrowException(env, "java/io/IOException", "ashmem region was purged");
83 env->SetByteArrayRegion(buffer, destOffset, count, (const jbyte *)address + srcOffset);
86 ashmem_unpin_region(fd, 0, 0);
91 static jint android_os_MemoryFile_write(JNIEnv* env, jobject clazz,
92 jobject fileDescriptor, jint address, jbyteArray buffer, jint srcOffset, jint destOffset,
93 jint count, jboolean unpinned)
95 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
96 if (unpinned && ashmem_pin_region(fd, 0, 0) == ASHMEM_WAS_PURGED) {
97 ashmem_unpin_region(fd, 0, 0);
98 jniThrowException(env, "java/io/IOException", "ashmem region was purged");
102 env->GetByteArrayRegion(buffer, srcOffset, count, (jbyte *)address + destOffset);
105 ashmem_unpin_region(fd, 0, 0);
110 static void android_os_MemoryFile_pin(JNIEnv* env, jobject clazz, jobject fileDescriptor, jboolean pin)
112 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
113 int result = (pin ? ashmem_pin_region(fd, 0, 0) : ashmem_unpin_region(fd, 0, 0));
115 jniThrowException(env, "java/io/IOException", NULL);
119 static jint android_os_MemoryFile_get_size(JNIEnv* env, jobject clazz,
120 jobject fileDescriptor) {
121 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
122 // Use ASHMEM_GET_SIZE to find out if the fd refers to an ashmem region.
123 // ASHMEM_GET_SIZE should succeed for all ashmem regions, and the kernel
124 // should return ENOTTY for all other valid file descriptors
125 int result = ashmem_get_size_region(fd);
127 if (errno == ENOTTY) {
128 // ENOTTY means that the ioctl does not apply to this object,
129 // i.e., it is not an ashmem region.
132 // Some other error, throw exception
133 jniThrowIOException(env, errno);
136 return (jint) result;
139 static const JNINativeMethod methods[] = {
140 {"native_open", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_MemoryFile_open},
141 {"native_mmap", "(Ljava/io/FileDescriptor;II)I", (void*)android_os_MemoryFile_mmap},
142 {"native_munmap", "(II)V", (void*)android_os_MemoryFile_munmap},
143 {"native_close", "(Ljava/io/FileDescriptor;)V", (void*)android_os_MemoryFile_close},
144 {"native_read", "(Ljava/io/FileDescriptor;I[BIIIZ)I", (void*)android_os_MemoryFile_read},
145 {"native_write", "(Ljava/io/FileDescriptor;I[BIIIZ)V", (void*)android_os_MemoryFile_write},
146 {"native_pin", "(Ljava/io/FileDescriptor;Z)V", (void*)android_os_MemoryFile_pin},
147 {"native_get_size", "(Ljava/io/FileDescriptor;)I",
148 (void*)android_os_MemoryFile_get_size}
151 int register_android_os_MemoryFile(JNIEnv* env)
153 return AndroidRuntime::registerNativeMethods(
154 env, "android/os/MemoryFile",
155 methods, NELEM(methods));