blob: 1ef2c581a8c478c7f7e7ad9d8f1e83229e8d2b53 [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>
25#include <utils/threads.h>
26
27#include "jni.h"
28#include "JNIHelp.h"
29#include "android_runtime/AndroidRuntime.h"
Mike Lockwooddad69272010-07-02 15:15:07 -040030#include "private/android_filesystem_config.h"
Mike Lockwood98ef64e2010-06-29 16:42:13 -040031
32#include "MtpServer.h"
33
Mike Lockwood81ea83d2010-06-30 17:49:41 -040034using namespace android;
Mike Lockwood98ef64e2010-06-29 16:42:13 -040035
36// ----------------------------------------------------------------------------
37
38static jfieldID field_context;
Mike Lockwood23ee42f2010-08-03 15:17:55 -040039static Mutex sMutex;
Mike Lockwood98ef64e2010-06-29 16:42:13 -040040
Mike Lockwoodd21eac92010-07-03 00:44:05 -040041// in android_media_MtpDatabase.cpp
42extern MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database);
Mike Lockwood98ef64e2010-06-29 16:42:13 -040043
44// ----------------------------------------------------------------------------
45
Mike Lockwoodff164a72010-07-15 15:01:17 -040046#ifdef HAVE_ANDROID_OS
47
Mike Lockwood98ef64e2010-06-29 16:42:13 -040048static bool ExceptionCheck(void* env)
49{
50 return ((JNIEnv *)env)->ExceptionCheck();
51}
52
53class MtpThread : public Thread {
54private:
Mike Lockwoodd21eac92010-07-03 00:44:05 -040055 MtpDatabase* mDatabase;
Mike Lockwoodbe125a52010-07-12 18:54:16 -040056 MtpServer* mServer;
Mike Lockwood23ee42f2010-08-03 15:17:55 -040057 String8 mStoragePath;
58 bool mDone;
59 jobject mJavaServer;
Mike Lockwood98ef64e2010-06-29 16:42:13 -040060
61public:
Mike Lockwood23ee42f2010-08-03 15:17:55 -040062 MtpThread(MtpDatabase* database, const char* storagePath, jobject javaServer)
63 : mDatabase(database),
64 mServer(NULL),
65 mStoragePath(storagePath),
66 mDone(false),
67 mJavaServer(javaServer)
Mike Lockwood98ef64e2010-06-29 16:42:13 -040068 {
69 }
70
71 virtual bool threadLoop() {
Mike Lockwood23ee42f2010-08-03 15:17:55 -040072 while (1) {
73 int fd = open("/dev/mtp_usb", O_RDWR);
74 printf("open returned %d\n", fd);
75 if (fd < 0) {
76 LOGE("could not open MTP driver\n");
77 break;
78 }
79
80 sMutex.lock();
81 mServer = new MtpServer(fd, mDatabase, AID_SDCARD_RW, 0664, 0775);
82 mServer->addStorage(mStoragePath);
83 sMutex.unlock();
84
85 LOGD("MtpThread mServer->run");
86 mServer->run();
87 close(fd);
88
89 sMutex.lock();
90 delete mServer;
91 mServer = NULL;
92 if (mDone)
93 goto done;
94 sMutex.unlock();
95 // wait a bit before retrying
96 sleep(1);
Mike Lockwood98ef64e2010-06-29 16:42:13 -040097 }
98
Mike Lockwood23ee42f2010-08-03 15:17:55 -040099 sMutex.lock();
100done:
101 JNIEnv* env = AndroidRuntime::getJNIEnv();
102 env->SetIntField(mJavaServer, field_context, 0);
103 env->DeleteGlobalRef(mJavaServer);
104 sMutex.unlock();
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400105
Mike Lockwood23ee42f2010-08-03 15:17:55 -0400106 LOGD("threadLoop returning");
107 return false;
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400108 }
109
Mike Lockwood23ee42f2010-08-03 15:17:55 -0400110 void setDone() {
111 LOGD("setDone");
112 mDone = true;
113 }
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400114
115 void sendObjectAdded(MtpObjectHandle handle) {
Mike Lockwood23ee42f2010-08-03 15:17:55 -0400116 sMutex.lock();
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400117 if (mServer)
118 mServer->sendObjectAdded(handle);
119 else
120 LOGE("sendObjectAdded called while disconnected\n");
Mike Lockwood23ee42f2010-08-03 15:17:55 -0400121 sMutex.unlock();
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400122 }
123
124 void sendObjectRemoved(MtpObjectHandle handle) {
Mike Lockwood23ee42f2010-08-03 15:17:55 -0400125 sMutex.lock();
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400126 if (mServer)
127 mServer->sendObjectRemoved(handle);
128 else
129 LOGE("sendObjectRemoved called while disconnected\n");
Mike Lockwood23ee42f2010-08-03 15:17:55 -0400130 sMutex.unlock();
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400131 }
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400132};
133
Mike Lockwoodff164a72010-07-15 15:01:17 -0400134#endif // HAVE_ANDROID_OS
135
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400136static void
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400137android_media_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase, jstring storagePath)
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400138{
Mike Lockwoodff164a72010-07-15 15:01:17 -0400139#ifdef HAVE_ANDROID_OS
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400140 LOGD("setup\n");
141
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400142 MtpDatabase* database = getMtpDatabase(env, javaDatabase);
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400143 const char *storagePathStr = env->GetStringUTFChars(storagePath, NULL);
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400144
Mike Lockwood23ee42f2010-08-03 15:17:55 -0400145 MtpThread* thread = new MtpThread(database, storagePathStr, env->NewGlobalRef(thiz));
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400146 env->SetIntField(thiz, field_context, (int)thread);
147
148 env->ReleaseStringUTFChars(storagePath, storagePathStr);
Mike Lockwoodff164a72010-07-15 15:01:17 -0400149#endif
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400150}
151
152static void
153android_media_MtpServer_finalize(JNIEnv *env, jobject thiz)
154{
155 LOGD("finalize\n");
156}
157
158
159static void
160android_media_MtpServer_start(JNIEnv *env, jobject thiz)
161{
Mike Lockwoodff164a72010-07-15 15:01:17 -0400162#ifdef HAVE_ANDROID_OS
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400163 LOGD("start\n");
164 MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
165 thread->run("MtpThread");
Mike Lockwoodff164a72010-07-15 15:01:17 -0400166#endif // HAVE_ANDROID_OS
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400167}
168
169static void
170android_media_MtpServer_stop(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("stop\n");
Mike Lockwood23ee42f2010-08-03 15:17:55 -0400174 sMutex.lock();
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400175 MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
Mike Lockwood23ee42f2010-08-03 15:17:55 -0400176 if (thread)
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400177 thread->setDone();
Mike Lockwood23ee42f2010-08-03 15:17:55 -0400178 sMutex.unlock();
Mike Lockwoodff164a72010-07-15 15:01:17 -0400179#endif
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400180}
181
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400182static void
183android_media_MtpServer_send_object_added(JNIEnv *env, jobject thiz, jint handle)
184{
Mike Lockwoodff164a72010-07-15 15:01:17 -0400185#ifdef HAVE_ANDROID_OS
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400186 LOGD("send_object_added %d\n", handle);
187 MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
188 if (thread)
189 thread->sendObjectAdded(handle);
190 else
191 LOGE("sendObjectAdded called while disconnected\n");
Mike Lockwoodff164a72010-07-15 15:01:17 -0400192#endif
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400193}
194
195static void
196android_media_MtpServer_send_object_removed(JNIEnv *env, jobject thiz, jint handle)
197{
Mike Lockwoodff164a72010-07-15 15:01:17 -0400198#ifdef HAVE_ANDROID_OS
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400199 LOGD("send_object_removed %d\n", handle);
200 MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
201 if (thread)
202 thread->sendObjectRemoved(handle);
203 else
204 LOGE("sendObjectRemoved called while disconnected\n");
Mike Lockwoodff164a72010-07-15 15:01:17 -0400205#endif
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400206}
207
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400208// ----------------------------------------------------------------------------
209
210static JNINativeMethod gMethods[] = {
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400211 {"native_setup", "(Landroid/media/MtpDatabase;Ljava/lang/String;)V",
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400212 (void *)android_media_MtpServer_setup},
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400213 {"native_finalize", "()V", (void *)android_media_MtpServer_finalize},
214 {"native_start", "()V", (void *)android_media_MtpServer_start},
215 {"native_stop", "()V", (void *)android_media_MtpServer_stop},
216 {"native_send_object_added", "(I)V", (void *)android_media_MtpServer_send_object_added},
217 {"native_send_object_removed", "(I)V", (void *)android_media_MtpServer_send_object_removed},
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400218};
219
220static const char* const kClassPathName = "android/media/MtpServer";
221
222int register_android_media_MtpServer(JNIEnv *env)
223{
224 jclass clazz;
225
226 LOGD("register_android_media_MtpServer\n");
227
228 clazz = env->FindClass("android/media/MtpServer");
229 if (clazz == NULL) {
230 LOGE("Can't find android/media/MtpServer");
231 return -1;
232 }
233 field_context = env->GetFieldID(clazz, "mNativeContext", "I");
234 if (field_context == NULL) {
235 LOGE("Can't find MtpServer.mNativeContext");
236 return -1;
237 }
238
239 return AndroidRuntime::registerNativeMethods(env,
240 "android/media/MtpServer", gMethods, NELEM(gMethods));
241}