Loading core/java/android/provider/MediaStore.java +7 −0 Original line number Original line Diff line number Diff line Loading @@ -273,6 +273,13 @@ public final class MediaStore { + "/object/" + objectId); + "/object/" + objectId); } } // used for MTP GetObjectReferences and SetObjectReferences public static final Uri getReferencesUri(String volumeName, long objectId) { return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName + "/object/" + objectId + "/references"); } /** /** * Fields for master table for all media files. * Fields for master table for all media files. * Table also contains MediaColumns._ID, DATA, SIZE and DATE_MODIFIED. * Table also contains MediaColumns._ID, DATA, SIZE and DATE_MODIFIED. Loading media/java/android/media/MtpDatabase.java +77 −1 Original line number Original line Diff line number Diff line Loading @@ -22,7 +22,10 @@ import android.content.IContentProvider; import android.database.Cursor; import android.database.Cursor; import android.net.Uri; import android.net.Uri; import android.os.RemoteException; import android.os.RemoteException; import android.provider.MediaStore.Audio; import android.provider.MediaStore.MediaColumns; import android.provider.MediaStore.MtpObjects; import android.provider.MediaStore.MtpObjects; import android.provider.Mtp; import android.util.Log; import android.util.Log; /** /** Loading Loading @@ -120,7 +123,33 @@ public class MtpDatabase { private void endSendObject(String path, int handle, int format, boolean succeeded) { private void endSendObject(String path, int handle, int format, boolean succeeded) { if (succeeded) { if (succeeded) { // handle abstract playlists separately // they do not exist in the file system so don't use the media scanner here if (format == Mtp.Object.FORMAT_ABSTRACT_AV_PLAYLIST) { // Strip Windows Media Player file extension if (path.endsWith(".pla")) { path = path.substring(0, path.length() - 4); } // extract name from path String name = path; int lastSlash = name.lastIndexOf('/'); if (lastSlash >= 0) { name = name.substring(lastSlash + 1); } ContentValues values = new ContentValues(1); values.put(Audio.Playlists.DATA, path); values.put(Audio.Playlists.NAME, name); values.put(MediaColumns.MEDIA_SCANNER_NEW_OBJECT_ID, handle); try { Uri uri = mMediaProvider.insert(Audio.Playlists.EXTERNAL_CONTENT_URI, values); } catch (RemoteException e) { Log.e(TAG, "RemoteException in endSendObject", e); } } else { Uri uri = mMediaScanner.scanMtpFile(path, mVolumeName, handle, format); Uri uri = mMediaScanner.scanMtpFile(path, mVolumeName, handle, format); } } else { } else { deleteFile(handle); deleteFile(handle); } } Loading Loading @@ -338,6 +367,53 @@ public class MtpDatabase { } } } } private int[] getObjectReferences(int handle) { Log.d(TAG, "getObjectReferences for: " + handle); Uri uri = MtpObjects.getReferencesUri(mVolumeName, handle); Cursor c = null; try { c = mMediaProvider.query(uri, ID_PROJECTION, null, null, null); if (c == null) { return null; } int count = c.getCount(); if (count > 0) { int[] result = new int[count]; for (int i = 0; i < count; i++) { c.moveToNext(); result[i] = c.getInt(0); } return result; } } catch (RemoteException e) { Log.e(TAG, "RemoteException in getObjectList", e); } finally { if (c != null) { c.close(); } } return null; } private int setObjectReferences(int handle, int[] references) { Uri uri = MtpObjects.getReferencesUri(mVolumeName, handle); int count = references.length; ContentValues[] valuesList = new ContentValues[count]; for (int i = 0; i < count; i++) { ContentValues values = new ContentValues(); values.put(MtpObjects.ObjectColumns._ID, references[i]); valuesList[i] = values; } try { if (count == mMediaProvider.bulkInsert(uri, valuesList)) { return MTP_RESPONSE_OK; } } catch (RemoteException e) { Log.e(TAG, "RemoteException in setObjectReferences", e); } return MTP_RESPONSE_GENERAL_ERROR; } // used by the JNI code // used by the JNI code private int mNativeContext; private int mNativeContext; Loading media/jni/android_media_MtpDatabase.cpp +48 −0 Original line number Original line Diff line number Diff line Loading @@ -44,6 +44,8 @@ static jmethodID method_getObjectProperty; static jmethodID method_getObjectInfo; static jmethodID method_getObjectInfo; static jmethodID method_getObjectFilePath; static jmethodID method_getObjectFilePath; static jmethodID method_deleteFile; static jmethodID method_deleteFile; static jmethodID method_getObjectReferences; static jmethodID method_setObjectReferences; static jfieldID field_context; static jfieldID field_context; MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database) { MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database) { Loading Loading @@ -98,6 +100,11 @@ public: virtual MtpResponseCode deleteFile(MtpObjectHandle handle); virtual MtpResponseCode deleteFile(MtpObjectHandle handle); bool getPropertyInfo(MtpObjectProperty property, int& type); bool getPropertyInfo(MtpObjectProperty property, int& type); virtual MtpObjectHandleList* getObjectReferences(MtpObjectHandle handle); virtual MtpResponseCode setObjectReferences(MtpObjectHandle handle, MtpObjectHandleList* references); }; }; MyMtpDatabase::MyMtpDatabase(JNIEnv *env, jobject client) MyMtpDatabase::MyMtpDatabase(JNIEnv *env, jobject client) Loading Loading @@ -344,6 +351,37 @@ bool MyMtpDatabase::getPropertyInfo(MtpObjectProperty property, int& type) { return false; return false; } } MtpObjectHandleList* MyMtpDatabase::getObjectReferences(MtpObjectHandle handle) { JNIEnv* env = AndroidRuntime::getJNIEnv(); jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectReferences, (jint)handle); if (!array) return NULL; MtpObjectHandleList* list = new MtpObjectHandleList(); jint* handles = env->GetIntArrayElements(array, 0); jsize length = env->GetArrayLength(array); for (int i = 0; i < length; i++) list->push(handles[i]); env->ReleaseIntArrayElements(array, handles, 0); return list; } MtpResponseCode MyMtpDatabase::setObjectReferences(MtpObjectHandle handle, MtpObjectHandleList* references) { JNIEnv* env = AndroidRuntime::getJNIEnv(); int count = references->size(); jintArray array = env->NewIntArray(count); if (!array) { LOGE("out of memory in setObjectReferences"); return false; } jint* handles = env->GetIntArrayElements(array, 0); for (int i = 0; i < count; i++) handles[i] = (*references)[i]; env->ReleaseIntArrayElements(array, handles, 0); return env->CallIntMethod(mDatabase, method_setObjectReferences, (jint)handle, array); } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) { static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) { Loading Loading @@ -442,6 +480,16 @@ int register_android_media_MtpDatabase(JNIEnv *env) LOGE("Can't find deleteFile"); LOGE("Can't find deleteFile"); return -1; return -1; } } method_getObjectReferences = env->GetMethodID(clazz, "getObjectReferences", "(I)[I"); if (method_getObjectReferences == NULL) { LOGE("Can't find getObjectReferences"); return -1; } method_setObjectReferences = env->GetMethodID(clazz, "setObjectReferences", "(I[I)I"); if (method_setObjectReferences == NULL) { LOGE("Can't find setObjectReferences"); return -1; } field_context = env->GetFieldID(clazz, "mNativeContext", "I"); field_context = env->GetFieldID(clazz, "mNativeContext", "I"); if (field_context == NULL) { if (field_context == NULL) { LOGE("Can't find MtpDatabase.mNativeContext"); LOGE("Can't find MtpDatabase.mNativeContext"); Loading media/jni/android_media_MtpServer.cpp +56 −38 Original line number Original line Diff line number Diff line Loading @@ -36,6 +36,7 @@ using namespace android; // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- static jfieldID field_context; static jfieldID field_context; static Mutex sMutex; // in android_media_MtpDatabase.cpp // in android_media_MtpDatabase.cpp extern MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database); extern MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database); Loading @@ -55,61 +56,78 @@ private: MtpServer* mServer; MtpServer* mServer; String8 mStoragePath; String8 mStoragePath; bool mDone; bool mDone; Mutex mMutex; jobject mJavaServer; public: public: MtpThread(MtpDatabase* database, const char* storagePath) MtpThread(MtpDatabase* database, const char* storagePath, jobject javaServer) : mDatabase(database), mServer(NULL), mStoragePath(storagePath), mDone(false) : mDatabase(database), mServer(NULL), mStoragePath(storagePath), mDone(false), mJavaServer(javaServer) { { } } virtual bool threadLoop() { virtual bool threadLoop() { while (1) { int fd = open("/dev/mtp_usb", O_RDWR); int fd = open("/dev/mtp_usb", O_RDWR); printf("open returned %d\n", fd); printf("open returned %d\n", fd); if (fd < 0) { if (fd < 0) { LOGE("could not open MTP driver\n"); LOGE("could not open MTP driver\n"); return false; break; } } mMutex.lock(); sMutex.lock(); mServer = new MtpServer(fd, mDatabase, AID_SDCARD_RW, 0664, 0775); mServer = new MtpServer(fd, mDatabase, AID_SDCARD_RW, 0664, 0775); mServer->addStorage(mStoragePath); mServer->addStorage(mStoragePath); mMutex.unlock(); sMutex.unlock(); LOGD("MtpThread mServer->run"); LOGD("MtpThread mServer->run"); mServer->run(); mServer->run(); close(fd); close(fd); mMutex.lock(); sMutex.lock(); delete mServer; delete mServer; mServer = NULL; mServer = NULL; mMutex.unlock(); if (mDone) goto done; sMutex.unlock(); // wait a bit before retrying sleep(1); } bool done = mDone; sMutex.lock(); if (done) done: delete this; JNIEnv* env = AndroidRuntime::getJNIEnv(); LOGD("threadLoop returning %s", (done ? "false" : "true")); env->SetIntField(mJavaServer, field_context, 0); return !done; env->DeleteGlobalRef(mJavaServer); sMutex.unlock(); LOGD("threadLoop returning"); return false; } } void setDone() { mDone = true; } void setDone() { LOGD("setDone"); mDone = true; } void sendObjectAdded(MtpObjectHandle handle) { void sendObjectAdded(MtpObjectHandle handle) { mMutex.lock(); sMutex.lock(); if (mServer) if (mServer) mServer->sendObjectAdded(handle); mServer->sendObjectAdded(handle); else else LOGE("sendObjectAdded called while disconnected\n"); LOGE("sendObjectAdded called while disconnected\n"); mMutex.unlock(); sMutex.unlock(); } } void sendObjectRemoved(MtpObjectHandle handle) { void sendObjectRemoved(MtpObjectHandle handle) { mMutex.lock(); sMutex.lock(); if (mServer) if (mServer) mServer->sendObjectRemoved(handle); mServer->sendObjectRemoved(handle); else else LOGE("sendObjectRemoved called while disconnected\n"); LOGE("sendObjectRemoved called while disconnected\n"); mMutex.unlock(); sMutex.unlock(); } } }; }; Loading @@ -124,7 +142,7 @@ android_media_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase, j MtpDatabase* database = getMtpDatabase(env, javaDatabase); MtpDatabase* database = getMtpDatabase(env, javaDatabase); const char *storagePathStr = env->GetStringUTFChars(storagePath, NULL); const char *storagePathStr = env->GetStringUTFChars(storagePath, NULL); MtpThread* thread = new MtpThread(database, storagePathStr); MtpThread* thread = new MtpThread(database, storagePathStr, env->NewGlobalRef(thiz)); env->SetIntField(thiz, field_context, (int)thread); env->SetIntField(thiz, field_context, (int)thread); env->ReleaseStringUTFChars(storagePath, storagePathStr); env->ReleaseStringUTFChars(storagePath, storagePathStr); Loading Loading @@ -153,11 +171,11 @@ android_media_MtpServer_stop(JNIEnv *env, jobject thiz) { { #ifdef HAVE_ANDROID_OS #ifdef HAVE_ANDROID_OS LOGD("stop\n"); LOGD("stop\n"); sMutex.lock(); MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context); MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context); if (thread) { if (thread) thread->setDone(); thread->setDone(); env->SetIntField(thiz, field_context, 0); sMutex.unlock(); } #endif #endif } } Loading media/mtp/MtpDatabase.h +7 −0 Original line number Original line Diff line number Diff line Loading @@ -61,7 +61,14 @@ public: virtual MtpResponseCode getObjectFilePath(MtpObjectHandle handle, virtual MtpResponseCode getObjectFilePath(MtpObjectHandle handle, MtpString& filePath, MtpString& filePath, int64_t& fileLength) = 0; int64_t& fileLength) = 0; virtual MtpResponseCode deleteFile(MtpObjectHandle handle) = 0; virtual MtpResponseCode deleteFile(MtpObjectHandle handle) = 0; virtual MtpObjectHandleList* getObjectReferences(MtpObjectHandle handle) = 0; virtual MtpResponseCode setObjectReferences(MtpObjectHandle handle, MtpObjectHandleList* references) = 0; }; }; }; // namespace android }; // namespace android Loading Loading
core/java/android/provider/MediaStore.java +7 −0 Original line number Original line Diff line number Diff line Loading @@ -273,6 +273,13 @@ public final class MediaStore { + "/object/" + objectId); + "/object/" + objectId); } } // used for MTP GetObjectReferences and SetObjectReferences public static final Uri getReferencesUri(String volumeName, long objectId) { return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName + "/object/" + objectId + "/references"); } /** /** * Fields for master table for all media files. * Fields for master table for all media files. * Table also contains MediaColumns._ID, DATA, SIZE and DATE_MODIFIED. * Table also contains MediaColumns._ID, DATA, SIZE and DATE_MODIFIED. Loading
media/java/android/media/MtpDatabase.java +77 −1 Original line number Original line Diff line number Diff line Loading @@ -22,7 +22,10 @@ import android.content.IContentProvider; import android.database.Cursor; import android.database.Cursor; import android.net.Uri; import android.net.Uri; import android.os.RemoteException; import android.os.RemoteException; import android.provider.MediaStore.Audio; import android.provider.MediaStore.MediaColumns; import android.provider.MediaStore.MtpObjects; import android.provider.MediaStore.MtpObjects; import android.provider.Mtp; import android.util.Log; import android.util.Log; /** /** Loading Loading @@ -120,7 +123,33 @@ public class MtpDatabase { private void endSendObject(String path, int handle, int format, boolean succeeded) { private void endSendObject(String path, int handle, int format, boolean succeeded) { if (succeeded) { if (succeeded) { // handle abstract playlists separately // they do not exist in the file system so don't use the media scanner here if (format == Mtp.Object.FORMAT_ABSTRACT_AV_PLAYLIST) { // Strip Windows Media Player file extension if (path.endsWith(".pla")) { path = path.substring(0, path.length() - 4); } // extract name from path String name = path; int lastSlash = name.lastIndexOf('/'); if (lastSlash >= 0) { name = name.substring(lastSlash + 1); } ContentValues values = new ContentValues(1); values.put(Audio.Playlists.DATA, path); values.put(Audio.Playlists.NAME, name); values.put(MediaColumns.MEDIA_SCANNER_NEW_OBJECT_ID, handle); try { Uri uri = mMediaProvider.insert(Audio.Playlists.EXTERNAL_CONTENT_URI, values); } catch (RemoteException e) { Log.e(TAG, "RemoteException in endSendObject", e); } } else { Uri uri = mMediaScanner.scanMtpFile(path, mVolumeName, handle, format); Uri uri = mMediaScanner.scanMtpFile(path, mVolumeName, handle, format); } } else { } else { deleteFile(handle); deleteFile(handle); } } Loading Loading @@ -338,6 +367,53 @@ public class MtpDatabase { } } } } private int[] getObjectReferences(int handle) { Log.d(TAG, "getObjectReferences for: " + handle); Uri uri = MtpObjects.getReferencesUri(mVolumeName, handle); Cursor c = null; try { c = mMediaProvider.query(uri, ID_PROJECTION, null, null, null); if (c == null) { return null; } int count = c.getCount(); if (count > 0) { int[] result = new int[count]; for (int i = 0; i < count; i++) { c.moveToNext(); result[i] = c.getInt(0); } return result; } } catch (RemoteException e) { Log.e(TAG, "RemoteException in getObjectList", e); } finally { if (c != null) { c.close(); } } return null; } private int setObjectReferences(int handle, int[] references) { Uri uri = MtpObjects.getReferencesUri(mVolumeName, handle); int count = references.length; ContentValues[] valuesList = new ContentValues[count]; for (int i = 0; i < count; i++) { ContentValues values = new ContentValues(); values.put(MtpObjects.ObjectColumns._ID, references[i]); valuesList[i] = values; } try { if (count == mMediaProvider.bulkInsert(uri, valuesList)) { return MTP_RESPONSE_OK; } } catch (RemoteException e) { Log.e(TAG, "RemoteException in setObjectReferences", e); } return MTP_RESPONSE_GENERAL_ERROR; } // used by the JNI code // used by the JNI code private int mNativeContext; private int mNativeContext; Loading
media/jni/android_media_MtpDatabase.cpp +48 −0 Original line number Original line Diff line number Diff line Loading @@ -44,6 +44,8 @@ static jmethodID method_getObjectProperty; static jmethodID method_getObjectInfo; static jmethodID method_getObjectInfo; static jmethodID method_getObjectFilePath; static jmethodID method_getObjectFilePath; static jmethodID method_deleteFile; static jmethodID method_deleteFile; static jmethodID method_getObjectReferences; static jmethodID method_setObjectReferences; static jfieldID field_context; static jfieldID field_context; MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database) { MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database) { Loading Loading @@ -98,6 +100,11 @@ public: virtual MtpResponseCode deleteFile(MtpObjectHandle handle); virtual MtpResponseCode deleteFile(MtpObjectHandle handle); bool getPropertyInfo(MtpObjectProperty property, int& type); bool getPropertyInfo(MtpObjectProperty property, int& type); virtual MtpObjectHandleList* getObjectReferences(MtpObjectHandle handle); virtual MtpResponseCode setObjectReferences(MtpObjectHandle handle, MtpObjectHandleList* references); }; }; MyMtpDatabase::MyMtpDatabase(JNIEnv *env, jobject client) MyMtpDatabase::MyMtpDatabase(JNIEnv *env, jobject client) Loading Loading @@ -344,6 +351,37 @@ bool MyMtpDatabase::getPropertyInfo(MtpObjectProperty property, int& type) { return false; return false; } } MtpObjectHandleList* MyMtpDatabase::getObjectReferences(MtpObjectHandle handle) { JNIEnv* env = AndroidRuntime::getJNIEnv(); jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectReferences, (jint)handle); if (!array) return NULL; MtpObjectHandleList* list = new MtpObjectHandleList(); jint* handles = env->GetIntArrayElements(array, 0); jsize length = env->GetArrayLength(array); for (int i = 0; i < length; i++) list->push(handles[i]); env->ReleaseIntArrayElements(array, handles, 0); return list; } MtpResponseCode MyMtpDatabase::setObjectReferences(MtpObjectHandle handle, MtpObjectHandleList* references) { JNIEnv* env = AndroidRuntime::getJNIEnv(); int count = references->size(); jintArray array = env->NewIntArray(count); if (!array) { LOGE("out of memory in setObjectReferences"); return false; } jint* handles = env->GetIntArrayElements(array, 0); for (int i = 0; i < count; i++) handles[i] = (*references)[i]; env->ReleaseIntArrayElements(array, handles, 0); return env->CallIntMethod(mDatabase, method_setObjectReferences, (jint)handle, array); } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) { static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) { Loading Loading @@ -442,6 +480,16 @@ int register_android_media_MtpDatabase(JNIEnv *env) LOGE("Can't find deleteFile"); LOGE("Can't find deleteFile"); return -1; return -1; } } method_getObjectReferences = env->GetMethodID(clazz, "getObjectReferences", "(I)[I"); if (method_getObjectReferences == NULL) { LOGE("Can't find getObjectReferences"); return -1; } method_setObjectReferences = env->GetMethodID(clazz, "setObjectReferences", "(I[I)I"); if (method_setObjectReferences == NULL) { LOGE("Can't find setObjectReferences"); return -1; } field_context = env->GetFieldID(clazz, "mNativeContext", "I"); field_context = env->GetFieldID(clazz, "mNativeContext", "I"); if (field_context == NULL) { if (field_context == NULL) { LOGE("Can't find MtpDatabase.mNativeContext"); LOGE("Can't find MtpDatabase.mNativeContext"); Loading
media/jni/android_media_MtpServer.cpp +56 −38 Original line number Original line Diff line number Diff line Loading @@ -36,6 +36,7 @@ using namespace android; // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- static jfieldID field_context; static jfieldID field_context; static Mutex sMutex; // in android_media_MtpDatabase.cpp // in android_media_MtpDatabase.cpp extern MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database); extern MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database); Loading @@ -55,61 +56,78 @@ private: MtpServer* mServer; MtpServer* mServer; String8 mStoragePath; String8 mStoragePath; bool mDone; bool mDone; Mutex mMutex; jobject mJavaServer; public: public: MtpThread(MtpDatabase* database, const char* storagePath) MtpThread(MtpDatabase* database, const char* storagePath, jobject javaServer) : mDatabase(database), mServer(NULL), mStoragePath(storagePath), mDone(false) : mDatabase(database), mServer(NULL), mStoragePath(storagePath), mDone(false), mJavaServer(javaServer) { { } } virtual bool threadLoop() { virtual bool threadLoop() { while (1) { int fd = open("/dev/mtp_usb", O_RDWR); int fd = open("/dev/mtp_usb", O_RDWR); printf("open returned %d\n", fd); printf("open returned %d\n", fd); if (fd < 0) { if (fd < 0) { LOGE("could not open MTP driver\n"); LOGE("could not open MTP driver\n"); return false; break; } } mMutex.lock(); sMutex.lock(); mServer = new MtpServer(fd, mDatabase, AID_SDCARD_RW, 0664, 0775); mServer = new MtpServer(fd, mDatabase, AID_SDCARD_RW, 0664, 0775); mServer->addStorage(mStoragePath); mServer->addStorage(mStoragePath); mMutex.unlock(); sMutex.unlock(); LOGD("MtpThread mServer->run"); LOGD("MtpThread mServer->run"); mServer->run(); mServer->run(); close(fd); close(fd); mMutex.lock(); sMutex.lock(); delete mServer; delete mServer; mServer = NULL; mServer = NULL; mMutex.unlock(); if (mDone) goto done; sMutex.unlock(); // wait a bit before retrying sleep(1); } bool done = mDone; sMutex.lock(); if (done) done: delete this; JNIEnv* env = AndroidRuntime::getJNIEnv(); LOGD("threadLoop returning %s", (done ? "false" : "true")); env->SetIntField(mJavaServer, field_context, 0); return !done; env->DeleteGlobalRef(mJavaServer); sMutex.unlock(); LOGD("threadLoop returning"); return false; } } void setDone() { mDone = true; } void setDone() { LOGD("setDone"); mDone = true; } void sendObjectAdded(MtpObjectHandle handle) { void sendObjectAdded(MtpObjectHandle handle) { mMutex.lock(); sMutex.lock(); if (mServer) if (mServer) mServer->sendObjectAdded(handle); mServer->sendObjectAdded(handle); else else LOGE("sendObjectAdded called while disconnected\n"); LOGE("sendObjectAdded called while disconnected\n"); mMutex.unlock(); sMutex.unlock(); } } void sendObjectRemoved(MtpObjectHandle handle) { void sendObjectRemoved(MtpObjectHandle handle) { mMutex.lock(); sMutex.lock(); if (mServer) if (mServer) mServer->sendObjectRemoved(handle); mServer->sendObjectRemoved(handle); else else LOGE("sendObjectRemoved called while disconnected\n"); LOGE("sendObjectRemoved called while disconnected\n"); mMutex.unlock(); sMutex.unlock(); } } }; }; Loading @@ -124,7 +142,7 @@ android_media_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase, j MtpDatabase* database = getMtpDatabase(env, javaDatabase); MtpDatabase* database = getMtpDatabase(env, javaDatabase); const char *storagePathStr = env->GetStringUTFChars(storagePath, NULL); const char *storagePathStr = env->GetStringUTFChars(storagePath, NULL); MtpThread* thread = new MtpThread(database, storagePathStr); MtpThread* thread = new MtpThread(database, storagePathStr, env->NewGlobalRef(thiz)); env->SetIntField(thiz, field_context, (int)thread); env->SetIntField(thiz, field_context, (int)thread); env->ReleaseStringUTFChars(storagePath, storagePathStr); env->ReleaseStringUTFChars(storagePath, storagePathStr); Loading Loading @@ -153,11 +171,11 @@ android_media_MtpServer_stop(JNIEnv *env, jobject thiz) { { #ifdef HAVE_ANDROID_OS #ifdef HAVE_ANDROID_OS LOGD("stop\n"); LOGD("stop\n"); sMutex.lock(); MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context); MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context); if (thread) { if (thread) thread->setDone(); thread->setDone(); env->SetIntField(thiz, field_context, 0); sMutex.unlock(); } #endif #endif } } Loading
media/mtp/MtpDatabase.h +7 −0 Original line number Original line Diff line number Diff line Loading @@ -61,7 +61,14 @@ public: virtual MtpResponseCode getObjectFilePath(MtpObjectHandle handle, virtual MtpResponseCode getObjectFilePath(MtpObjectHandle handle, MtpString& filePath, MtpString& filePath, int64_t& fileLength) = 0; int64_t& fileLength) = 0; virtual MtpResponseCode deleteFile(MtpObjectHandle handle) = 0; virtual MtpResponseCode deleteFile(MtpObjectHandle handle) = 0; virtual MtpObjectHandleList* getObjectReferences(MtpObjectHandle handle) = 0; virtual MtpResponseCode setObjectReferences(MtpObjectHandle handle, MtpObjectHandleList* references) = 0; }; }; }; // namespace android }; // namespace android Loading