android_os_MemoryFile.cpp revision 54b6cfa9a9e5b861a9930af873580d6dc20f773c
1d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala/* 2d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala * Copyright (C) 2008 The Android Open Source Project 3d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala * 4d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala * Licensed under the Apache License, Version 2.0 (the "License"); 5d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala * you may not use this file except in compliance with the License. 6d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala * You may obtain a copy of the License at 7d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala * 8d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala * http://www.apache.org/licenses/LICENSE-2.0 9d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala * 10d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala * Unless required by applicable law or agreed to in writing, software 11d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala * distributed under the License is distributed on an "AS IS" BASIS, 12d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala * See the License for the specific language governing permissions and 14d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala * limitations under the License. 15d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala */ 16d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala 17d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala#define LOG_TAG "MemoryFile" 18d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala#include <utils/Log.h> 19d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala 20d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala#include <cutils/ashmem.h> 21d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala#include <android_runtime/AndroidRuntime.h> 22d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala#include "JNIHelp.h" 23d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala#include <unistd.h> 2471c73a2985a7ac65ee597be3441ab300fa56e22eEmilian Peev#include <sys/mman.h> 25d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala 26d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala 27d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvalanamespace android { 28f51fca277eb5b86bd0b2e3fc90ecb2b63089de29Eino-Ville Talvala 29d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvalastatic jint android_os_MemoryFile_open(JNIEnv* env, jobject clazz, jstring name, jint length) 30d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala{ 31d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala const char* namestr = (name ? env->GetStringUTFChars(name, NULL) : NULL); 32d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala 33d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala // round up length to page boundary 34d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala length = (((length - 1) / getpagesize()) + 1) * getpagesize(); 35d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala int result = ashmem_create_region(namestr, length); 36d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala 37d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala if (name) 38d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala env->ReleaseStringUTFChars(name, namestr); 39d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala 40d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala if (result < 0) 41d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala jniThrowException(env, "java/io/IOException", "ashmem_create_region failed"); 42d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala return result; 43d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala} 44d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala 45d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvalastatic jint android_os_MemoryFile_mmap(JNIEnv* env, jobject clazz, jint fd, jint length) 46d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala{ 47d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala jint result = (jint)mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); 48d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala if (!result) 49d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala jniThrowException(env, "java/io/IOException", "mmap failed"); 50d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala return result; 51d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala} 52d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala 53d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvalastatic void android_os_MemoryFile_close(JNIEnv* env, jobject clazz, jint fd) 54d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala{ 55d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala close(fd); 56d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala} 57d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala 58d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvalastatic jint android_os_MemoryFile_read(JNIEnv* env, jobject clazz, 59d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala jint fd, jint address, jbyteArray buffer, jint srcOffset, jint destOffset, 60d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala jint count, jboolean unpinned) 61d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala{ 62d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala if (unpinned && ashmem_pin_region(fd, 0, 0) == ASHMEM_WAS_PURGED) { 63d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala ashmem_unpin_region(fd, 0, 0); 64d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala jniThrowException(env, "java/io/IOException", "ashmem region was purged"); 65d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala return -1; 66d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala } 67d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala 68d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala jbyte* bytes = env->GetByteArrayElements(buffer, 0); 69d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala memcpy(bytes + destOffset, (const char *)address + srcOffset, count); 70d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala env->ReleaseByteArrayElements(buffer, bytes, 0); 71d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala 72d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala if (unpinned) { 73d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala ashmem_unpin_region(fd, 0, 0); 74d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala } 75d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala return count; 76d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala} 77d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala 78d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvalastatic jint android_os_MemoryFile_write(JNIEnv* env, jobject clazz, 79d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala jint fd, jint address, jbyteArray buffer, jint srcOffset, jint destOffset, 80d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala jint count, jboolean unpinned) 81d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala{ 82d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala if (unpinned && ashmem_pin_region(fd, 0, 0) == ASHMEM_WAS_PURGED) { 83d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala ashmem_unpin_region(fd, 0, 0); 84d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala jniThrowException(env, "java/io/IOException", "ashmem region was purged"); 85d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala return -1; 86d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala } 87d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala 88f51fca277eb5b86bd0b2e3fc90ecb2b63089de29Eino-Ville Talvala jbyte* bytes = env->GetByteArrayElements(buffer, 0); 89d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala memcpy((char *)address + destOffset, bytes + srcOffset, count); 90d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala env->ReleaseByteArrayElements(buffer, bytes, 0); 91d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala 92d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala if (unpinned) { 93d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala ashmem_unpin_region(fd, 0, 0); 94d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala } 95d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala return count; 96d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala} 97d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala 98d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvalastatic void android_os_MemoryFile_pin(JNIEnv* env, jobject clazz, jint fd, jboolean pin) 99d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala{ 100d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala int result = (pin ? ashmem_pin_region(fd, 0, 0) : ashmem_unpin_region(fd, 0, 0)); 101d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala if (result < 0) { 102d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala jniThrowException(env, "java/io/IOException", NULL); 103d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala } 104d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala} 105d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala 106d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvalastatic const JNINativeMethod methods[] = { 107f51fca277eb5b86bd0b2e3fc90ecb2b63089de29Eino-Ville Talvala {"native_open", "(Ljava/lang/String;I)I", (void*)android_os_MemoryFile_open}, 108f51fca277eb5b86bd0b2e3fc90ecb2b63089de29Eino-Ville Talvala {"native_mmap", "(II)I", (void*)android_os_MemoryFile_mmap}, 109f51fca277eb5b86bd0b2e3fc90ecb2b63089de29Eino-Ville Talvala {"native_close", "(I)V", (void*)android_os_MemoryFile_close}, 110f51fca277eb5b86bd0b2e3fc90ecb2b63089de29Eino-Ville Talvala {"native_read", "(II[BIIIZ)I", (void*)android_os_MemoryFile_read}, 111f51fca277eb5b86bd0b2e3fc90ecb2b63089de29Eino-Ville Talvala {"native_write", "(II[BIIIZ)V", (void*)android_os_MemoryFile_write}, 112f51fca277eb5b86bd0b2e3fc90ecb2b63089de29Eino-Ville Talvala {"native_pin", "(IZ)V", (void*)android_os_MemoryFile_pin}, 113f51fca277eb5b86bd0b2e3fc90ecb2b63089de29Eino-Ville Talvala}; 114f51fca277eb5b86bd0b2e3fc90ecb2b63089de29Eino-Ville Talvala 115f51fca277eb5b86bd0b2e3fc90ecb2b63089de29Eino-Ville Talvalastatic const char* const kClassPathName = "android/os/MemoryFile"; 116f51fca277eb5b86bd0b2e3fc90ecb2b63089de29Eino-Ville Talvala 117d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvalaint register_android_os_MemoryFile(JNIEnv* env) 118d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala{ 119d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala jclass clazz; 120d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala 121d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala clazz = env->FindClass(kClassPathName); 122d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.FileUtils"); 123d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala 124f51fca277eb5b86bd0b2e3fc90ecb2b63089de29Eino-Ville Talvala return AndroidRuntime::registerNativeMethods( 125d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala env, kClassPathName, 126d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala methods, NELEM(methods)); 127d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala} 128d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala 129d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala} 130d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala