diff options
Diffstat (limited to 'media/mtp')
-rw-r--r-- | media/mtp/MtpServer.cpp | 85 | ||||
-rw-r--r-- | media/mtp/MtpServer.h | 7 | ||||
-rw-r--r-- | media/mtp/MtpUtils.cpp | 38 |
3 files changed, 80 insertions, 50 deletions
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp index 07199e3..d5f8ff4 100644 --- a/media/mtp/MtpServer.cpp +++ b/media/mtp/MtpServer.cpp @@ -95,6 +95,7 @@ static const MtpEventCode kSupportedEventCodes[] = { MTP_EVENT_STORE_ADDED, MTP_EVENT_STORE_REMOVED, MTP_EVENT_DEVICE_PROP_CHANGED, + MTP_EVENT_OBJECT_PROP_CHANGED, }; MtpServer::MtpServer(int fd, MtpDatabase* database, bool ptp, @@ -136,20 +137,9 @@ void MtpServer::removeStorage(MtpStorage* storage) { } MtpStorage* MtpServer::getStorage(MtpStorageID id) { - if (id == 0) - return mStorages[0]; - for (size_t i = 0; i < mStorages.size(); i++) { - MtpStorage* storage = mStorages[i]; - if (storage->getStorageID() == id) - return storage; - } - return NULL; -} + Mutex::Autolock autoLock(mMutex); -bool MtpServer::hasStorage(MtpStorageID id) { - if (id == 0 || id == 0xFFFFFFFF) - return mStorages.size() > 0; - return (getStorage(id) != NULL); + return getStorageLocked(id); } void MtpServer::run() { @@ -214,10 +204,11 @@ void MtpServer::run() { mResponse.setTransactionID(transaction); ALOGV("sending response %04X", mResponse.getResponseCode()); ret = mResponse.write(fd); + const int savedErrno = errno; mResponse.dump(); if (ret < 0) { ALOGE("request write returned %d, errno: %d", ret, errno); - if (errno == ECANCELED) { + if (savedErrno == ECANCELED) { // return to top of loop and wait for next command continue; } @@ -253,6 +244,28 @@ void MtpServer::sendObjectRemoved(MtpObjectHandle handle) { sendEvent(MTP_EVENT_OBJECT_REMOVED, handle); } +void MtpServer::sendObjectUpdated(MtpObjectHandle handle) { + ALOGV("sendObjectUpdated %d\n", handle); + sendEvent(MTP_EVENT_OBJECT_PROP_CHANGED, handle); +} + +MtpStorage* MtpServer::getStorageLocked(MtpStorageID id) { + if (id == 0) + return mStorages.empty() ? NULL : mStorages[0]; + for (size_t i = 0; i < mStorages.size(); i++) { + MtpStorage* storage = mStorages[i]; + if (storage->getStorageID() == id) + return storage; + } + return NULL; +} + +bool MtpServer::hasStorage(MtpStorageID id) { + if (id == 0 || id == 0xFFFFFFFF) + return mStorages.size() > 0; + return (getStorageLocked(id) != NULL); +} + void MtpServer::sendStoreAdded(MtpStorageID id) { ALOGV("sendStoreAdded %08X\n", id); sendEvent(MTP_EVENT_STORE_ADDED, id); @@ -536,7 +549,7 @@ MtpResponseCode MtpServer::doGetStorageInfo() { return MTP_RESPONSE_INVALID_PARAMETER; MtpStorageID id = mRequest.getParameter(1); - MtpStorage* storage = getStorage(id); + MtpStorage* storage = getStorageLocked(id); if (!storage) return MTP_RESPONSE_INVALID_STORAGE_ID; @@ -787,15 +800,19 @@ MtpResponseCode MtpServer::doGetObject() { // then transfer the file int ret = ioctl(mFD, MTP_SEND_FILE_WITH_HEADER, (unsigned long)&mfr); - ALOGV("MTP_SEND_FILE_WITH_HEADER returned %d\n", ret); - close(mfr.fd); if (ret < 0) { - if (errno == ECANCELED) - return MTP_RESPONSE_TRANSACTION_CANCELLED; - else - return MTP_RESPONSE_GENERAL_ERROR; + if (errno == ECANCELED) { + result = MTP_RESPONSE_TRANSACTION_CANCELLED; + } else { + result = MTP_RESPONSE_GENERAL_ERROR; + } + } else { + result = MTP_RESPONSE_OK; } - return MTP_RESPONSE_OK; + + ALOGV("MTP_SEND_FILE_WITH_HEADER returned %d\n", ret); + close(mfr.fd); + return result; } MtpResponseCode MtpServer::doGetThumb() { @@ -864,14 +881,15 @@ MtpResponseCode MtpServer::doGetPartialObject(MtpOperationCode operation) { // transfer the file int ret = ioctl(mFD, MTP_SEND_FILE_WITH_HEADER, (unsigned long)&mfr); ALOGV("MTP_SEND_FILE_WITH_HEADER returned %d\n", ret); - close(mfr.fd); + result = MTP_RESPONSE_OK; if (ret < 0) { if (errno == ECANCELED) - return MTP_RESPONSE_TRANSACTION_CANCELLED; + result = MTP_RESPONSE_TRANSACTION_CANCELLED; else - return MTP_RESPONSE_GENERAL_ERROR; + result = MTP_RESPONSE_GENERAL_ERROR; } - return MTP_RESPONSE_OK; + close(mfr.fd); + return result; } MtpResponseCode MtpServer::doSendObjectInfo() { @@ -882,7 +900,7 @@ MtpResponseCode MtpServer::doSendObjectInfo() { if (mRequest.getParameterCount() < 2) return MTP_RESPONSE_INVALID_PARAMETER; MtpStorageID storageID = mRequest.getParameter(1); - MtpStorage* storage = getStorage(storageID); + MtpStorage* storage = getStorageLocked(storageID); MtpObjectHandle parent = mRequest.getParameter(2); if (!storage) return MTP_RESPONSE_INVALID_STORAGE_ID; @@ -985,6 +1003,7 @@ MtpResponseCode MtpServer::doSendObject() { MtpResponseCode result = MTP_RESPONSE_OK; mode_t mask; int ret, initialData; + bool isCanceled = false; if (mSendObjectHandle == kInvalidObjectHandle) { ALOGE("Expected SendObjectInfo before SendObject"); @@ -1032,6 +1051,10 @@ MtpResponseCode MtpServer::doSendObject() { ALOGV("receiving %s\n", (const char *)mSendObjectFilePath); // transfer the file ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr); + if ((ret < 0) && (errno == ECANCELED)) { + isCanceled = true; + } + ALOGV("MTP_RECEIVE_FILE returned %d\n", ret); } } @@ -1039,7 +1062,7 @@ MtpResponseCode MtpServer::doSendObject() { if (ret < 0) { unlink(mSendObjectFilePath); - if (errno == ECANCELED) + if (isCanceled) result = MTP_RESPONSE_TRANSACTION_CANCELLED; else result = MTP_RESPONSE_GENERAL_ERROR; @@ -1208,6 +1231,7 @@ MtpResponseCode MtpServer::doSendPartialObject() { length -= initialData; } + bool isCanceled = false; if (ret < 0) { ALOGE("failed to write initial data"); } else { @@ -1219,12 +1243,15 @@ MtpResponseCode MtpServer::doSendPartialObject() { // transfer the file ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr); + if ((ret < 0) && (errno == ECANCELED)) { + isCanceled = true; + } ALOGV("MTP_RECEIVE_FILE returned %d", ret); } } if (ret < 0) { mResponse.setParameter(1, 0); - if (errno == ECANCELED) + if (isCanceled) return MTP_RESPONSE_TRANSACTION_CANCELLED; else return MTP_RESPONSE_GENERAL_ERROR; diff --git a/media/mtp/MtpServer.h b/media/mtp/MtpServer.h index b3a11e0..a79e199 100644 --- a/media/mtp/MtpServer.h +++ b/media/mtp/MtpServer.h @@ -95,8 +95,6 @@ public: virtual ~MtpServer(); MtpStorage* getStorage(MtpStorageID id); - inline bool hasStorage() { return mStorages.size() > 0; } - bool hasStorage(MtpStorageID id); void addStorage(MtpStorage* storage); void removeStorage(MtpStorage* storage); @@ -105,8 +103,13 @@ public: void sendObjectAdded(MtpObjectHandle handle); void sendObjectRemoved(MtpObjectHandle handle); void sendDevicePropertyChanged(MtpDeviceProperty property); + void sendObjectUpdated(MtpObjectHandle handle); private: + MtpStorage* getStorageLocked(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); diff --git a/media/mtp/MtpUtils.cpp b/media/mtp/MtpUtils.cpp index 0667bdd..ebf3601 100644 --- a/media/mtp/MtpUtils.cpp +++ b/media/mtp/MtpUtils.cpp @@ -19,8 +19,6 @@ #include <stdio.h> #include <time.h> -#include <../private/bionic_time.h> /* TODO: switch this code to icu4c! */ - #include "MtpUtils.h" namespace android { @@ -32,38 +30,40 @@ representation, YYYY shall be replaced by the year, MM replaced by the month (01 DD replaced by the day (01-31), T is a constant character 'T' delimiting time from date, hh is replaced by the hour (00-23), mm is replaced by the minute (00-59), and ss by the second (00-59). The ".s" is optional, and represents tenths of a second. +This is followed by a UTC offset given as "[+-]zzzz" or the literal "Z", meaning UTC. */ bool parseDateTime(const char* dateTime, time_t& outSeconds) { int year, month, day, hour, minute, second; - struct tm tm; - if (sscanf(dateTime, "%04d%02d%02dT%02d%02d%02d", - &year, &month, &day, &hour, &minute, &second) != 6) + &year, &month, &day, &hour, &minute, &second) != 6) return false; - const char* tail = dateTime + 15; + // skip optional tenth of second - if (tail[0] == '.' && tail[1]) - tail += 2; - //FIXME - support +/-hhmm - bool useUTC = (tail[0] == 'Z'); + const char* tail = dateTime + 15; + if (tail[0] == '.' && tail[1]) tail += 2; - // hack to compute timezone - time_t dummy; - localtime_r(&dummy, &tm); + // FIXME: "Z" means UTC, but non-"Z" doesn't mean local time. + // It might be that you're in Asia/Seoul on vacation and your Android + // device has noticed this via the network, but your camera was set to + // America/Los_Angeles once when you bought it and doesn't know where + // it is right now, so the camera says "20160106T081700-0800" but we + // just ignore the "-0800" and assume local time which is actually "+0900". + // I think to support this (without switching to Java or using icu4c) + // you'd want to always use timegm(3) and then manually add/subtract + // the UTC offset parsed from the string (taking care of wrapping). + // mktime(3) ignores the tm_gmtoff field, so you can't let it do the work. + bool useUTC = (tail[0] == 'Z'); + struct tm tm = {}; tm.tm_sec = second; tm.tm_min = minute; tm.tm_hour = hour; tm.tm_mday = day; tm.tm_mon = month - 1; // mktime uses months in 0 - 11 range tm.tm_year = year - 1900; - tm.tm_wday = 0; tm.tm_isdst = -1; - if (useUTC) - outSeconds = mktime(&tm); - else - outSeconds = mktime_tz(&tm, tm.tm_zone); + outSeconds = useUTC ? timegm(&tm) : mktime(&tm); return true; } @@ -73,7 +73,7 @@ void formatDateTime(time_t seconds, char* buffer, int bufferLength) { localtime_r(&seconds, &tm); snprintf(buffer, bufferLength, "%04d%02d%02dT%02d%02d%02d", - tm.tm_year + 1900, + tm.tm_year + 1900, tm.tm_mon + 1, // localtime_r uses months in 0 - 11 range tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); } |