blob: eddad5749c02f53f8e248f33e14a40bdb7275790 [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;
39
Mike Lockwoodd21eac92010-07-03 00:44:05 -040040// in android_media_MtpDatabase.cpp
41extern MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database);
Mike Lockwood98ef64e2010-06-29 16:42:13 -040042
43// ----------------------------------------------------------------------------
44
Mike Lockwoodff164a72010-07-15 15:01:17 -040045#ifdef HAVE_ANDROID_OS
46
Mike Lockwood98ef64e2010-06-29 16:42:13 -040047static bool ExceptionCheck(void* env)
48{
49 return ((JNIEnv *)env)->ExceptionCheck();
50}
51
52class MtpThread : public Thread {
53private:
Mike Lockwoodd21eac92010-07-03 00:44:05 -040054 MtpDatabase* mDatabase;
Mike Lockwoodbe125a52010-07-12 18:54:16 -040055 MtpServer* mServer;
Mike Lockwood98ef64e2010-06-29 16:42:13 -040056 String8 mStoragePath;
Mike Lockwood98ef64e2010-06-29 16:42:13 -040057 bool mDone;
Mike Lockwoodbe125a52010-07-12 18:54:16 -040058 Mutex mMutex;
Mike Lockwood98ef64e2010-06-29 16:42:13 -040059
60public:
Mike Lockwoodd21eac92010-07-03 00:44:05 -040061 MtpThread(MtpDatabase* database, const char* storagePath)
Mike Lockwoodbe125a52010-07-12 18:54:16 -040062 : mDatabase(database), mServer(NULL), mStoragePath(storagePath), mDone(false)
Mike Lockwood98ef64e2010-06-29 16:42:13 -040063 {
64 }
65
66 virtual bool threadLoop() {
67 int fd = open("/dev/mtp_usb", O_RDWR);
68 printf("open returned %d\n", fd);
69 if (fd < 0) {
70 LOGE("could not open MTP driver\n");
71 return false;
72 }
73
Mike Lockwoodbe125a52010-07-12 18:54:16 -040074 mMutex.lock();
75 mServer = new MtpServer(fd, mDatabase, AID_SDCARD_RW, 0664, 0775);
76 mServer->addStorage(mStoragePath);
77 mMutex.unlock();
Mike Lockwood98ef64e2010-06-29 16:42:13 -040078
Mike Lockwoodbe125a52010-07-12 18:54:16 -040079 LOGD("MtpThread mServer->run");
80 mServer->run();
Mike Lockwood98ef64e2010-06-29 16:42:13 -040081 close(fd);
Mike Lockwoodbe125a52010-07-12 18:54:16 -040082
83 mMutex.lock();
84 delete mServer;
85 mServer = NULL;
86 mMutex.unlock();
Mike Lockwood98ef64e2010-06-29 16:42:13 -040087
88 bool done = mDone;
89 if (done)
90 delete this;
91 LOGD("threadLoop returning %s", (done ? "false" : "true"));
92 return !done;
93 }
94
95 void setDone() { mDone = true; }
Mike Lockwoodbe125a52010-07-12 18:54:16 -040096
97 void sendObjectAdded(MtpObjectHandle handle) {
98 mMutex.lock();
99 if (mServer)
100 mServer->sendObjectAdded(handle);
101 else
102 LOGE("sendObjectAdded called while disconnected\n");
103 mMutex.unlock();
104 }
105
106 void sendObjectRemoved(MtpObjectHandle handle) {
107 mMutex.lock();
108 if (mServer)
109 mServer->sendObjectRemoved(handle);
110 else
111 LOGE("sendObjectRemoved called while disconnected\n");
112 mMutex.unlock();
113 }
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400114};
115
Mike Lockwoodff164a72010-07-15 15:01:17 -0400116#endif // HAVE_ANDROID_OS
117
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400118static void
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400119android_media_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase, jstring storagePath)
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400120{
Mike Lockwoodff164a72010-07-15 15:01:17 -0400121#ifdef HAVE_ANDROID_OS
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400122 LOGD("setup\n");
123
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400124 MtpDatabase* database = getMtpDatabase(env, javaDatabase);
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400125 const char *storagePathStr = env->GetStringUTFChars(storagePath, NULL);
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400126
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400127 MtpThread* thread = new MtpThread(database, storagePathStr);
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400128 env->SetIntField(thiz, field_context, (int)thread);
129
130 env->ReleaseStringUTFChars(storagePath, storagePathStr);
Mike Lockwoodff164a72010-07-15 15:01:17 -0400131#endif
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400132}
133
134static void
135android_media_MtpServer_finalize(JNIEnv *env, jobject thiz)
136{
137 LOGD("finalize\n");
138}
139
140
141static void
142android_media_MtpServer_start(JNIEnv *env, jobject thiz)
143{
Mike Lockwoodff164a72010-07-15 15:01:17 -0400144#ifdef HAVE_ANDROID_OS
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400145 LOGD("start\n");
146 MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
147 thread->run("MtpThread");
Mike Lockwoodff164a72010-07-15 15:01:17 -0400148#endif // HAVE_ANDROID_OS
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400149}
150
151static void
152android_media_MtpServer_stop(JNIEnv *env, jobject thiz)
153{
Mike Lockwoodff164a72010-07-15 15:01:17 -0400154#ifdef HAVE_ANDROID_OS
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400155 LOGD("stop\n");
156 MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
157 if (thread) {
158 thread->setDone();
159 env->SetIntField(thiz, field_context, 0);
160 }
Mike Lockwoodff164a72010-07-15 15:01:17 -0400161#endif
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400162}
163
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400164static void
165android_media_MtpServer_send_object_added(JNIEnv *env, jobject thiz, jint handle)
166{
Mike Lockwoodff164a72010-07-15 15:01:17 -0400167#ifdef HAVE_ANDROID_OS
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400168 LOGD("send_object_added %d\n", handle);
169 MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
170 if (thread)
171 thread->sendObjectAdded(handle);
172 else
173 LOGE("sendObjectAdded called while disconnected\n");
Mike Lockwoodff164a72010-07-15 15:01:17 -0400174#endif
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400175}
176
177static void
178android_media_MtpServer_send_object_removed(JNIEnv *env, jobject thiz, jint handle)
179{
Mike Lockwoodff164a72010-07-15 15:01:17 -0400180#ifdef HAVE_ANDROID_OS
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400181 LOGD("send_object_removed %d\n", handle);
182 MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
183 if (thread)
184 thread->sendObjectRemoved(handle);
185 else
186 LOGE("sendObjectRemoved called while disconnected\n");
Mike Lockwoodff164a72010-07-15 15:01:17 -0400187#endif
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400188}
189
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400190// ----------------------------------------------------------------------------
191
192static JNINativeMethod gMethods[] = {
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400193 {"native_setup", "(Landroid/media/MtpDatabase;Ljava/lang/String;)V",
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400194 (void *)android_media_MtpServer_setup},
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400195 {"native_finalize", "()V", (void *)android_media_MtpServer_finalize},
196 {"native_start", "()V", (void *)android_media_MtpServer_start},
197 {"native_stop", "()V", (void *)android_media_MtpServer_stop},
198 {"native_send_object_added", "(I)V", (void *)android_media_MtpServer_send_object_added},
199 {"native_send_object_removed", "(I)V", (void *)android_media_MtpServer_send_object_removed},
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400200};
201
202static const char* const kClassPathName = "android/media/MtpServer";
203
204int register_android_media_MtpServer(JNIEnv *env)
205{
206 jclass clazz;
207
208 LOGD("register_android_media_MtpServer\n");
209
210 clazz = env->FindClass("android/media/MtpServer");
211 if (clazz == NULL) {
212 LOGE("Can't find android/media/MtpServer");
213 return -1;
214 }
215 field_context = env->GetFieldID(clazz, "mNativeContext", "I");
216 if (field_context == NULL) {
217 LOGE("Can't find MtpServer.mNativeContext");
218 return -1;
219 }
220
221 return AndroidRuntime::registerNativeMethods(env,
222 "android/media/MtpServer", gMethods, NELEM(gMethods));
223}