blob: 28a80cb09683d4830085bf4ee36095ac94506477 [file] [log] [blame]
Mike Lockwood98ef64e2010-06-29 16:42:13 -04001/*
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>
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -040025#include <sys/ioctl.h>
Mike Lockwood98ef64e2010-06-29 16:42:13 -040026#include <utils/threads.h>
27
Mike Lockwood602bebd2010-09-02 09:58:48 -040028#ifdef HAVE_ANDROID_OS
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -040029#include <linux/usb/f_mtp.h>
Mike Lockwood602bebd2010-09-02 09:58:48 -040030#endif
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -040031
Mike Lockwood98ef64e2010-06-29 16:42:13 -040032#include "jni.h"
33#include "JNIHelp.h"
34#include "android_runtime/AndroidRuntime.h"
Mike Lockwooddad69272010-07-02 15:15:07 -040035#include "private/android_filesystem_config.h"
Mike Lockwood98ef64e2010-06-29 16:42:13 -040036
37#include "MtpServer.h"
38
Mike Lockwood81ea83d2010-06-30 17:49:41 -040039using namespace android;
Mike Lockwood98ef64e2010-06-29 16:42:13 -040040
41// ----------------------------------------------------------------------------
42
43static jfieldID field_context;
Mike Lockwood23ee42f2010-08-03 15:17:55 -040044static Mutex sMutex;
Mike Lockwood98ef64e2010-06-29 16:42:13 -040045
Mike Lockwoodd21eac92010-07-03 00:44:05 -040046// in android_media_MtpDatabase.cpp
47extern MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database);
Mike Lockwood98ef64e2010-06-29 16:42:13 -040048
49// ----------------------------------------------------------------------------
50
Mike Lockwoodff164a72010-07-15 15:01:17 -040051#ifdef HAVE_ANDROID_OS
52
Mike Lockwood98ef64e2010-06-29 16:42:13 -040053static bool ExceptionCheck(void* env)
54{
55 return ((JNIEnv *)env)->ExceptionCheck();
56}
57
58class MtpThread : public Thread {
59private:
Mike Lockwoodd21eac92010-07-03 00:44:05 -040060 MtpDatabase* mDatabase;
Mike Lockwoodbe125a52010-07-12 18:54:16 -040061 MtpServer* mServer;
Mike Lockwood23ee42f2010-08-03 15:17:55 -040062 String8 mStoragePath;
Mike Lockwood7f36b192010-12-12 12:17:43 -080063 uint64_t mReserveSpace;
Mike Lockwood23ee42f2010-08-03 15:17:55 -040064 jobject mJavaServer;
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -040065 int mFd;
Mike Lockwood98ef64e2010-06-29 16:42:13 -040066
67public:
Mike Lockwood7f36b192010-12-12 12:17:43 -080068 MtpThread(MtpDatabase* database, const char* storagePath, uint64_t reserveSpace,
69 jobject javaServer)
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -040070 : mDatabase(database),
Mike Lockwood23ee42f2010-08-03 15:17:55 -040071 mServer(NULL),
72 mStoragePath(storagePath),
Mike Lockwood7f36b192010-12-12 12:17:43 -080073 mReserveSpace(reserveSpace),
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -040074 mJavaServer(javaServer),
75 mFd(-1)
Mike Lockwood98ef64e2010-06-29 16:42:13 -040076 {
77 }
78
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -040079 void setPtpMode(bool usePtp) {
80 sMutex.lock();
81 if (mFd >= 0) {
82 ioctl(mFd, MTP_SET_INTERFACE_MODE,
83 (usePtp ? MTP_INTERFACE_MODE_PTP : MTP_INTERFACE_MODE_MTP));
84 } else {
85 int fd = open("/dev/mtp_usb", O_RDWR);
86 if (fd >= 0) {
87 ioctl(fd, MTP_SET_INTERFACE_MODE,
88 (usePtp ? MTP_INTERFACE_MODE_PTP : MTP_INTERFACE_MODE_MTP));
89 close(fd);
90 }
91 }
92 sMutex.unlock();
93 }
94
Mike Lockwood98ef64e2010-06-29 16:42:13 -040095 virtual bool threadLoop() {
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -040096 sMutex.lock();
97 mFd = open("/dev/mtp_usb", O_RDWR);
98 printf("open returned %d\n", mFd);
99 if (mFd < 0) {
Mike Lockwood2b2bff52010-08-18 12:32:26 -0400100 LOGE("could not open MTP driver\n");
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -0400101 sMutex.unlock();
Mike Lockwood2b2bff52010-08-18 12:32:26 -0400102 return false;
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400103 }
104
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -0400105 mServer = new MtpServer(mFd, mDatabase, AID_SDCARD_RW, 0664, 0775);
Mike Lockwood7f36b192010-12-12 12:17:43 -0800106 mServer->addStorage(mStoragePath, mReserveSpace);
Mike Lockwood2b2bff52010-08-18 12:32:26 -0400107 sMutex.unlock();
108
109 LOGD("MtpThread mServer->run");
110 mServer->run();
Mike Lockwood2b2bff52010-08-18 12:32:26 -0400111
112 sMutex.lock();
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -0400113 close(mFd);
114 mFd = -1;
Mike Lockwood2b2bff52010-08-18 12:32:26 -0400115 delete mServer;
116 mServer = NULL;
117
Mike Lockwood23ee42f2010-08-03 15:17:55 -0400118 JNIEnv* env = AndroidRuntime::getJNIEnv();
119 env->SetIntField(mJavaServer, field_context, 0);
120 env->DeleteGlobalRef(mJavaServer);
121 sMutex.unlock();
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400122
Mike Lockwood23ee42f2010-08-03 15:17:55 -0400123 LOGD("threadLoop returning");
124 return false;
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400125 }
126
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400127 void sendObjectAdded(MtpObjectHandle handle) {
Mike Lockwood23ee42f2010-08-03 15:17:55 -0400128 sMutex.lock();
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400129 if (mServer)
130 mServer->sendObjectAdded(handle);
Mike Lockwood23ee42f2010-08-03 15:17:55 -0400131 sMutex.unlock();
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400132 }
133
134 void sendObjectRemoved(MtpObjectHandle handle) {
Mike Lockwood23ee42f2010-08-03 15:17:55 -0400135 sMutex.lock();
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400136 if (mServer)
137 mServer->sendObjectRemoved(handle);
Mike Lockwood23ee42f2010-08-03 15:17:55 -0400138 sMutex.unlock();
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400139 }
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400140};
141
Mike Lockwoodff164a72010-07-15 15:01:17 -0400142#endif // HAVE_ANDROID_OS
143
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400144static void
Mike Lockwood7f36b192010-12-12 12:17:43 -0800145android_media_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase,
146 jstring storagePath, jlong reserveSpace)
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400147{
Mike Lockwoodff164a72010-07-15 15:01:17 -0400148#ifdef HAVE_ANDROID_OS
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400149 LOGD("setup\n");
150
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400151 MtpDatabase* database = getMtpDatabase(env, javaDatabase);
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400152 const char *storagePathStr = env->GetStringUTFChars(storagePath, NULL);
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400153
Mike Lockwood7f36b192010-12-12 12:17:43 -0800154 MtpThread* thread = new MtpThread(database, storagePathStr,
155 reserveSpace, env->NewGlobalRef(thiz));
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400156 env->SetIntField(thiz, field_context, (int)thread);
157
158 env->ReleaseStringUTFChars(storagePath, storagePathStr);
Mike Lockwoodff164a72010-07-15 15:01:17 -0400159#endif
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400160}
161
162static void
163android_media_MtpServer_finalize(JNIEnv *env, jobject thiz)
164{
165 LOGD("finalize\n");
166}
167
168
169static void
170android_media_MtpServer_start(JNIEnv *env, jobject thiz)
171{
Mike Lockwoodff164a72010-07-15 15:01:17 -0400172#ifdef HAVE_ANDROID_OS
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400173 LOGD("start\n");
174 MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
175 thread->run("MtpThread");
Mike Lockwoodff164a72010-07-15 15:01:17 -0400176#endif // HAVE_ANDROID_OS
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400177}
178
179static void
180android_media_MtpServer_stop(JNIEnv *env, jobject thiz)
181{
Mike Lockwoodff164a72010-07-15 15:01:17 -0400182#ifdef HAVE_ANDROID_OS
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400183 LOGD("stop\n");
Mike Lockwoodff164a72010-07-15 15:01:17 -0400184#endif
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400185}
186
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400187static void
188android_media_MtpServer_send_object_added(JNIEnv *env, jobject thiz, jint handle)
189{
Mike Lockwoodff164a72010-07-15 15:01:17 -0400190#ifdef HAVE_ANDROID_OS
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400191 MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
192 if (thread)
193 thread->sendObjectAdded(handle);
Mike Lockwoodff164a72010-07-15 15:01:17 -0400194#endif
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400195}
196
197static void
198android_media_MtpServer_send_object_removed(JNIEnv *env, jobject thiz, jint handle)
199{
Mike Lockwoodff164a72010-07-15 15:01:17 -0400200#ifdef HAVE_ANDROID_OS
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400201 MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
202 if (thread)
203 thread->sendObjectRemoved(handle);
Mike Lockwoodff164a72010-07-15 15:01:17 -0400204#endif
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400205}
206
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -0400207static void
208android_media_MtpServer_set_ptp_mode(JNIEnv *env, jobject thiz, jboolean usePtp)
209{
210#ifdef HAVE_ANDROID_OS
211 LOGD("set_ptp_mode\n");
212 MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
213 if (thread)
214 thread->setPtpMode(usePtp);
215 #endif
216}
217
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400218// ----------------------------------------------------------------------------
219
220static JNINativeMethod gMethods[] = {
Mike Lockwood7f36b192010-12-12 12:17:43 -0800221 {"native_setup", "(Landroid/media/MtpDatabase;Ljava/lang/String;J)V",
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400222 (void *)android_media_MtpServer_setup},
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400223 {"native_finalize", "()V", (void *)android_media_MtpServer_finalize},
224 {"native_start", "()V", (void *)android_media_MtpServer_start},
225 {"native_stop", "()V", (void *)android_media_MtpServer_stop},
226 {"native_send_object_added", "(I)V", (void *)android_media_MtpServer_send_object_added},
227 {"native_send_object_removed", "(I)V", (void *)android_media_MtpServer_send_object_removed},
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -0400228 {"native_set_ptp_mode", "(Z)V", (void *)android_media_MtpServer_set_ptp_mode},
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400229};
230
231static const char* const kClassPathName = "android/media/MtpServer";
232
233int register_android_media_MtpServer(JNIEnv *env)
234{
235 jclass clazz;
236
237 LOGD("register_android_media_MtpServer\n");
238
239 clazz = env->FindClass("android/media/MtpServer");
240 if (clazz == NULL) {
241 LOGE("Can't find android/media/MtpServer");
242 return -1;
243 }
244 field_context = env->GetFieldID(clazz, "mNativeContext", "I");
245 if (field_context == NULL) {
246 LOGE("Can't find MtpServer.mNativeContext");
247 return -1;
248 }
249
250 return AndroidRuntime::registerNativeMethods(env,
251 "android/media/MtpServer", gMethods, NELEM(gMethods));
252}