android_os_MemoryFile.cpp revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
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 jint 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 result;
43}
44
45static jint android_os_MemoryFile_mmap(JNIEnv* env, jobject clazz, jint fd, jint length)
46{
47    jint result = (jint)mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
48    if (!result)
49        jniThrowException(env, "java/io/IOException", "mmap failed");
50    return result;
51}
52
53static void android_os_MemoryFile_close(JNIEnv* env, jobject clazz, jint fd)
54{
55    close(fd);
56}
57
58static jint android_os_MemoryFile_read(JNIEnv* env, jobject clazz,
59        jint fd, jint address, jbyteArray buffer, jint srcOffset, jint destOffset,
60        jint count, jboolean unpinned)
61{
62    if (unpinned && ashmem_pin_region(fd, 0, 0) == ASHMEM_WAS_PURGED) {
63        ashmem_unpin_region(fd, 0, 0);
64        jniThrowException(env, "java/io/IOException", "ashmem region was purged");
65        return -1;
66    }
67
68    jbyte* bytes = env->GetByteArrayElements(buffer, 0);
69    memcpy(bytes + destOffset, (const char *)address + srcOffset, count);
70    env->ReleaseByteArrayElements(buffer, bytes, 0);
71
72    if (unpinned) {
73        ashmem_unpin_region(fd, 0, 0);
74    }
75    return count;
76}
77
78static jint android_os_MemoryFile_write(JNIEnv* env, jobject clazz,
79        jint fd, jint address, jbyteArray buffer, jint srcOffset, jint destOffset,
80        jint count, jboolean unpinned)
81{
82    if (unpinned && ashmem_pin_region(fd, 0, 0) == ASHMEM_WAS_PURGED) {
83        ashmem_unpin_region(fd, 0, 0);
84        jniThrowException(env, "java/io/IOException", "ashmem region was purged");
85        return -1;
86    }
87
88    jbyte* bytes = env->GetByteArrayElements(buffer, 0);
89    memcpy((char *)address + destOffset, bytes + srcOffset, count);
90    env->ReleaseByteArrayElements(buffer, bytes, 0);
91
92    if (unpinned) {
93        ashmem_unpin_region(fd, 0, 0);
94    }
95    return count;
96}
97
98static void android_os_MemoryFile_pin(JNIEnv* env, jobject clazz, jint fd, jboolean pin)
99{
100    int result = (pin ? ashmem_pin_region(fd, 0, 0) : ashmem_unpin_region(fd, 0, 0));
101    if (result < 0) {
102        jniThrowException(env, "java/io/IOException", NULL);
103    }
104}
105
106static const JNINativeMethod methods[] = {
107	{"native_open",  "(Ljava/lang/String;I)I", (void*)android_os_MemoryFile_open},
108    {"native_mmap",  "(II)I", (void*)android_os_MemoryFile_mmap},
109    {"native_close", "(I)V", (void*)android_os_MemoryFile_close},
110    {"native_read",  "(II[BIIIZ)I", (void*)android_os_MemoryFile_read},
111    {"native_write", "(II[BIIIZ)V", (void*)android_os_MemoryFile_write},
112    {"native_pin",   "(IZ)V", (void*)android_os_MemoryFile_pin},
113};
114
115static const char* const kClassPathName = "android/os/MemoryFile";
116
117int register_android_os_MemoryFile(JNIEnv* env)
118{
119    jclass clazz;
120
121    clazz = env->FindClass(kClassPathName);
122    LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.FileUtils");
123
124    return AndroidRuntime::registerNativeMethods(
125        env, kClassPathName,
126        methods, NELEM(methods));
127}
128
129}
130