android_os_MemoryFile.cpp revision ad984f19339008f7eb8687aecc1779be70bc1f65
1/* 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> 21#include <android_runtime/AndroidRuntime.h> 22#include "JNIHelp.h" 23#include <unistd.h> 24#include <sys/mman.h> 25 26 27namespace android { 28 29static jobject android_os_MemoryFile_open(JNIEnv* env, jobject clazz, jstring name, jint length) 30{ 31 const char* namestr = (name ? env->GetStringUTFChars(name, NULL) : NULL); 32 33 // round up length to page boundary 34 length = (((length - 1) / getpagesize()) + 1) * getpagesize(); 35 int result = ashmem_create_region(namestr, length); 36 37 if (name) 38 env->ReleaseStringUTFChars(name, namestr); 39 40 if (result < 0) { 41 jniThrowException(env, "java/io/IOException", "ashmem_create_region failed"); 42 return NULL; 43 } 44 45 return jniCreateFileDescriptor(env, result); 46} 47 48static jint android_os_MemoryFile_mmap(JNIEnv* env, jobject clazz, jobject fileDescriptor, 49 jint length) 50{ 51 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 52 jint result = (jint)mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); 53 if (!result) 54 jniThrowException(env, "java/io/IOException", "mmap failed"); 55 return result; 56} 57 58static void android_os_MemoryFile_munmap(JNIEnv* env, jobject clazz, jint addr, jint length) 59{ 60 int result = munmap((void *)addr, length); 61 if (result < 0) 62 jniThrowException(env, "java/io/IOException", "munmap failed"); 63} 64 65static void android_os_MemoryFile_close(JNIEnv* env, jobject clazz, jobject fileDescriptor) 66{ 67 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 68 if (fd >= 0) { 69 jniSetFileDescriptorOfFD(env, fileDescriptor, -1); 70 close(fd); 71 } 72} 73 74static jint android_os_MemoryFile_read(JNIEnv* env, jobject clazz, 75 jobject fileDescriptor, jint address, jbyteArray buffer, jint srcOffset, jint destOffset, 76 jint count, jboolean unpinned) 77{ 78 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 79 if (unpinned && ashmem_pin_region(fd, 0, 0) == ASHMEM_WAS_PURGED) { 80 ashmem_unpin_region(fd, 0, 0); 81 jniThrowException(env, "java/io/IOException", "ashmem region was purged"); 82 return -1; 83 } 84 85 env->SetByteArrayRegion(buffer, destOffset, count, (const jbyte *)address + srcOffset); 86 87 if (unpinned) { 88 ashmem_unpin_region(fd, 0, 0); 89 } 90 return count; 91} 92 93static jint android_os_MemoryFile_write(JNIEnv* env, jobject clazz, 94 jobject fileDescriptor, jint address, jbyteArray buffer, jint srcOffset, jint destOffset, 95 jint count, jboolean unpinned) 96{ 97 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 98 if (unpinned && ashmem_pin_region(fd, 0, 0) == ASHMEM_WAS_PURGED) { 99 ashmem_unpin_region(fd, 0, 0); 100 jniThrowException(env, "java/io/IOException", "ashmem region was purged"); 101 return -1; 102 } 103 104 env->GetByteArrayRegion(buffer, srcOffset, count, (jbyte *)address + destOffset); 105 106 if (unpinned) { 107 ashmem_unpin_region(fd, 0, 0); 108 } 109 return count; 110} 111 112static void android_os_MemoryFile_pin(JNIEnv* env, jobject clazz, jobject fileDescriptor, jboolean pin) 113{ 114 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor); 115 int result = (pin ? ashmem_pin_region(fd, 0, 0) : ashmem_unpin_region(fd, 0, 0)); 116 if (result < 0) { 117 jniThrowException(env, "java/io/IOException", NULL); 118 } 119} 120 121static const JNINativeMethod methods[] = { 122 {"native_open", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_MemoryFile_open}, 123 {"native_mmap", "(Ljava/io/FileDescriptor;I)I", (void*)android_os_MemoryFile_mmap}, 124 {"native_munmap", "(II)V", (void*)android_os_MemoryFile_munmap}, 125 {"native_close", "(Ljava/io/FileDescriptor;)V", (void*)android_os_MemoryFile_close}, 126 {"native_read", "(Ljava/io/FileDescriptor;I[BIIIZ)I", (void*)android_os_MemoryFile_read}, 127 {"native_write", "(Ljava/io/FileDescriptor;I[BIIIZ)V", (void*)android_os_MemoryFile_write}, 128 {"native_pin", "(Ljava/io/FileDescriptor;Z)V", (void*)android_os_MemoryFile_pin}, 129}; 130 131static const char* const kClassPathName = "android/os/MemoryFile"; 132 133int register_android_os_MemoryFile(JNIEnv* env) 134{ 135 jclass clazz; 136 137 clazz = env->FindClass(kClassPathName); 138 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.FileUtils"); 139 140 return AndroidRuntime::registerNativeMethods( 141 env, kClassPathName, 142 methods, NELEM(methods)); 143} 144 145} 146