Loading media/java/android/mtp/MtpServer.java +10 −20 Original line number Diff line number Diff line Loading @@ -16,18 +16,13 @@ package android.mtp; import android.util.Log; /** * Java wrapper for MTP/PTP support as USB responder. * {@hide} */ public class MtpServer { private final Object mLock = new Object(); private boolean mStarted; public class MtpServer implements Runnable { private static final String TAG = "MtpServer"; private int mNativeContext; // accessed by native methods static { System.loadLibrary("media_jni"); Loading @@ -38,19 +33,14 @@ public class MtpServer { } public void start() { synchronized (mLock) { native_start(); mStarted = true; } Thread thread = new Thread(this, "MtpServer"); thread.start(); } public void stop() { synchronized (mLock) { if (mStarted) { native_stop(); mStarted = false; } } @Override public void run() { native_run(); native_cleanup(); } public void sendObjectAdded(int handle) { Loading @@ -70,8 +60,8 @@ public class MtpServer { } private native final void native_setup(MtpDatabase database, boolean usePtp); private native final void native_start(); private native final void native_stop(); private native final void native_run(); private native final void native_cleanup(); private native final void native_send_object_added(int handle); private native final void native_send_object_removed(int handle); private native final void native_add_storage(MtpStorage storage); Loading media/jni/android_mtp_MtpServer.cpp +65 −161 Original line number Diff line number Diff line Loading @@ -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" Loading @@ -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; Loading @@ -57,173 +52,78 @@ static Mutex sMutex; // 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) static void android_mtp_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase, jboolean usePtp) { } 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]); } 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(); 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) android_mtp_MtpServer_run(JNIEnv *env, jobject thiz) { #ifdef HAVE_ANDROID_OS // create the thread and assign it to the smart pointer sThread = new MtpThread(getMtpDatabase(env, javaDatabase), usePtp); #endif MtpServer* server = getMtpServer(env, thiz); if (server) server->run(); else LOGE("server is null in run"); } static void android_mtp_MtpServer_start(JNIEnv *env, jobject thiz) android_mtp_MtpServer_cleanup(JNIEnv *env, jobject thiz) { #ifdef HAVE_ANDROID_OS sMutex.lock(); MtpThread *thread = sThread.get(); if (thread) thread->start(); sMutex.unlock(); #endif // HAVE_ANDROID_OS } Mutex::Autolock autoLock(sMutex); 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; MtpServer* server = getMtpServer(env, thiz); if (server) { delete server; env->SetIntField(thiz, field_MtpServer_nativeContext, 0); } else { LOGE("server is null in cleanup"); } sMutex.unlock(); #endif } 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); Loading @@ -237,7 +137,7 @@ android_mtp_MtpServer_add_storage(JNIEnv *env, jobject thiz, jobject jstorage) 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 { Loading @@ -245,24 +145,24 @@ android_mtp_MtpServer_add_storage(JNIEnv *env, jobject thiz, jobject jstorage) } } } 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"); } // ---------------------------------------------------------------------------- Loading @@ -270,8 +170,8 @@ android_mtp_MtpServer_remove_storage(JNIEnv *env, jobject thiz, jint storageId) 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", Loading Loading @@ -320,13 +220,17 @@ int register_android_mtp_MtpServer(JNIEnv *env) 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)); Loading media/mtp/MtpServer.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -237,6 +237,8 @@ void MtpServer::run() { if (mSessionOpen) mDatabase->sessionEnded(); close(fd); mFD = -1; } void MtpServer::sendObjectAdded(MtpObjectHandle handle) { Loading Loading
media/java/android/mtp/MtpServer.java +10 −20 Original line number Diff line number Diff line Loading @@ -16,18 +16,13 @@ package android.mtp; import android.util.Log; /** * Java wrapper for MTP/PTP support as USB responder. * {@hide} */ public class MtpServer { private final Object mLock = new Object(); private boolean mStarted; public class MtpServer implements Runnable { private static final String TAG = "MtpServer"; private int mNativeContext; // accessed by native methods static { System.loadLibrary("media_jni"); Loading @@ -38,19 +33,14 @@ public class MtpServer { } public void start() { synchronized (mLock) { native_start(); mStarted = true; } Thread thread = new Thread(this, "MtpServer"); thread.start(); } public void stop() { synchronized (mLock) { if (mStarted) { native_stop(); mStarted = false; } } @Override public void run() { native_run(); native_cleanup(); } public void sendObjectAdded(int handle) { Loading @@ -70,8 +60,8 @@ public class MtpServer { } private native final void native_setup(MtpDatabase database, boolean usePtp); private native final void native_start(); private native final void native_stop(); private native final void native_run(); private native final void native_cleanup(); private native final void native_send_object_added(int handle); private native final void native_send_object_removed(int handle); private native final void native_add_storage(MtpStorage storage); Loading
media/jni/android_mtp_MtpServer.cpp +65 −161 Original line number Diff line number Diff line Loading @@ -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" Loading @@ -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; Loading @@ -57,173 +52,78 @@ static Mutex sMutex; // 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) static void android_mtp_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase, jboolean usePtp) { } 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]); } 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(); 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) android_mtp_MtpServer_run(JNIEnv *env, jobject thiz) { #ifdef HAVE_ANDROID_OS // create the thread and assign it to the smart pointer sThread = new MtpThread(getMtpDatabase(env, javaDatabase), usePtp); #endif MtpServer* server = getMtpServer(env, thiz); if (server) server->run(); else LOGE("server is null in run"); } static void android_mtp_MtpServer_start(JNIEnv *env, jobject thiz) android_mtp_MtpServer_cleanup(JNIEnv *env, jobject thiz) { #ifdef HAVE_ANDROID_OS sMutex.lock(); MtpThread *thread = sThread.get(); if (thread) thread->start(); sMutex.unlock(); #endif // HAVE_ANDROID_OS } Mutex::Autolock autoLock(sMutex); 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; MtpServer* server = getMtpServer(env, thiz); if (server) { delete server; env->SetIntField(thiz, field_MtpServer_nativeContext, 0); } else { LOGE("server is null in cleanup"); } sMutex.unlock(); #endif } 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); Loading @@ -237,7 +137,7 @@ android_mtp_MtpServer_add_storage(JNIEnv *env, jobject thiz, jobject jstorage) 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 { Loading @@ -245,24 +145,24 @@ android_mtp_MtpServer_add_storage(JNIEnv *env, jobject thiz, jobject jstorage) } } } 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"); } // ---------------------------------------------------------------------------- Loading @@ -270,8 +170,8 @@ android_mtp_MtpServer_remove_storage(JNIEnv *env, jobject thiz, jint storageId) 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", Loading Loading @@ -320,13 +220,17 @@ int register_android_mtp_MtpServer(JNIEnv *env) 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)); Loading
media/mtp/MtpServer.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -237,6 +237,8 @@ void MtpServer::run() { if (mSessionOpen) mDatabase->sessionEnded(); close(fd); mFD = -1; } void MtpServer::sendObjectAdded(MtpObjectHandle handle) { Loading