blob: 3da3165347dfaae33a386a691b4668dd9ef8ad67 [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 Lockwoodeabe8bf2010-08-31 14:35:23 -040028#include <linux/usb/f_mtp.h>
29
Mike Lockwood98ef64e2010-06-29 16:42:13 -040030#include "jni.h"
31#include "JNIHelp.h"
32#include "android_runtime/AndroidRuntime.h"
Mike Lockwooddad69272010-07-02 15:15:07 -040033#include "private/android_filesystem_config.h"
Mike Lockwood98ef64e2010-06-29 16:42:13 -040034
35#include "MtpServer.h"
36
Mike Lockwood81ea83d2010-06-30 17:49:41 -040037using namespace android;
Mike Lockwood98ef64e2010-06-29 16:42:13 -040038
39// ----------------------------------------------------------------------------
40
41static jfieldID field_context;
Mike Lockwood23ee42f2010-08-03 15:17:55 -040042static Mutex sMutex;
Mike Lockwood98ef64e2010-06-29 16:42:13 -040043
Mike Lockwoodd21eac92010-07-03 00:44:05 -040044// in android_media_MtpDatabase.cpp
45extern MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database);
Mike Lockwood98ef64e2010-06-29 16:42:13 -040046
47// ----------------------------------------------------------------------------
48
Mike Lockwoodff164a72010-07-15 15:01:17 -040049#ifdef HAVE_ANDROID_OS
50
Mike Lockwood98ef64e2010-06-29 16:42:13 -040051static bool ExceptionCheck(void* env)
52{
53 return ((JNIEnv *)env)->ExceptionCheck();
54}
55
56class MtpThread : public Thread {
57private:
Mike Lockwoodd21eac92010-07-03 00:44:05 -040058 MtpDatabase* mDatabase;
Mike Lockwoodbe125a52010-07-12 18:54:16 -040059 MtpServer* mServer;
Mike Lockwood23ee42f2010-08-03 15:17:55 -040060 String8 mStoragePath;
Mike Lockwood23ee42f2010-08-03 15:17:55 -040061 jobject mJavaServer;
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -040062 int mFd;
Mike Lockwood98ef64e2010-06-29 16:42:13 -040063
64public:
Mike Lockwood23ee42f2010-08-03 15:17:55 -040065 MtpThread(MtpDatabase* database, const char* storagePath, jobject javaServer)
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -040066 : mDatabase(database),
Mike Lockwood23ee42f2010-08-03 15:17:55 -040067 mServer(NULL),
68 mStoragePath(storagePath),
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -040069 mJavaServer(javaServer),
70 mFd(-1)
Mike Lockwood98ef64e2010-06-29 16:42:13 -040071 {
72 }
73
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -040074 void setPtpMode(bool usePtp) {
75 sMutex.lock();
76 if (mFd >= 0) {
77 ioctl(mFd, MTP_SET_INTERFACE_MODE,
78 (usePtp ? MTP_INTERFACE_MODE_PTP : MTP_INTERFACE_MODE_MTP));
79 } else {
80 int fd = open("/dev/mtp_usb", O_RDWR);
81 if (fd >= 0) {
82 ioctl(fd, MTP_SET_INTERFACE_MODE,
83 (usePtp ? MTP_INTERFACE_MODE_PTP : MTP_INTERFACE_MODE_MTP));
84 close(fd);
85 }
86 }
87 sMutex.unlock();
88 }
89
Mike Lockwood98ef64e2010-06-29 16:42:13 -040090 virtual bool threadLoop() {
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -040091 sMutex.lock();
92 mFd = open("/dev/mtp_usb", O_RDWR);
93 printf("open returned %d\n", mFd);
94 if (mFd < 0) {
Mike Lockwood2b2bff52010-08-18 12:32:26 -040095 LOGE("could not open MTP driver\n");
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -040096 sMutex.unlock();
Mike Lockwood2b2bff52010-08-18 12:32:26 -040097 return false;
Mike Lockwood98ef64e2010-06-29 16:42:13 -040098 }
99
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -0400100 mServer = new MtpServer(mFd, mDatabase, AID_SDCARD_RW, 0664, 0775);
Mike Lockwood2b2bff52010-08-18 12:32:26 -0400101 mServer->addStorage(mStoragePath);
102 sMutex.unlock();
103
104 LOGD("MtpThread mServer->run");
105 mServer->run();
Mike Lockwood2b2bff52010-08-18 12:32:26 -0400106
107 sMutex.lock();
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -0400108 close(mFd);
109 mFd = -1;
Mike Lockwood2b2bff52010-08-18 12:32:26 -0400110 delete mServer;
111 mServer = NULL;
112
Mike Lockwood23ee42f2010-08-03 15:17:55 -0400113 JNIEnv* env = AndroidRuntime::getJNIEnv();
114 env->SetIntField(mJavaServer, field_context, 0);
115 env->DeleteGlobalRef(mJavaServer);
116 sMutex.unlock();
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400117
Mike Lockwood23ee42f2010-08-03 15:17:55 -0400118 LOGD("threadLoop returning");
119 return false;
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400120 }
121
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400122 void sendObjectAdded(MtpObjectHandle handle) {
Mike Lockwood23ee42f2010-08-03 15:17:55 -0400123 sMutex.lock();
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400124 if (mServer)
125 mServer->sendObjectAdded(handle);
126 else
127 LOGE("sendObjectAdded called while disconnected\n");
Mike Lockwood23ee42f2010-08-03 15:17:55 -0400128 sMutex.unlock();
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400129 }
130
131 void sendObjectRemoved(MtpObjectHandle handle) {
Mike Lockwood23ee42f2010-08-03 15:17:55 -0400132 sMutex.lock();
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400133 if (mServer)
134 mServer->sendObjectRemoved(handle);
135 else
136 LOGE("sendObjectRemoved called while disconnected\n");
Mike Lockwood23ee42f2010-08-03 15:17:55 -0400137 sMutex.unlock();
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400138 }
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400139};
140
Mike Lockwoodff164a72010-07-15 15:01:17 -0400141#endif // HAVE_ANDROID_OS
142
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400143static void
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400144android_media_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase, jstring storagePath)
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400145{
Mike Lockwoodff164a72010-07-15 15:01:17 -0400146#ifdef HAVE_ANDROID_OS
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400147 LOGD("setup\n");
148
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400149 MtpDatabase* database = getMtpDatabase(env, javaDatabase);
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400150 const char *storagePathStr = env->GetStringUTFChars(storagePath, NULL);
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400151
Mike Lockwood23ee42f2010-08-03 15:17:55 -0400152 MtpThread* thread = new MtpThread(database, storagePathStr, env->NewGlobalRef(thiz));
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400153 env->SetIntField(thiz, field_context, (int)thread);
154
155 env->ReleaseStringUTFChars(storagePath, storagePathStr);
Mike Lockwoodff164a72010-07-15 15:01:17 -0400156#endif
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400157}
158
159static void
160android_media_MtpServer_finalize(JNIEnv *env, jobject thiz)
161{
162 LOGD("finalize\n");
163}
164
165
166static void
167android_media_MtpServer_start(JNIEnv *env, jobject thiz)
168{
Mike Lockwoodff164a72010-07-15 15:01:17 -0400169#ifdef HAVE_ANDROID_OS
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400170 LOGD("start\n");
171 MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
172 thread->run("MtpThread");
Mike Lockwoodff164a72010-07-15 15:01:17 -0400173#endif // HAVE_ANDROID_OS
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400174}
175
176static void
177android_media_MtpServer_stop(JNIEnv *env, jobject thiz)
178{
Mike Lockwoodff164a72010-07-15 15:01:17 -0400179#ifdef HAVE_ANDROID_OS
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400180 LOGD("stop\n");
Mike Lockwoodff164a72010-07-15 15:01:17 -0400181#endif
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400182}
183
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400184static void
185android_media_MtpServer_send_object_added(JNIEnv *env, jobject thiz, jint handle)
186{
Mike Lockwoodff164a72010-07-15 15:01:17 -0400187#ifdef HAVE_ANDROID_OS
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400188 LOGD("send_object_added %d\n", handle);
189 MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
190 if (thread)
191 thread->sendObjectAdded(handle);
192 else
193 LOGE("sendObjectAdded called while disconnected\n");
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 LOGD("send_object_removed %d\n", handle);
202 MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
203 if (thread)
204 thread->sendObjectRemoved(handle);
205 else
206 LOGE("sendObjectRemoved called while disconnected\n");
Mike Lockwoodff164a72010-07-15 15:01:17 -0400207#endif
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400208}
209
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -0400210static void
211android_media_MtpServer_set_ptp_mode(JNIEnv *env, jobject thiz, jboolean usePtp)
212{
213#ifdef HAVE_ANDROID_OS
214 LOGD("set_ptp_mode\n");
215 MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
216 if (thread)
217 thread->setPtpMode(usePtp);
218 #endif
219}
220
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400221// ----------------------------------------------------------------------------
222
223static JNINativeMethod gMethods[] = {
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400224 {"native_setup", "(Landroid/media/MtpDatabase;Ljava/lang/String;)V",
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400225 (void *)android_media_MtpServer_setup},
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400226 {"native_finalize", "()V", (void *)android_media_MtpServer_finalize},
227 {"native_start", "()V", (void *)android_media_MtpServer_start},
228 {"native_stop", "()V", (void *)android_media_MtpServer_stop},
229 {"native_send_object_added", "(I)V", (void *)android_media_MtpServer_send_object_added},
230 {"native_send_object_removed", "(I)V", (void *)android_media_MtpServer_send_object_removed},
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -0400231 {"native_set_ptp_mode", "(Z)V", (void *)android_media_MtpServer_set_ptp_mode},
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400232};
233
234static const char* const kClassPathName = "android/media/MtpServer";
235
236int register_android_media_MtpServer(JNIEnv *env)
237{
238 jclass clazz;
239
240 LOGD("register_android_media_MtpServer\n");
241
242 clazz = env->FindClass("android/media/MtpServer");
243 if (clazz == NULL) {
244 LOGE("Can't find android/media/MtpServer");
245 return -1;
246 }
247 field_context = env->GetFieldID(clazz, "mNativeContext", "I");
248 if (field_context == NULL) {
249 LOGE("Can't find MtpServer.mNativeContext");
250 return -1;
251 }
252
253 return AndroidRuntime::registerNativeMethods(env,
254 "android/media/MtpServer", gMethods, NELEM(gMethods));
255}