blob: e025ef1acff8c76fe0cee81793051e607c7e502c [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"
Mike Lockwood467ca0d2011-02-18 09:07:14 -050038#include "MtpStorage.h"
Mike Lockwood98ef64e2010-06-29 16:42:13 -040039
Mike Lockwood81ea83d2010-06-30 17:49:41 -040040using namespace android;
Mike Lockwood98ef64e2010-06-29 16:42:13 -040041
42// ----------------------------------------------------------------------------
43
Mike Lockwood0cd01362010-12-30 11:54:33 -050044// in android_mtp_MtpDatabase.cpp
Mike Lockwoodd21eac92010-07-03 00:44:05 -040045extern 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 Lockwood467ca0d2011-02-18 09:07:14 -050060 MtpStorage* mStorage;
Mike Lockwood071b2b62011-01-25 09:29:27 -080061 Mutex mMutex;
62 bool mUsePtp;
Mike Lockwood66e57f62011-02-18 13:24:01 -050063 bool mLocked;
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -040064 int mFd;
Mike Lockwood98ef64e2010-06-29 16:42:13 -040065
66public:
Mike Lockwood467ca0d2011-02-18 09:07:14 -050067 MtpThread(MtpDatabase* database, MtpStorage* storage)
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -040068 : mDatabase(database),
Mike Lockwood23ee42f2010-08-03 15:17:55 -040069 mServer(NULL),
Mike Lockwood467ca0d2011-02-18 09:07:14 -050070 mStorage(storage),
Mike Lockwood66e57f62011-02-18 13:24:01 -050071 mUsePtp(false),
72 mLocked(false),
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -040073 mFd(-1)
Mike Lockwood98ef64e2010-06-29 16:42:13 -040074 {
75 }
76
Mike Lockwood467ca0d2011-02-18 09:07:14 -050077 virtual ~MtpThread() {
78 delete mStorage;
79 }
80
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -040081 void setPtpMode(bool usePtp) {
Mike Lockwood071b2b62011-01-25 09:29:27 -080082 mMutex.lock();
83 mUsePtp = usePtp;
84 mMutex.unlock();
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -040085 }
86
Mike Lockwood66e57f62011-02-18 13:24:01 -050087 void setLocked(bool locked) {
88 mMutex.lock();
89 if (locked != mLocked) {
90 if (mServer) {
91 if (locked)
92 mServer->removeStorage(mStorage);
93 else
94 mServer->addStorage(mStorage);
95 }
96 mLocked = locked;
97 }
98 mMutex.unlock();
99 }
100
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400101 virtual bool threadLoop() {
Mike Lockwood071b2b62011-01-25 09:29:27 -0800102 mMutex.lock();
103 mFd = open("/dev/mtp_usb", O_RDWR);
104 if (mFd >= 0) {
105 ioctl(mFd, MTP_SET_INTERFACE_MODE,
106 (mUsePtp ? MTP_INTERFACE_MODE_PTP : MTP_INTERFACE_MODE_MTP));
Mike Lockwood897f8942011-01-19 10:11:28 -0800107
108 mServer = new MtpServer(mFd, mDatabase, AID_MEDIA_RW, 0664, 0775);
Mike Lockwood66e57f62011-02-18 13:24:01 -0500109 if (!mLocked)
110 mServer->addStorage(mStorage);
Mike Lockwood897f8942011-01-19 10:11:28 -0800111
Mike Lockwood071b2b62011-01-25 09:29:27 -0800112 mMutex.unlock();
Mike Lockwooda1c91802011-01-18 20:11:29 -0800113 mServer->run();
Mike Lockwood071b2b62011-01-25 09:29:27 -0800114 mMutex.lock();
Mike Lockwooda1c91802011-01-18 20:11:29 -0800115
Mike Lockwood897f8942011-01-19 10:11:28 -0800116 close(mFd);
117 mFd = -1;
118 delete mServer;
119 mServer = NULL;
Mike Lockwood071b2b62011-01-25 09:29:27 -0800120 } else {
121 LOGE("could not open MTP driver, errno: %d", errno);
122 }
123 mMutex.unlock();
124 // delay a bit before retrying to avoid excessive spin
125 if (!exitPending()) {
126 sleep(1);
Mike Lockwood897f8942011-01-19 10:11:28 -0800127 }
Mike Lockwood2b2bff52010-08-18 12:32:26 -0400128
Mike Lockwood071b2b62011-01-25 09:29:27 -0800129 return true;
Mike Lockwooda1c91802011-01-18 20:11:29 -0800130 }
131
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400132 void sendObjectAdded(MtpObjectHandle handle) {
Mike Lockwood071b2b62011-01-25 09:29:27 -0800133 mMutex.lock();
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400134 if (mServer)
135 mServer->sendObjectAdded(handle);
Mike Lockwood071b2b62011-01-25 09:29:27 -0800136 mMutex.unlock();
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400137 }
138
139 void sendObjectRemoved(MtpObjectHandle handle) {
Mike Lockwood071b2b62011-01-25 09:29:27 -0800140 mMutex.lock();
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400141 if (mServer)
142 mServer->sendObjectRemoved(handle);
Mike Lockwood071b2b62011-01-25 09:29:27 -0800143 mMutex.unlock();
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400144 }
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400145};
146
Mike Lockwood071b2b62011-01-25 09:29:27 -0800147// This smart pointer is necessary for preventing MtpThread from exiting too early
148static sp<MtpThread> sThread;
149
Mike Lockwoodff164a72010-07-15 15:01:17 -0400150#endif // HAVE_ANDROID_OS
151
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400152static void
Mike Lockwood0cd01362010-12-30 11:54:33 -0500153android_mtp_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase,
Mike Lockwood7f36b192010-12-12 12:17:43 -0800154 jstring storagePath, jlong reserveSpace)
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400155{
Mike Lockwoodff164a72010-07-15 15:01:17 -0400156#ifdef HAVE_ANDROID_OS
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400157 MtpDatabase* database = getMtpDatabase(env, javaDatabase);
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400158 const char *storagePathStr = env->GetStringUTFChars(storagePath, NULL);
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400159
Mike Lockwood071b2b62011-01-25 09:29:27 -0800160 // create the thread and assign it to the smart pointer
Mike Lockwood467ca0d2011-02-18 09:07:14 -0500161 MtpStorage* storage = new MtpStorage(MTP_FIRST_STORAGE_ID, storagePathStr, reserveSpace);
162 sThread = new MtpThread(database, storage);
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400163
164 env->ReleaseStringUTFChars(storagePath, storagePathStr);
Mike Lockwoodff164a72010-07-15 15:01:17 -0400165#endif
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400166}
167
168static void
Mike Lockwood0cd01362010-12-30 11:54:33 -0500169android_mtp_MtpServer_start(JNIEnv *env, jobject thiz)
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400170{
Mike Lockwoodff164a72010-07-15 15:01:17 -0400171#ifdef HAVE_ANDROID_OS
Mike Lockwood071b2b62011-01-25 09:29:27 -0800172 MtpThread *thread = sThread.get();
173 if (thread)
174 thread->run("MtpThread");
Mike Lockwoodff164a72010-07-15 15:01:17 -0400175#endif // HAVE_ANDROID_OS
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400176}
177
178static void
Mike Lockwood0cd01362010-12-30 11:54:33 -0500179android_mtp_MtpServer_stop(JNIEnv *env, jobject thiz)
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400180{
Mike Lockwoodff164a72010-07-15 15:01:17 -0400181#ifdef HAVE_ANDROID_OS
Mike Lockwood071b2b62011-01-25 09:29:27 -0800182 MtpThread *thread = sThread.get();
183 if (thread) {
184 thread->requestExitAndWait();
185 sThread = NULL;
186 }
Mike Lockwoodff164a72010-07-15 15:01:17 -0400187#endif
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400188}
189
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400190static void
Mike Lockwood0cd01362010-12-30 11:54:33 -0500191android_mtp_MtpServer_send_object_added(JNIEnv *env, jobject thiz, jint handle)
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400192{
Mike Lockwoodff164a72010-07-15 15:01:17 -0400193#ifdef HAVE_ANDROID_OS
Mike Lockwood071b2b62011-01-25 09:29:27 -0800194 MtpThread *thread = sThread.get();
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400195 if (thread)
196 thread->sendObjectAdded(handle);
Mike Lockwoodff164a72010-07-15 15:01:17 -0400197#endif
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400198}
199
200static void
Mike Lockwood0cd01362010-12-30 11:54:33 -0500201android_mtp_MtpServer_send_object_removed(JNIEnv *env, jobject thiz, jint handle)
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400202{
Mike Lockwoodff164a72010-07-15 15:01:17 -0400203#ifdef HAVE_ANDROID_OS
Mike Lockwood071b2b62011-01-25 09:29:27 -0800204 MtpThread *thread = sThread.get();
Mike Lockwoodbe125a52010-07-12 18:54:16 -0400205 if (thread)
206 thread->sendObjectRemoved(handle);
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
Mike Lockwood0cd01362010-12-30 11:54:33 -0500211android_mtp_MtpServer_set_ptp_mode(JNIEnv *env, jobject thiz, jboolean usePtp)
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -0400212{
213#ifdef HAVE_ANDROID_OS
Mike Lockwood071b2b62011-01-25 09:29:27 -0800214 MtpThread *thread = sThread.get();
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -0400215 if (thread)
216 thread->setPtpMode(usePtp);
Mike Lockwooda1c91802011-01-18 20:11:29 -0800217#endif
Mike Lockwoodeabe8bf2010-08-31 14:35:23 -0400218}
219
Mike Lockwood66e57f62011-02-18 13:24:01 -0500220static void
221android_mtp_MtpServer_set_locked(JNIEnv *env, jobject thiz, jboolean locked)
222{
223#ifdef HAVE_ANDROID_OS
224 MtpThread *thread = sThread.get();
225 if (thread)
226 thread->setLocked(locked);
227#endif
228}
229
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400230// ----------------------------------------------------------------------------
231
232static JNINativeMethod gMethods[] = {
Mike Lockwood0cd01362010-12-30 11:54:33 -0500233 {"native_setup", "(Landroid/mtp/MtpDatabase;Ljava/lang/String;J)V",
234 (void *)android_mtp_MtpServer_setup},
Mike Lockwood0cd01362010-12-30 11:54:33 -0500235 {"native_start", "()V", (void *)android_mtp_MtpServer_start},
236 {"native_stop", "()V", (void *)android_mtp_MtpServer_stop},
237 {"native_send_object_added", "(I)V", (void *)android_mtp_MtpServer_send_object_added},
238 {"native_send_object_removed", "(I)V", (void *)android_mtp_MtpServer_send_object_removed},
239 {"native_set_ptp_mode", "(Z)V", (void *)android_mtp_MtpServer_set_ptp_mode},
Mike Lockwood66e57f62011-02-18 13:24:01 -0500240 {"native_set_locked", "(Z)V", (void *)android_mtp_MtpServer_set_locked},
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400241};
242
Mike Lockwood0cd01362010-12-30 11:54:33 -0500243static const char* const kClassPathName = "android/mtp/MtpServer";
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400244
Mike Lockwood0cd01362010-12-30 11:54:33 -0500245int register_android_mtp_MtpServer(JNIEnv *env)
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400246{
247 jclass clazz;
248
Mike Lockwood0cd01362010-12-30 11:54:33 -0500249 clazz = env->FindClass("android/mtp/MtpServer");
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400250 if (clazz == NULL) {
Mike Lockwood0cd01362010-12-30 11:54:33 -0500251 LOGE("Can't find android/mtp/MtpServer");
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400252 return -1;
253 }
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400254
255 return AndroidRuntime::registerNativeMethods(env,
Mike Lockwood0cd01362010-12-30 11:54:33 -0500256 "android/mtp/MtpServer", gMethods, NELEM(gMethods));
Mike Lockwood98ef64e2010-06-29 16:42:13 -0400257}