From a849440ca96e93f700d62c6e41d48905b4d405b6 Mon Sep 17 00:00:00 2001 From: Mike Lockwood Date: Fri, 18 Feb 2011 09:07:14 -0500 Subject: MTP: Add support for dynamically adding and removing storage units BUG: 3402847 Change-Id: I7da266061d949abcb6bb11c6faaa47b5e4a2a977 --- 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 ++ 5 files changed, 95 insertions(+), 25 deletions(-) (limited to 'media/mtp') diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp index 853a5af..37e02a3 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; @@ -439,6 +469,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; @@ -455,6 +488,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; @@ -471,7 +506,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); @@ -487,7 +524,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; @@ -495,6 +535,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, @@ -504,6 +546,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, @@ -537,6 +581,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 @@ -552,11 +598,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; @@ -592,6 +642,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); @@ -688,6 +740,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) { @@ -719,6 +772,8 @@ MtpResponseCode MtpServer::doSendObjectInfo() { } MtpResponseCode MtpServer::doSendObject() { + if (!hasStorage()) + return MTP_RESPONSE_GENERAL_ERROR; MtpResponseCode result = MTP_RESPONSE_OK; mode_t mask; int ret; @@ -835,6 +890,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 605d5a2..1efa715 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 2fbbc51..6cb88b3 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 ace720b..858c9d3 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 8bc2e22..6fedc16 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.1