From 0600fff9149df3af01e90d4996b70dbc1ee7c135 Mon Sep 17 00:00:00 2001 From: Mike Lockwood Date: Fri, 18 Feb 2011 09:07:14 -0500 Subject: DO NOT MERGE: MTP: Add support for dynamically adding and removing storage units BUG: 3402847 Change-Id: I46e90f546a8d72c273cd7f2de2d086bb6dbdc1b8 Signed-off-by: Mike Lockwood --- media/jni/android_mtp_MtpServer.cpp | 18 +++++--- media/mtp/MtpServer.cpp | 91 ++++++++++++++++++++++++++++++------- media/mtp/MtpServer.h | 18 ++++++-- media/mtp/MtpStorage.cpp | 4 +- media/mtp/MtpStorage.h | 5 +- media/mtp/mtp.h | 2 + 6 files changed, 106 insertions(+), 32 deletions(-) diff --git a/media/jni/android_mtp_MtpServer.cpp b/media/jni/android_mtp_MtpServer.cpp index 3883fb2dcd7a..b27441fb681c 100644 --- a/media/jni/android_mtp_MtpServer.cpp +++ b/media/jni/android_mtp_MtpServer.cpp @@ -35,6 +35,7 @@ #include "private/android_filesystem_config.h" #include "MtpServer.h" +#include "MtpStorage.h" using namespace android; @@ -56,22 +57,24 @@ class MtpThread : public Thread { private: MtpDatabase* mDatabase; MtpServer* mServer; - String8 mStoragePath; - uint64_t mReserveSpace; + MtpStorage* mStorage; Mutex mMutex; bool mUsePtp; int mFd; public: - MtpThread(MtpDatabase* database, const char* storagePath, uint64_t reserveSpace) + MtpThread(MtpDatabase* database, MtpStorage* storage) : mDatabase(database), mServer(NULL), - mStoragePath(storagePath), - mReserveSpace(reserveSpace), + mStorage(storage), mFd(-1) { } + virtual ~MtpThread() { + delete mStorage; + } + void setPtpMode(bool usePtp) { mMutex.lock(); mUsePtp = usePtp; @@ -86,7 +89,7 @@ public: (mUsePtp ? MTP_INTERFACE_MODE_PTP : MTP_INTERFACE_MODE_MTP)); mServer = new MtpServer(mFd, mDatabase, AID_MEDIA_RW, 0664, 0775); - mServer->addStorage(mStoragePath, mReserveSpace); + mServer->addStorage(mStorage); mMutex.unlock(); mServer->run(); @@ -137,7 +140,8 @@ android_mtp_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase, const char *storagePathStr = env->GetStringUTFChars(storagePath, NULL); // create the thread and assign it to the smart pointer - sThread = new MtpThread(database, storagePathStr, reserveSpace); + MtpStorage* storage = new MtpStorage(MTP_FIRST_STORAGE_ID, storagePathStr, reserveSpace); + sThread = new MtpThread(database, storage); env->ReleaseStringUTFChars(storagePath, storagePathStr); #endif diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp index be004d2dd786..469fb0470b4c 100644 --- a/media/mtp/MtpServer.cpp +++ b/media/mtp/MtpServer.cpp @@ -84,6 +84,8 @@ static const MtpOperationCode kSupportedOperationCodes[] = { static const MtpEventCode kSupportedEventCodes[] = { MTP_EVENT_OBJECT_ADDED, MTP_EVENT_OBJECT_REMOVED, + MTP_EVENT_STORE_ADDED, + MTP_EVENT_STORE_REMOVED, }; MtpServer::MtpServer(int fd, MtpDatabase* database, @@ -104,11 +106,23 @@ MtpServer::MtpServer(int fd, MtpDatabase* database, MtpServer::~MtpServer() { } -void MtpServer::addStorage(const char* filePath, uint64_t reserveSpace) { - int index = mStorages.size() + 1; - index |= index << 16; // set high and low part to our index - MtpStorage* storage = new MtpStorage(index, filePath, reserveSpace); - addStorage(storage); +void MtpServer::addStorage(MtpStorage* storage) { + Mutex::Autolock autoLock(mMutex); + + mStorages.push(storage); + sendStoreAdded(storage->getStorageID()); +} + +void MtpServer::removeStorage(MtpStorage* storage) { + Mutex::Autolock autoLock(mMutex); + + for (int i = 0; i < mStorages.size(); i++) { + if (mStorages[i] == storage) { + mStorages.removeAt(i); + sendStoreRemoved(storage->getStorageID()); + break; + } + } } MtpStorage* MtpServer::getStorage(MtpStorageID id) { @@ -122,6 +136,12 @@ MtpStorage* MtpServer::getStorage(MtpStorageID id) { return NULL; } +bool MtpServer::hasStorage(MtpStorageID id) { + if (id == 0 || id == 0xFFFFFFFF) + return mStorages.size() > 0; + return (getStorage(id) != NULL); +} + void MtpServer::run() { int fd = mFD; @@ -203,28 +223,38 @@ void MtpServer::run() { } void MtpServer::sendObjectAdded(MtpObjectHandle handle) { - if (mSessionOpen) { - LOGV("sendObjectAdded %d\n", handle); - mEvent.setEventCode(MTP_EVENT_OBJECT_ADDED); - mEvent.setTransactionID(mRequest.getTransactionID()); - mEvent.setParameter(1, handle); - int ret = mEvent.write(mFD); - LOGV("mEvent.write returned %d\n", ret); - } + LOGV("sendObjectAdded %d\n", handle); + sendEvent(MTP_EVENT_OBJECT_ADDED, handle); } void MtpServer::sendObjectRemoved(MtpObjectHandle handle) { + LOGV("sendObjectRemoved %d\n", handle); + sendEvent(MTP_EVENT_OBJECT_REMOVED, handle); +} + +void MtpServer::sendStoreAdded(MtpStorageID id) { + LOGV("sendStoreAdded %08X\n", id); + sendEvent(MTP_EVENT_STORE_ADDED, id); +} + +void MtpServer::sendStoreRemoved(MtpStorageID id) { + LOGV("sendStoreRemoved %08X\n", id); + sendEvent(MTP_EVENT_STORE_REMOVED, id); +} + +void MtpServer::sendEvent(MtpEventCode code, uint32_t param1) { if (mSessionOpen) { - LOGV("sendObjectRemoved %d\n", handle); - mEvent.setEventCode(MTP_EVENT_OBJECT_REMOVED); + mEvent.setEventCode(code); mEvent.setTransactionID(mRequest.getTransactionID()); - mEvent.setParameter(1, handle); + mEvent.setParameter(1, param1); int ret = mEvent.write(mFD); LOGV("mEvent.write returned %d\n", ret); } } bool MtpServer::handleRequest() { + Mutex::Autolock autoLock(mMutex); + MtpOperationCode operation = mRequest.getOperationCode(); MtpResponseCode response; @@ -438,6 +468,9 @@ MtpResponseCode MtpServer::doGetObjectHandles() { MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent // 0x00000000 for all objects? + + if (!hasStorage(storageID)) + return MTP_RESPONSE_INVALID_STORAGE_ID; if (parent == 0xFFFFFFFF) parent = 0; @@ -454,6 +487,8 @@ MtpResponseCode MtpServer::doGetNumObjects() { MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent // 0x00000000 for all objects? + if (!hasStorage(storageID)) + return MTP_RESPONSE_INVALID_STORAGE_ID; if (parent == 0xFFFFFFFF) parent = 0; @@ -470,7 +505,9 @@ MtpResponseCode MtpServer::doGetNumObjects() { MtpResponseCode MtpServer::doGetObjectReferences() { if (!mSessionOpen) return MTP_RESPONSE_SESSION_NOT_OPEN; - MtpStorageID handle = mRequest.getParameter(1); + if (!hasStorage()) + return MTP_RESPONSE_INVALID_OBJECT_HANDLE; + MtpObjectHandle handle = mRequest.getParameter(1); // FIXME - check for invalid object handle MtpObjectHandleList* handles = mDatabase->getObjectReferences(handle); @@ -486,7 +523,10 @@ MtpResponseCode MtpServer::doGetObjectReferences() { MtpResponseCode MtpServer::doSetObjectReferences() { if (!mSessionOpen) return MTP_RESPONSE_SESSION_NOT_OPEN; + if (!hasStorage()) + return MTP_RESPONSE_INVALID_OBJECT_HANDLE; MtpStorageID handle = mRequest.getParameter(1); + MtpObjectHandleList* references = mData.getAUInt32(); MtpResponseCode result = mDatabase->setObjectReferences(handle, references); delete references; @@ -494,6 +534,8 @@ MtpResponseCode MtpServer::doSetObjectReferences() { } MtpResponseCode MtpServer::doGetObjectPropValue() { + if (!hasStorage()) + return MTP_RESPONSE_INVALID_OBJECT_HANDLE; MtpObjectHandle handle = mRequest.getParameter(1); MtpObjectProperty property = mRequest.getParameter(2); LOGV("GetObjectPropValue %d %s\n", handle, @@ -503,6 +545,8 @@ MtpResponseCode MtpServer::doGetObjectPropValue() { } MtpResponseCode MtpServer::doSetObjectPropValue() { + if (!hasStorage()) + return MTP_RESPONSE_INVALID_OBJECT_HANDLE; MtpObjectHandle handle = mRequest.getParameter(1); MtpObjectProperty property = mRequest.getParameter(2); LOGV("SetObjectPropValue %d %s\n", handle, @@ -536,6 +580,8 @@ MtpResponseCode MtpServer::doResetDevicePropValue() { } MtpResponseCode MtpServer::doGetObjectPropList() { + if (!hasStorage()) + return MTP_RESPONSE_INVALID_OBJECT_HANDLE; MtpObjectHandle handle = mRequest.getParameter(1); // use uint32_t so we can support 0xFFFFFFFF @@ -551,11 +597,15 @@ MtpResponseCode MtpServer::doGetObjectPropList() { } MtpResponseCode MtpServer::doGetObjectInfo() { + if (!hasStorage()) + return MTP_RESPONSE_INVALID_OBJECT_HANDLE; MtpObjectHandle handle = mRequest.getParameter(1); return mDatabase->getObjectInfo(handle, mData); } MtpResponseCode MtpServer::doGetObject() { + if (!hasStorage()) + return MTP_RESPONSE_INVALID_OBJECT_HANDLE; MtpObjectHandle handle = mRequest.getParameter(1); MtpString pathBuf; int64_t fileLength; @@ -591,6 +641,8 @@ MtpResponseCode MtpServer::doGetObject() { } MtpResponseCode MtpServer::doGetPartialObject() { + if (!hasStorage()) + return MTP_RESPONSE_INVALID_OBJECT_HANDLE; MtpObjectHandle handle = mRequest.getParameter(1); uint32_t offset = mRequest.getParameter(2); uint32_t length = mRequest.getParameter(3); @@ -687,6 +739,7 @@ MtpResponseCode MtpServer::doSendObjectInfo() { if (mSendObjectFileSize > storage->getFreeSpace()) return MTP_RESPONSE_STORAGE_FULL; +LOGD("path: %s parent: %d storageID: %08X", (const char*)path, parent, storageID); MtpObjectHandle handle = mDatabase->beginSendObject((const char*)path, format, parent, storageID, mSendObjectFileSize, modifiedTime); if (handle == kInvalidObjectHandle) { @@ -718,6 +771,8 @@ MtpResponseCode MtpServer::doSendObjectInfo() { } MtpResponseCode MtpServer::doSendObject() { + if (!hasStorage()) + return MTP_RESPONSE_GENERAL_ERROR; MtpResponseCode result = MTP_RESPONSE_OK; mode_t mask; int ret; @@ -834,6 +889,8 @@ static void deletePath(const char* path) { } MtpResponseCode MtpServer::doDeleteObject() { + if (!hasStorage()) + return MTP_RESPONSE_INVALID_OBJECT_HANDLE; MtpObjectHandle handle = mRequest.getParameter(1); MtpObjectFormat format = mRequest.getParameter(2); // FIXME - support deleting all objects if handle is 0xFFFFFFFF diff --git a/media/mtp/MtpServer.h b/media/mtp/MtpServer.h index 605d5a2e0d4d..1efa7158baa6 100644 --- a/media/mtp/MtpServer.h +++ b/media/mtp/MtpServer.h @@ -22,9 +22,10 @@ #include "MtpResponsePacket.h" #include "MtpEventPacket.h" #include "mtp.h" - #include "MtpUtils.h" +#include + namespace android { class MtpDatabase; @@ -62,20 +63,29 @@ private: MtpString mSendObjectFilePath; size_t mSendObjectFileSize; + Mutex mMutex; + public: MtpServer(int fd, MtpDatabase* database, int fileGroup, int filePerm, int directoryPerm); virtual ~MtpServer(); - void addStorage(const char* filePath, uint64_t reserveSpace); - inline void addStorage(MtpStorage* storage) { mStorages.push(storage); } - MtpStorage* getStorage(MtpStorageID id); + void addStorage(MtpStorage* storage); + void removeStorage(MtpStorage* storage); + void run(); void sendObjectAdded(MtpObjectHandle handle); void sendObjectRemoved(MtpObjectHandle handle); private: + MtpStorage* getStorage(MtpStorageID id); + inline bool hasStorage() { return mStorages.size() > 0; } + bool hasStorage(MtpStorageID id); + void sendStoreAdded(MtpStorageID id); + void sendStoreRemoved(MtpStorageID id); + void sendEvent(MtpEventCode code, uint32_t param1); + bool handleRequest(); MtpResponseCode doGetDeviceInfo(); diff --git a/media/mtp/MtpStorage.cpp b/media/mtp/MtpStorage.cpp index 2fbbc512d1e2..6cb88b33551f 100644 --- a/media/mtp/MtpStorage.cpp +++ b/media/mtp/MtpStorage.cpp @@ -59,7 +59,7 @@ int MtpStorage::getAccessCapability() const { uint64_t MtpStorage::getMaxCapacity() { if (mMaxCapacity == 0) { struct statfs stat; - if (statfs(mFilePath, &stat)) + if (statfs(getPath(), &stat)) return -1; mMaxCapacity = (uint64_t)stat.f_blocks * (uint64_t)stat.f_bsize; } @@ -68,7 +68,7 @@ uint64_t MtpStorage::getMaxCapacity() { uint64_t MtpStorage::getFreeSpace() { struct statfs stat; - if (statfs(mFilePath, &stat)) + if (statfs(getPath(), &stat)) return -1; uint64_t freeSpace = (uint64_t)stat.f_bavail * (uint64_t)stat.f_bsize; return (freeSpace > mReserveSpace ? freeSpace - mReserveSpace : 0); diff --git a/media/mtp/MtpStorage.h b/media/mtp/MtpStorage.h index ace720b9f511..858c9d38a3f6 100644 --- a/media/mtp/MtpStorage.h +++ b/media/mtp/MtpStorage.h @@ -17,6 +17,7 @@ #ifndef _MTP_STORAGE_H #define _MTP_STORAGE_H +#include "MtpTypes.h" #include "mtp.h" namespace android { @@ -27,7 +28,7 @@ class MtpStorage { private: MtpStorageID mStorageID; - const char* mFilePath; + MtpString mFilePath; uint64_t mMaxCapacity; // amount of free space to leave unallocated uint64_t mReserveSpace; @@ -44,7 +45,7 @@ public: uint64_t getMaxCapacity(); uint64_t getFreeSpace(); const char* getDescription() const; - inline const char* getPath() const { return mFilePath; } + inline const char* getPath() const { return (const char *)mFilePath; } }; }; // namespace android diff --git a/media/mtp/mtp.h b/media/mtp/mtp.h index 8bc2e22c31d8..6fedc161b9c1 100644 --- a/media/mtp/mtp.h +++ b/media/mtp/mtp.h @@ -22,6 +22,8 @@ #define MTP_STANDARD_VERSION 100 +#define MTP_FIRST_STORAGE_ID 0x00010001 + // Container Types #define MTP_CONTAINER_TYPE_UNDEFINED 0 #define MTP_CONTAINER_TYPE_COMMAND 1 -- cgit v1.2.3-59-g8ed1b