OSDN Git Service

am b7f0d825: am 691257b1: am 68e37dac: am 55f115a3: Merge "stagefright: Only use...
[android-x86/frameworks-base.git] / core / jni / android_os_MemoryFile.cpp
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
27 namespace android {
28
29 static 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     int result = ashmem_create_region(namestr, length);
34
35     if (name)
36         env->ReleaseStringUTFChars(name, namestr);
37
38     if (result < 0) {
39         jniThrowException(env, "java/io/IOException", "ashmem_create_region failed");
40         return NULL;
41     }
42
43     return jniCreateFileDescriptor(env, result);
44 }
45
46 static jint android_os_MemoryFile_mmap(JNIEnv* env, jobject clazz, jobject fileDescriptor,
47         jint length, jint prot)
48 {
49     int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
50     jint result = (jint)mmap(NULL, length, prot, MAP_SHARED, fd, 0);
51     if (!result)
52         jniThrowException(env, "java/io/IOException", "mmap failed");
53     return result;
54 }
55
56 static void android_os_MemoryFile_munmap(JNIEnv* env, jobject clazz, jint addr, jint length)
57 {
58     int result = munmap((void *)addr, length);
59     if (result < 0)
60         jniThrowException(env, "java/io/IOException", "munmap failed");
61 }
62
63 static void android_os_MemoryFile_close(JNIEnv* env, jobject clazz, jobject fileDescriptor)
64 {
65     int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
66     if (fd >= 0) {
67         jniSetFileDescriptorOfFD(env, fileDescriptor, -1);
68         close(fd);
69     }
70 }
71
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)
75 {
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");
80         return -1;
81     }
82
83     env->SetByteArrayRegion(buffer, destOffset, count, (const jbyte *)address + srcOffset);
84
85     if (unpinned) {
86         ashmem_unpin_region(fd, 0, 0);
87     }
88     return count;
89 }
90
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)
94 {
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");
99         return -1;
100     }
101
102     env->GetByteArrayRegion(buffer, srcOffset, count, (jbyte *)address + destOffset);
103
104     if (unpinned) {
105         ashmem_unpin_region(fd, 0, 0);
106     }
107     return count;
108 }
109
110 static void android_os_MemoryFile_pin(JNIEnv* env, jobject clazz, jobject fileDescriptor, jboolean pin)
111 {
112     int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
113     int result = (pin ? ashmem_pin_region(fd, 0, 0) : ashmem_unpin_region(fd, 0, 0));
114     if (result < 0) {
115         jniThrowException(env, "java/io/IOException", NULL);
116     }
117 }
118
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);
126     if (result < 0) {
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.
130             return (jint) -1;
131         }
132         // Some other error, throw exception
133         jniThrowIOException(env, errno);
134         return (jint) -1;
135     }
136     return (jint) result;
137 }
138
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}
149 };
150
151 int register_android_os_MemoryFile(JNIEnv* env)
152 {
153     return AndroidRuntime::registerNativeMethods(
154         env, "android/os/MemoryFile",
155         methods, NELEM(methods));
156 }
157
158 }