Merge "Support transcode via MTP"
diff --git a/media/mtp/IMtpDatabase.h b/media/mtp/IMtpDatabase.h
index 81fa60c..3b9bbb0 100644
--- a/media/mtp/IMtpDatabase.h
+++ b/media/mtp/IMtpDatabase.h
@@ -39,7 +39,7 @@
     // Called to report success or failure of the SendObject file transfer.
     virtual void                    endSendObject(MtpObjectHandle handle,
                                             bool succeeded) = 0;
-    
+
     // Called to rescan a file, such as after an edit.
     virtual void                    rescanFile(const char* path,
                                             MtpObjectHandle handle,
@@ -91,6 +91,8 @@
                                             int64_t& outFileLength,
                                             MtpObjectFormat& outFormat) = 0;
 
+    virtual int                     openFilePath(const char* path, bool transcode) = 0;
+
     virtual MtpResponseCode         beginDeleteObject(MtpObjectHandle handle) = 0;
     virtual void                    endDeleteObject(MtpObjectHandle handle, bool succeeded) = 0;
 
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index 8677b90..d0ad22c 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -790,11 +790,34 @@
     auto start = std::chrono::steady_clock::now();
 
     const char* filePath = (const char *)pathBuf;
-    mtp_file_range  mfr;
-    mfr.fd = open(filePath, O_RDONLY);
-    if (mfr.fd < 0) {
-        return MTP_RESPONSE_GENERAL_ERROR;
+    mtp_file_range mfr;
+    struct stat sstat;
+    uint64_t finalsize;
+    bool transcode = android::base::GetBoolProperty("sys.fuse.transcode_mtp", true);
+    if (!transcode) {
+        ALOGD("Mtp transcode disabled");
+        mfr.fd = mDatabase->openFilePath(filePath, false);
+        // Doing this here because we want to update fileLength only for this case and leave the
+        // regular path as unchanged as possible.
+        if (mfr.fd >= 0) {
+            fstat(mfr.fd, &sstat);
+            finalsize = sstat.st_size;
+            fileLength = finalsize;
+        } else {
+            ALOGW("Mtp open with no transcoding failed for %s. Falling back to the original",
+                    filePath);
+        }
     }
+
+    if (transcode || mfr.fd < 0) {
+        mfr.fd = open(filePath, O_RDONLY);
+        if (mfr.fd < 0) {
+            return MTP_RESPONSE_GENERAL_ERROR;
+        }
+        fstat(mfr.fd, &sstat);
+        finalsize = sstat.st_size;
+    }
+
     mfr.offset = 0;
     mfr.length = fileLength;
     mfr.command = mRequest.getOperationCode();
@@ -815,9 +838,6 @@
 
     auto end = std::chrono::steady_clock::now();
     std::chrono::duration<double> diff = end - start;
-    struct stat sstat;
-    fstat(mfr.fd, &sstat);
-    uint64_t finalsize = sstat.st_size;
     ALOGV("Sent a file over MTP. Time: %f s, Size: %" PRIu64 ", Rate: %f bytes/s",
             diff.count(), finalsize, ((double) finalsize) / diff.count());
     closeObjFd(mfr.fd, filePath);
diff --git a/media/mtp/tests/MtpFuzzer/MtpMockDatabase.cpp b/media/mtp/tests/MtpFuzzer/MtpMockDatabase.cpp
index 5d95aa2..8aafe33 100644
--- a/media/mtp/tests/MtpFuzzer/MtpMockDatabase.cpp
+++ b/media/mtp/tests/MtpFuzzer/MtpMockDatabase.cpp
@@ -252,6 +252,11 @@
     return MTP_RESPONSE_OK;
 }
 
+int MtpMockDatabase::openFilePath(const char* path, bool transcode) {
+    ALOGD("MockDatabase %s: filePath=%s transcode=%d\n", __func__, path, transcode);
+    return 0;
+}
+
 MtpResponseCode MtpMockDatabase::beginDeleteObject(MtpObjectHandle handle) {
     ALOGD("MockDatabase %s: ohandle=%u\n", __func__, handle);
     return MTP_RESPONSE_OK;
diff --git a/media/mtp/tests/MtpFuzzer/MtpMockDatabase.h b/media/mtp/tests/MtpFuzzer/MtpMockDatabase.h
index 876719e..e9e6a64 100644
--- a/media/mtp/tests/MtpFuzzer/MtpMockDatabase.h
+++ b/media/mtp/tests/MtpFuzzer/MtpMockDatabase.h
@@ -90,6 +90,8 @@
     MtpResponseCode getObjectFilePath(MtpObjectHandle handle, MtpStringBuffer& outFilePath,
                                       int64_t& outFileLength, MtpObjectFormat& outFormat);
 
+    int openFilePath(const char* path, bool transcode);
+
     MtpResponseCode beginDeleteObject(MtpObjectHandle handle);
     void endDeleteObject(MtpObjectHandle handle, bool succeeded);