blob: 971f87c2969cb0e64945261fe923d6ffcda4265e [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/* //device/libs/android_runtime/android_os_ParcelFileDescriptor.cpp
2**
3** Copyright 2008, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -070018//#define LOG_NDEBUG 0
19
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020#include "JNIHelp.h"
21
22#include <fcntl.h>
23#include <sys/stat.h>
24#include <stdio.h>
25
26#include <utils/Log.h>
27
28#include <android_runtime/AndroidRuntime.h>
29
30namespace android
31{
32
33static struct file_descriptor_offsets_t
34{
35 jclass mClass;
36 jmethodID mConstructor;
37 jfieldID mDescriptor;
38} gFileDescriptorOffsets;
39
40static struct socket_offsets_t
41{
42 jfieldID mSocketImpl;
43} gSocketOffsets;
44
45static struct socket_impl_offsets_t
46{
47 jfieldID mFileDescriptor;
48} gSocketImplOffsets;
49
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -070050static struct parcel_file_descriptor_offsets_t
51{
52 jclass mClass;
53 jfieldID mFileDescriptor;
54} gParcelFileDescriptorOffsets;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055
56static jobject android_os_ParcelFileDescriptor_getFileDescriptorFromSocket(JNIEnv* env,
57 jobject clazz, jobject object)
58{
59 jobject socketImpl = env->GetObjectField(object, gSocketOffsets.mSocketImpl);
60 jobject fileDescriptor = env->GetObjectField(socketImpl, gSocketImplOffsets.mFileDescriptor);
61 jint fd = env->GetIntField(fileDescriptor, gFileDescriptorOffsets.mDescriptor);
62 jobject fileDescriptorClone = env->NewObject(gFileDescriptorOffsets.mClass,
63 gFileDescriptorOffsets.mConstructor);
64 if (fileDescriptorClone != NULL) {
65 env->SetIntField(fileDescriptorClone, gFileDescriptorOffsets.mDescriptor, dup(fd));
66 }
67 return fileDescriptorClone;
68}
69
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -070070static jint getFd(JNIEnv* env, jobject clazz)
71{
72 jobject descriptor = env->GetObjectField(clazz, gParcelFileDescriptorOffsets.mFileDescriptor);
73 if (descriptor == NULL) return -1;
74 return env->GetIntField(descriptor, gFileDescriptorOffsets.mDescriptor);
75}
76
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077static jlong android_os_ParcelFileDescriptor_getStatSize(JNIEnv* env,
78 jobject clazz)
79{
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -070080 jint fd = getFd(env, clazz);
81 if (fd < 0) {
82 jniThrowException(env, "java/lang/IllegalArgumentException", "bad file descriptor");
83 return -1;
84 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085
86 struct stat st;
87 if (fstat(fd, &st) != 0) {
88 return -1;
89 }
90
91 if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
92 return st.st_size;
93 }
94
95 return -1;
96}
97
98static jlong android_os_ParcelFileDescriptor_seekTo(JNIEnv* env,
99 jobject clazz, jlong pos)
100{
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700101 jint fd = getFd(env, clazz);
102 if (fd < 0) {
103 jniThrowException(env, "java/lang/IllegalArgumentException", "bad file descriptor");
104 return -1;
105 }
106
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107 return lseek(fd, pos, SEEK_SET);
108}
109
110static const JNINativeMethod gParcelFileDescriptorMethods[] = {
111 {"getFileDescriptorFromSocket", "(Ljava/net/Socket;)Ljava/io/FileDescriptor;",
112 (void*)android_os_ParcelFileDescriptor_getFileDescriptorFromSocket},
113 {"getStatSize", "()J",
114 (void*)android_os_ParcelFileDescriptor_getStatSize},
115 {"seekTo", "(J)J",
116 (void*)android_os_ParcelFileDescriptor_seekTo}
117};
118
119const char* const kParcelFileDescriptorPathName = "android/os/ParcelFileDescriptor";
120
121int register_android_os_ParcelFileDescriptor(JNIEnv* env)
122{
123 jclass clazz;
124
125 clazz = env->FindClass("java/net/Socket");
126 LOG_FATAL_IF(clazz == NULL, "Unable to find class java.net.Socket");
127 gSocketOffsets.mSocketImpl = env->GetFieldID(clazz, "impl", "Ljava/net/SocketImpl;");
128 LOG_FATAL_IF(gSocketOffsets.mSocketImpl == NULL,
129 "Unable to find impl field in java.net.Socket");
130
131 clazz = env->FindClass("java/net/SocketImpl");
132 LOG_FATAL_IF(clazz == NULL, "Unable to find class java.net.SocketImpl");
133 gSocketImplOffsets.mFileDescriptor = env->GetFieldID(clazz, "fd", "Ljava/io/FileDescriptor;");
134 LOG_FATAL_IF(gSocketImplOffsets.mFileDescriptor == NULL,
135 "Unable to find fd field in java.net.SocketImpl");
136
137 clazz = env->FindClass("java/io/FileDescriptor");
138 LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
139 gFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
140 gFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "()V");
141 gFileDescriptorOffsets.mDescriptor = env->GetFieldID(clazz, "descriptor", "I");
142 LOG_FATAL_IF(gFileDescriptorOffsets.mDescriptor == NULL,
143 "Unable to find descriptor field in java.io.FileDescriptor");
144
145 clazz = env->FindClass(kParcelFileDescriptorPathName);
146 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor");
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700147 gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
148 gParcelFileDescriptorOffsets.mFileDescriptor = env->GetFieldID(clazz, "mFileDescriptor", "Ljava/io/FileDescriptor;");
149 LOG_FATAL_IF(gParcelFileDescriptorOffsets.mFileDescriptor == NULL,
150 "Unable to find mFileDescriptor field in android.os.ParcelFileDescriptor");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151
152 return AndroidRuntime::registerNativeMethods(
153 env, kParcelFileDescriptorPathName,
154 gParcelFileDescriptorMethods, NELEM(gParcelFileDescriptorMethods));
155}
156
157}