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