• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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 "MtpServerJNI"
18 #include "utils/Log.h"
19 
20 #include <stdio.h>
21 #include <assert.h>
22 #include <limits.h>
23 #include <unistd.h>
24 #include <fcntl.h>
25 #include <utils/threads.h>
26 
27 #include "jni.h"
28 #include <nativehelper/JNIHelp.h>
29 #include "android_runtime/AndroidRuntime.h"
30 #include "private/android_filesystem_config.h"
31 
32 #include "MtpServer.h"
33 #include "MtpStorage.h"
34 
35 using namespace android;
36 
37 // MtpServer fields
38 static jfieldID field_MtpServer_nativeContext;
39 
40 // MtpStorage fields
41 static jfieldID field_MtpStorage_storageId;
42 static jfieldID field_MtpStorage_path;
43 static jfieldID field_MtpStorage_description;
44 static jfieldID field_MtpStorage_reserveSpace;
45 static jfieldID field_MtpStorage_removable;
46 static jfieldID field_MtpStorage_maxFileSize;
47 
48 static Mutex sMutex;
49 
50 // ----------------------------------------------------------------------------
51 
52 // in android_mtp_MtpDatabase.cpp
53 extern MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database);
54 
getMtpServer(JNIEnv * env,jobject thiz)55 static inline MtpServer* getMtpServer(JNIEnv *env, jobject thiz) {
56     return (MtpServer*)env->GetLongField(thiz, field_MtpServer_nativeContext);
57 }
58 
android_mtp_configure(JNIEnv *,jobject,jboolean usePtp)59 static void android_mtp_configure(JNIEnv *, jobject, jboolean usePtp) {
60     MtpServer::configure(usePtp);
61 }
62 
63 static void
android_mtp_MtpServer_setup(JNIEnv * env,jobject thiz,jobject javaDatabase,jboolean usePtp,jstring deviceInfoManufacturer,jstring deviceInfoModel,jstring deviceInfoDeviceVersion,jstring deviceInfoSerialNumber)64 android_mtp_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase, jboolean usePtp,
65         jstring deviceInfoManufacturer,
66         jstring deviceInfoModel,
67         jstring deviceInfoDeviceVersion,
68         jstring deviceInfoSerialNumber)
69 {
70     const char *deviceInfoManufacturerStr = env->GetStringUTFChars(deviceInfoManufacturer, NULL);
71     const char *deviceInfoModelStr = env->GetStringUTFChars(deviceInfoModel, NULL);
72     const char *deviceInfoDeviceVersionStr = env->GetStringUTFChars(deviceInfoDeviceVersion, NULL);
73     const char *deviceInfoSerialNumberStr = env->GetStringUTFChars(deviceInfoSerialNumber, NULL);
74     MtpServer* server = new MtpServer(getMtpDatabase(env, javaDatabase),
75             usePtp, AID_MEDIA_RW, 0664, 0775,
76             MtpString((deviceInfoManufacturerStr != NULL) ? deviceInfoManufacturerStr : ""),
77             MtpString((deviceInfoModelStr != NULL) ? deviceInfoModelStr : ""),
78             MtpString((deviceInfoDeviceVersionStr != NULL) ? deviceInfoDeviceVersionStr : ""),
79             MtpString((deviceInfoSerialNumberStr != NULL) ? deviceInfoSerialNumberStr : ""));
80     if (deviceInfoManufacturerStr != NULL) {
81         env->ReleaseStringUTFChars(deviceInfoManufacturer, deviceInfoManufacturerStr);
82     }
83     if (deviceInfoModelStr != NULL) {
84         env->ReleaseStringUTFChars(deviceInfoModel, deviceInfoModelStr);
85     }
86     if (deviceInfoDeviceVersionStr != NULL) {
87         env->ReleaseStringUTFChars(deviceInfoDeviceVersion, deviceInfoDeviceVersionStr);
88     }
89     if (deviceInfoSerialNumberStr != NULL) {
90         env->ReleaseStringUTFChars(deviceInfoSerialNumber, deviceInfoSerialNumberStr);
91     }
92     env->SetLongField(thiz, field_MtpServer_nativeContext, (jlong)server);
93 }
94 
95 static void
android_mtp_MtpServer_run(JNIEnv * env,jobject thiz)96 android_mtp_MtpServer_run(JNIEnv *env, jobject thiz)
97 {
98     MtpServer* server = getMtpServer(env, thiz);
99     if (server)
100         server->run();
101     else
102         ALOGE("server is null in run");
103 }
104 
105 static void
android_mtp_MtpServer_cleanup(JNIEnv * env,jobject thiz)106 android_mtp_MtpServer_cleanup(JNIEnv *env, jobject thiz)
107 {
108     Mutex::Autolock autoLock(sMutex);
109 
110     MtpServer* server = getMtpServer(env, thiz);
111     if (server) {
112         delete server;
113         env->SetLongField(thiz, field_MtpServer_nativeContext, 0);
114     } else {
115         ALOGE("server is null in cleanup");
116     }
117 }
118 
119 static void
android_mtp_MtpServer_send_object_added(JNIEnv * env,jobject thiz,jint handle)120 android_mtp_MtpServer_send_object_added(JNIEnv *env, jobject thiz, jint handle)
121 {
122     Mutex::Autolock autoLock(sMutex);
123 
124     MtpServer* server = getMtpServer(env, thiz);
125     if (server)
126         server->sendObjectAdded(handle);
127     else
128         ALOGE("server is null in send_object_added");
129 }
130 
131 static void
android_mtp_MtpServer_send_object_removed(JNIEnv * env,jobject thiz,jint handle)132 android_mtp_MtpServer_send_object_removed(JNIEnv *env, jobject thiz, jint handle)
133 {
134     Mutex::Autolock autoLock(sMutex);
135 
136     MtpServer* server = getMtpServer(env, thiz);
137     if (server)
138         server->sendObjectRemoved(handle);
139     else
140         ALOGE("server is null in send_object_removed");
141 }
142 
143 static void
android_mtp_MtpServer_send_device_property_changed(JNIEnv * env,jobject thiz,jint property)144 android_mtp_MtpServer_send_device_property_changed(JNIEnv *env, jobject thiz, jint property)
145 {
146     Mutex::Autolock autoLock(sMutex);
147 
148     MtpServer* server = getMtpServer(env, thiz);
149     if (server)
150         server->sendDevicePropertyChanged(property);
151     else
152         ALOGE("server is null in send_object_removed");
153 }
154 
155 static void
android_mtp_MtpServer_add_storage(JNIEnv * env,jobject thiz,jobject jstorage)156 android_mtp_MtpServer_add_storage(JNIEnv *env, jobject thiz, jobject jstorage)
157 {
158     Mutex::Autolock autoLock(sMutex);
159 
160     MtpServer* server = getMtpServer(env, thiz);
161     if (server) {
162         jint storageID = env->GetIntField(jstorage, field_MtpStorage_storageId);
163         jstring path = (jstring)env->GetObjectField(jstorage, field_MtpStorage_path);
164         jstring description = (jstring)env->GetObjectField(jstorage, field_MtpStorage_description);
165         jlong reserveSpace = env->GetLongField(jstorage, field_MtpStorage_reserveSpace);
166         jboolean removable = env->GetBooleanField(jstorage, field_MtpStorage_removable);
167         jlong maxFileSize = env->GetLongField(jstorage, field_MtpStorage_maxFileSize);
168 
169         const char *pathStr = env->GetStringUTFChars(path, NULL);
170         if (pathStr != NULL) {
171             const char *descriptionStr = env->GetStringUTFChars(description, NULL);
172             if (descriptionStr != NULL) {
173                 MtpStorage* storage = new MtpStorage(storageID, pathStr, descriptionStr,
174                         reserveSpace, removable, maxFileSize);
175                 server->addStorage(storage);
176                 env->ReleaseStringUTFChars(path, pathStr);
177                 env->ReleaseStringUTFChars(description, descriptionStr);
178             } else {
179                 env->ReleaseStringUTFChars(path, pathStr);
180             }
181         }
182     } else {
183         ALOGE("server is null in add_storage");
184     }
185 }
186 
187 static void
android_mtp_MtpServer_remove_storage(JNIEnv * env,jobject thiz,jint storageId)188 android_mtp_MtpServer_remove_storage(JNIEnv *env, jobject thiz, jint storageId)
189 {
190     Mutex::Autolock autoLock(sMutex);
191 
192     MtpServer* server = getMtpServer(env, thiz);
193     if (server) {
194         MtpStorage* storage = server->getStorage(storageId);
195         if (storage) {
196             server->removeStorage(storage);
197             delete storage;
198         }
199     } else
200         ALOGE("server is null in remove_storage");
201 }
202 
203 // ----------------------------------------------------------------------------
204 
205 static const JNINativeMethod gMethods[] = {
206     {"native_configure",              "(Z)V",  (void *)android_mtp_configure},
207     {"native_setup",                "(Landroid/mtp/MtpDatabase;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
208                                             (void *)android_mtp_MtpServer_setup},
209     {"native_run",                  "()V",  (void *)android_mtp_MtpServer_run},
210     {"native_cleanup",              "()V",  (void *)android_mtp_MtpServer_cleanup},
211     {"native_send_object_added",    "(I)V", (void *)android_mtp_MtpServer_send_object_added},
212     {"native_send_object_removed",  "(I)V", (void *)android_mtp_MtpServer_send_object_removed},
213     {"native_send_device_property_changed",  "(I)V",
214                                     (void *)android_mtp_MtpServer_send_device_property_changed},
215     {"native_add_storage",          "(Landroid/mtp/MtpStorage;)V",
216                                             (void *)android_mtp_MtpServer_add_storage},
217     {"native_remove_storage",       "(I)V", (void *)android_mtp_MtpServer_remove_storage},
218 };
219 
register_android_mtp_MtpServer(JNIEnv * env)220 int register_android_mtp_MtpServer(JNIEnv *env)
221 {
222     jclass clazz;
223 
224     clazz = env->FindClass("android/mtp/MtpStorage");
225     if (clazz == NULL) {
226         ALOGE("Can't find android/mtp/MtpStorage");
227         return -1;
228     }
229     field_MtpStorage_storageId = env->GetFieldID(clazz, "mStorageId", "I");
230     if (field_MtpStorage_storageId == NULL) {
231         ALOGE("Can't find MtpStorage.mStorageId");
232         return -1;
233     }
234     field_MtpStorage_path = env->GetFieldID(clazz, "mPath", "Ljava/lang/String;");
235     if (field_MtpStorage_path == NULL) {
236         ALOGE("Can't find MtpStorage.mPath");
237         return -1;
238     }
239     field_MtpStorage_description = env->GetFieldID(clazz, "mDescription", "Ljava/lang/String;");
240     if (field_MtpStorage_description == NULL) {
241         ALOGE("Can't find MtpStorage.mDescription");
242         return -1;
243     }
244     field_MtpStorage_reserveSpace = env->GetFieldID(clazz, "mReserveSpace", "J");
245     if (field_MtpStorage_reserveSpace == NULL) {
246         ALOGE("Can't find MtpStorage.mReserveSpace");
247         return -1;
248     }
249     field_MtpStorage_removable = env->GetFieldID(clazz, "mRemovable", "Z");
250     if (field_MtpStorage_removable == NULL) {
251         ALOGE("Can't find MtpStorage.mRemovable");
252         return -1;
253     }
254     field_MtpStorage_maxFileSize = env->GetFieldID(clazz, "mMaxFileSize", "J");
255     if (field_MtpStorage_maxFileSize == NULL) {
256         ALOGE("Can't find MtpStorage.mMaxFileSize");
257         return -1;
258     }
259 
260     clazz = env->FindClass("android/mtp/MtpServer");
261     if (clazz == NULL) {
262         ALOGE("Can't find android/mtp/MtpServer");
263         return -1;
264     }
265     field_MtpServer_nativeContext = env->GetFieldID(clazz, "mNativeContext", "J");
266     if (field_MtpServer_nativeContext == NULL) {
267         ALOGE("Can't find MtpServer.mNativeContext");
268         return -1;
269     }
270 
271     return AndroidRuntime::registerNativeMethods(env,
272                 "android/mtp/MtpServer", gMethods, NELEM(gMethods));
273 }
274