summaryrefslogtreecommitdiffstats
path: root/media/mtp
diff options
context:
space:
mode:
Diffstat (limited to 'media/mtp')
-rw-r--r--media/mtp/MtpServer.cpp85
-rw-r--r--media/mtp/MtpServer.h7
-rw-r--r--media/mtp/MtpUtils.cpp38
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);
}