MTP: Clean up MtpServer initialization and threading:
Move thread from native to Java code
Remove the stop() method (the thread will exit on its own)
Change-Id: Ib897c3630162f82669a4ee8c187e8172da50b29d
diff --git a/media/jni/android_mtp_MtpServer.cpp b/media/jni/android_mtp_MtpServer.cpp
index 446b630..107db08 100644
--- a/media/jni/android_mtp_MtpServer.cpp
+++ b/media/jni/android_mtp_MtpServer.cpp
@@ -22,13 +22,8 @@
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
-#include <sys/ioctl.h>
#include <utils/threads.h>
-#ifdef HAVE_ANDROID_OS
-#include <linux/usb/f_mtp.h>
-#endif
-
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
@@ -39,8 +34,8 @@
using namespace android;
-// MtpStorage class
-jclass clazz_MtpStorage;
+// MtpServer fields
+static jfieldID field_MtpServer_nativeContext;
// MtpStorage fields
static jfieldID field_MtpStorage_storageId;
@@ -57,173 +52,78 @@
// in android_mtp_MtpDatabase.cpp
extern MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database);
-// ----------------------------------------------------------------------------
-
-#ifdef HAVE_ANDROID_OS
-
-static bool ExceptionCheck(void* env)
-{
- return ((JNIEnv *)env)->ExceptionCheck();
+static inline MtpServer* getMtpServer(JNIEnv *env, jobject thiz) {
+ return (MtpServer*)env->GetIntField(thiz, field_MtpServer_nativeContext);
}
-class MtpThread : public Thread {
-private:
- MtpDatabase* mDatabase;
- bool mPtp;
- MtpServer* mServer;
- MtpStorageList mStorageList;
- int mFd;
-
-public:
- MtpThread(MtpDatabase* database, bool usePtp)
- : mDatabase(database),
- mPtp(usePtp),
- mServer(NULL),
- mFd(-1)
- {
- }
-
- virtual ~MtpThread() {
- }
-
- void addStorage(MtpStorage *storage) {
- mStorageList.push(storage);
- if (mServer)
- mServer->addStorage(storage);
- }
-
- void removeStorage(MtpStorageID id) {
- MtpStorage* storage = mServer->getStorage(id);
- if (storage) {
- for (size_t i = 0; i < mStorageList.size(); i++) {
- if (mStorageList[i] == storage) {
- mStorageList.removeAt(i);
- break;
- }
- }
- if (mServer)
- mServer->removeStorage(storage);
- delete storage;
- }
- }
-
- void start() {
- run("MtpThread");
- }
-
- virtual bool threadLoop() {
- sMutex.lock();
-
- mFd = open("/dev/mtp_usb", O_RDWR);
- if (mFd >= 0) {
- mServer = new MtpServer(mFd, mDatabase, mPtp, AID_MEDIA_RW, 0664, 0775);
- for (size_t i = 0; i < mStorageList.size(); i++) {
- mServer->addStorage(mStorageList[i]);
- }
- } else {
- LOGE("could not open MTP driver, errno: %d", errno);
- }
-
- sMutex.unlock();
- mServer->run();
- sMutex.lock();
-
- close(mFd);
- mFd = -1;
- delete mServer;
- mServer = NULL;
-
- sMutex.unlock();
- // delay a bit before retrying to avoid excessive spin
- if (!exitPending()) {
- sleep(1);
- }
-
- return true;
- }
-
- void sendObjectAdded(MtpObjectHandle handle) {
- if (mServer)
- mServer->sendObjectAdded(handle);
- }
-
- void sendObjectRemoved(MtpObjectHandle handle) {
- if (mServer)
- mServer->sendObjectRemoved(handle);
- }
-};
-
-// This smart pointer is necessary for preventing MtpThread from exiting too early
-static sp<MtpThread> sThread;
-
-#endif // HAVE_ANDROID_OS
-
static void
android_mtp_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase, jboolean usePtp)
{
-#ifdef HAVE_ANDROID_OS
- // create the thread and assign it to the smart pointer
- sThread = new MtpThread(getMtpDatabase(env, javaDatabase), usePtp);
-#endif
-}
-
-static void
-android_mtp_MtpServer_start(JNIEnv *env, jobject thiz)
-{
-#ifdef HAVE_ANDROID_OS
- sMutex.lock();
- MtpThread *thread = sThread.get();
- if (thread)
- thread->start();
- sMutex.unlock();
-#endif // HAVE_ANDROID_OS
-}
-
-static void
-android_mtp_MtpServer_stop(JNIEnv *env, jobject thiz)
-{
-#ifdef HAVE_ANDROID_OS
- sMutex.lock();
- MtpThread *thread = sThread.get();
- if (thread) {
- thread->requestExitAndWait();
- sThread = NULL;
+ int fd = open("/dev/mtp_usb", O_RDWR);
+ if (fd >= 0) {
+ MtpServer* server = new MtpServer(fd, getMtpDatabase(env, javaDatabase),
+ usePtp, AID_MEDIA_RW, 0664, 0775);
+ env->SetIntField(thiz, field_MtpServer_nativeContext, (int)server);
+ } else {
+ LOGE("could not open MTP driver, errno: %d", errno);
}
- sMutex.unlock();
-#endif
+}
+
+static void
+android_mtp_MtpServer_run(JNIEnv *env, jobject thiz)
+{
+ MtpServer* server = getMtpServer(env, thiz);
+ if (server)
+ server->run();
+ else
+ LOGE("server is null in run");
+}
+
+static void
+android_mtp_MtpServer_cleanup(JNIEnv *env, jobject thiz)
+{
+ Mutex::Autolock autoLock(sMutex);
+
+ MtpServer* server = getMtpServer(env, thiz);
+ if (server) {
+ delete server;
+ env->SetIntField(thiz, field_MtpServer_nativeContext, 0);
+ } else {
+ LOGE("server is null in cleanup");
+ }
}
static void
android_mtp_MtpServer_send_object_added(JNIEnv *env, jobject thiz, jint handle)
{
-#ifdef HAVE_ANDROID_OS
- sMutex.lock();
- MtpThread *thread = sThread.get();
- if (thread)
- thread->sendObjectAdded(handle);
- sMutex.unlock();
-#endif
+ Mutex::Autolock autoLock(sMutex);
+
+ MtpServer* server = getMtpServer(env, thiz);
+ if (server)
+ server->sendObjectAdded(handle);
+ else
+ LOGE("server is null in send_object_added");
}
static void
android_mtp_MtpServer_send_object_removed(JNIEnv *env, jobject thiz, jint handle)
{
-#ifdef HAVE_ANDROID_OS
- sMutex.lock();
- MtpThread *thread = sThread.get();
- if (thread)
- thread->sendObjectRemoved(handle);
- sMutex.unlock();
-#endif
+ Mutex::Autolock autoLock(sMutex);
+
+ MtpServer* server = getMtpServer(env, thiz);
+ if (server)
+ server->sendObjectRemoved(handle);
+ else
+ LOGE("server is null in send_object_removed");
}
static void
android_mtp_MtpServer_add_storage(JNIEnv *env, jobject thiz, jobject jstorage)
{
-#ifdef HAVE_ANDROID_OS
- sMutex.lock();
- MtpThread *thread = sThread.get();
- if (thread) {
+ Mutex::Autolock autoLock(sMutex);
+
+ MtpServer* server = getMtpServer(env, thiz);
+ if (server) {
jint storageID = env->GetIntField(jstorage, field_MtpStorage_storageId);
jstring path = (jstring)env->GetObjectField(jstorage, field_MtpStorage_path);
jstring description = (jstring)env->GetObjectField(jstorage, field_MtpStorage_description);
@@ -237,7 +137,7 @@
if (descriptionStr != NULL) {
MtpStorage* storage = new MtpStorage(storageID, pathStr, descriptionStr,
reserveSpace, removable, maxFileSize);
- thread->addStorage(storage);
+ server->addStorage(storage);
env->ReleaseStringUTFChars(path, pathStr);
env->ReleaseStringUTFChars(description, descriptionStr);
} else {
@@ -245,24 +145,24 @@
}
}
} else {
- LOGE("MtpThread is null in add_storage");
+ LOGE("server is null in add_storage");
}
- sMutex.unlock();
-#endif
}
static void
android_mtp_MtpServer_remove_storage(JNIEnv *env, jobject thiz, jint storageId)
{
-#ifdef HAVE_ANDROID_OS
- sMutex.lock();
- MtpThread *thread = sThread.get();
- if (thread)
- thread->removeStorage(storageId);
- else
- LOGE("MtpThread is null in remove_storage");
- sMutex.unlock();
-#endif
+ Mutex::Autolock autoLock(sMutex);
+
+ MtpServer* server = getMtpServer(env, thiz);
+ if (server) {
+ MtpStorage* storage = server->getStorage(storageId);
+ if (storage) {
+ server->removeStorage(storage);
+ delete storage;
+ }
+ } else
+ LOGE("server is null in remove_storage");
}
// ----------------------------------------------------------------------------
@@ -270,8 +170,8 @@
static JNINativeMethod gMethods[] = {
{"native_setup", "(Landroid/mtp/MtpDatabase;Z)V",
(void *)android_mtp_MtpServer_setup},
- {"native_start", "()V", (void *)android_mtp_MtpServer_start},
- {"native_stop", "()V", (void *)android_mtp_MtpServer_stop},
+ {"native_run", "()V", (void *)android_mtp_MtpServer_run},
+ {"native_cleanup", "()V", (void *)android_mtp_MtpServer_cleanup},
{"native_send_object_added", "(I)V", (void *)android_mtp_MtpServer_send_object_added},
{"native_send_object_removed", "(I)V", (void *)android_mtp_MtpServer_send_object_removed},
{"native_add_storage", "(Landroid/mtp/MtpStorage;)V",
@@ -320,13 +220,17 @@
LOGE("Can't find MtpStorage.mMaxFileSize");
return -1;
}
- clazz_MtpStorage = (jclass)env->NewGlobalRef(clazz);
clazz = env->FindClass("android/mtp/MtpServer");
if (clazz == NULL) {
LOGE("Can't find android/mtp/MtpServer");
return -1;
}
+ field_MtpServer_nativeContext = env->GetFieldID(clazz, "mNativeContext", "I");
+ if (field_MtpServer_nativeContext == NULL) {
+ LOGE("Can't find MtpServer.mNativeContext");
+ return -1;
+ }
return AndroidRuntime::registerNativeMethods(env,
"android/mtp/MtpServer", gMethods, NELEM(gMethods));