android_os_ParcelFileDescriptor.cpp revision 54b6cfa9a9e5b861a9930af873580d6dc20f773c
1/* //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
18#include "JNIHelp.h"
19
20#include <fcntl.h>
21#include <sys/stat.h>
22#include <stdio.h>
23
24#include <utils/Log.h>
25
26#include <android_runtime/AndroidRuntime.h>
27
28namespace android
29{
30
31static struct file_descriptor_offsets_t
32{
33    jclass mClass;
34    jmethodID mConstructor;
35    jfieldID mDescriptor;
36} gFileDescriptorOffsets;
37
38static struct socket_offsets_t
39{
40    jfieldID mSocketImpl;
41} gSocketOffsets;
42
43static struct socket_impl_offsets_t
44{
45    jfieldID mFileDescriptor;
46} gSocketImplOffsets;
47
48
49static jobject android_os_ParcelFileDescriptor_getFileDescriptorFromSocket(JNIEnv* env,
50    jobject clazz, jobject object)
51{
52    jobject socketImpl = env->GetObjectField(object, gSocketOffsets.mSocketImpl);
53    jobject fileDescriptor = env->GetObjectField(socketImpl, gSocketImplOffsets.mFileDescriptor);
54    jint fd = env->GetIntField(fileDescriptor, gFileDescriptorOffsets.mDescriptor);
55    jobject fileDescriptorClone = env->NewObject(gFileDescriptorOffsets.mClass,
56        gFileDescriptorOffsets.mConstructor);
57    if (fileDescriptorClone != NULL) {
58        env->SetIntField(fileDescriptorClone, gFileDescriptorOffsets.mDescriptor, dup(fd));
59    }
60    return fileDescriptorClone;
61}
62
63static const JNINativeMethod gParcelFileDescriptorMethods[] = {
64    {"getFileDescriptorFromSocket", "(Ljava/net/Socket;)Ljava/io/FileDescriptor;",
65        (void*)android_os_ParcelFileDescriptor_getFileDescriptorFromSocket}
66};
67
68const char* const kParcelFileDescriptorPathName = "android/os/ParcelFileDescriptor";
69
70int register_android_os_ParcelFileDescriptor(JNIEnv* env)
71{
72    jclass clazz;
73
74    clazz = env->FindClass("java/net/Socket");
75    LOG_FATAL_IF(clazz == NULL, "Unable to find class java.net.Socket");
76    gSocketOffsets.mSocketImpl = env->GetFieldID(clazz, "impl", "Ljava/net/SocketImpl;");
77    LOG_FATAL_IF(gSocketOffsets.mSocketImpl == NULL,
78        "Unable to find impl field in java.net.Socket");
79
80    clazz = env->FindClass("java/net/SocketImpl");
81    LOG_FATAL_IF(clazz == NULL, "Unable to find class java.net.SocketImpl");
82    gSocketImplOffsets.mFileDescriptor = env->GetFieldID(clazz, "fd", "Ljava/io/FileDescriptor;");
83    LOG_FATAL_IF(gSocketImplOffsets.mFileDescriptor == NULL,
84                 "Unable to find fd field in java.net.SocketImpl");
85
86    clazz = env->FindClass("java/io/FileDescriptor");
87    LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
88    gFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
89    gFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "()V");
90    gFileDescriptorOffsets.mDescriptor = env->GetFieldID(clazz, "descriptor", "I");
91    LOG_FATAL_IF(gFileDescriptorOffsets.mDescriptor == NULL,
92                 "Unable to find descriptor field in java.io.FileDescriptor");
93
94    clazz = env->FindClass(kParcelFileDescriptorPathName);
95    LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor");
96
97    return AndroidRuntime::registerNativeMethods(
98        env, kParcelFileDescriptorPathName,
99        gParcelFileDescriptorMethods, NELEM(gParcelFileDescriptorMethods));
100}
101
102}
103