MtpDatabase: Use actual file size instead of media database size column
Fixes problems with file transfer from device to host that can occur if the database size value is wrong. Bug: 6954446 Change-Id: I03c3dd4b75267d1f4613f0b588c8899ded9a70be Signed-off-by: Mike Lockwood <lockwood@google.com>
This commit is contained in:
@@ -84,11 +84,10 @@ public class MtpDatabase {
|
||||
Files.FileColumns._ID, // 0
|
||||
Files.FileColumns.DATA, // 1
|
||||
};
|
||||
private static final String[] PATH_SIZE_FORMAT_PROJECTION = new String[] {
|
||||
private static final String[] PATH_FORMAT_PROJECTION = new String[] {
|
||||
Files.FileColumns._ID, // 0
|
||||
Files.FileColumns.DATA, // 1
|
||||
Files.FileColumns.SIZE, // 2
|
||||
Files.FileColumns.FORMAT, // 3
|
||||
Files.FileColumns.FORMAT, // 2
|
||||
};
|
||||
private static final String[] OBJECT_INFO_PROJECTION = new String[] {
|
||||
Files.FileColumns._ID, // 0
|
||||
@@ -96,8 +95,7 @@ public class MtpDatabase {
|
||||
Files.FileColumns.FORMAT, // 2
|
||||
Files.FileColumns.PARENT, // 3
|
||||
Files.FileColumns.DATA, // 4
|
||||
Files.FileColumns.SIZE, // 5
|
||||
Files.FileColumns.DATE_MODIFIED, // 6
|
||||
Files.FileColumns.DATE_MODIFIED, // 5
|
||||
};
|
||||
private static final String ID_WHERE = Files.FileColumns._ID + "=?";
|
||||
private static final String PATH_WHERE = Files.FileColumns.DATA + "=?";
|
||||
@@ -834,7 +832,7 @@ public class MtpDatabase {
|
||||
}
|
||||
|
||||
private boolean getObjectInfo(int handle, int[] outStorageFormatParent,
|
||||
char[] outName, long[] outSizeModified) {
|
||||
char[] outName, long[] outModified) {
|
||||
Cursor c = null;
|
||||
try {
|
||||
c = mMediaProvider.query(mObjectsUri, OBJECT_INFO_PROJECTION,
|
||||
@@ -855,8 +853,7 @@ public class MtpDatabase {
|
||||
path.getChars(start, end, outName, 0);
|
||||
outName[end - start] = 0;
|
||||
|
||||
outSizeModified[0] = c.getLong(5);
|
||||
outSizeModified[1] = c.getLong(6);
|
||||
outModified[0] = c.getLong(5);
|
||||
return true;
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
@@ -880,14 +877,16 @@ public class MtpDatabase {
|
||||
}
|
||||
Cursor c = null;
|
||||
try {
|
||||
c = mMediaProvider.query(mObjectsUri, PATH_SIZE_FORMAT_PROJECTION,
|
||||
c = mMediaProvider.query(mObjectsUri, PATH_FORMAT_PROJECTION,
|
||||
ID_WHERE, new String[] { Integer.toString(handle) }, null, null);
|
||||
if (c != null && c.moveToNext()) {
|
||||
String path = c.getString(1);
|
||||
path.getChars(0, path.length(), outFilePath, 0);
|
||||
outFilePath[path.length()] = 0;
|
||||
outFileLengthFormat[0] = c.getLong(2);
|
||||
outFileLengthFormat[1] = c.getLong(3);
|
||||
// File transfers from device to host will likely fail if the size is incorrect.
|
||||
// So to be safe, use the actual file size here.
|
||||
outFileLengthFormat[0] = new File(path).length();
|
||||
outFileLengthFormat[1] = c.getLong(2);
|
||||
return MtpConstants.RESPONSE_OK;
|
||||
} else {
|
||||
return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
|
||||
@@ -909,13 +908,13 @@ public class MtpDatabase {
|
||||
|
||||
Cursor c = null;
|
||||
try {
|
||||
c = mMediaProvider.query(mObjectsUri, PATH_SIZE_FORMAT_PROJECTION,
|
||||
c = mMediaProvider.query(mObjectsUri, PATH_FORMAT_PROJECTION,
|
||||
ID_WHERE, new String[] { Integer.toString(handle) }, null, null);
|
||||
if (c != null && c.moveToNext()) {
|
||||
// don't convert to media path here, since we will be matching
|
||||
// against paths in the database matching /data/media
|
||||
path = c.getString(1);
|
||||
format = c.getInt(3);
|
||||
format = c.getInt(2);
|
||||
} else {
|
||||
return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
|
||||
}
|
||||
|
||||
@@ -751,13 +751,22 @@ MtpResponseCode MyMtpDatabase::getObjectPropertyList(MtpObjectHandle handle,
|
||||
|
||||
MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
|
||||
MtpObjectInfo& info) {
|
||||
char date[20];
|
||||
char date[20];
|
||||
MtpString path;
|
||||
int64_t length;
|
||||
MtpObjectFormat format;
|
||||
|
||||
MtpResponseCode result = getObjectFilePath(handle, path, length, format);
|
||||
if (result != MTP_RESPONSE_OK) {
|
||||
return result;
|
||||
}
|
||||
info.mCompressedSize = (length > 0xFFFFFFFFLL ? 0xFFFFFFFF : (uint32_t)length);
|
||||
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
jboolean result = env->CallBooleanMethod(mDatabase, method_getObjectInfo,
|
||||
(jint)handle, mIntBuffer, mStringBuffer, mLongBuffer);
|
||||
if (!result)
|
||||
if (!env->CallBooleanMethod(mDatabase, method_getObjectInfo,
|
||||
(jint)handle, mIntBuffer, mStringBuffer, mLongBuffer)) {
|
||||
return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
|
||||
}
|
||||
|
||||
jint* intValues = env->GetIntArrayElements(mIntBuffer, 0);
|
||||
info.mStorageID = intValues[0];
|
||||
@@ -766,9 +775,7 @@ MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
|
||||
env->ReleaseIntArrayElements(mIntBuffer, intValues, 0);
|
||||
|
||||
jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
|
||||
uint64_t size = longValues[0];
|
||||
info.mCompressedSize = (size > 0xFFFFFFFFLL ? 0xFFFFFFFF : size);
|
||||
info.mDateModified = longValues[1];
|
||||
info.mDateModified = longValues[0];
|
||||
env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
|
||||
|
||||
// info.mAssociationType = (format == MTP_FORMAT_ASSOCIATION ?
|
||||
@@ -783,28 +790,23 @@ MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
|
||||
|
||||
// read EXIF data for thumbnail information
|
||||
if (info.mFormat == MTP_FORMAT_EXIF_JPEG || info.mFormat == MTP_FORMAT_JFIF) {
|
||||
MtpString path;
|
||||
int64_t length;
|
||||
MtpObjectFormat format;
|
||||
if (getObjectFilePath(handle, path, length, format) == MTP_RESPONSE_OK) {
|
||||
ResetJpgfile();
|
||||
// Start with an empty image information structure.
|
||||
memset(&ImageInfo, 0, sizeof(ImageInfo));
|
||||
ImageInfo.FlashUsed = -1;
|
||||
ImageInfo.MeteringMode = -1;
|
||||
ImageInfo.Whitebalance = -1;
|
||||
strncpy(ImageInfo.FileName, (const char *)path, PATH_MAX);
|
||||
if (ReadJpegFile((const char*)path, READ_METADATA)) {
|
||||
Section_t* section = FindSection(M_EXIF);
|
||||
if (section) {
|
||||
info.mThumbCompressedSize = ImageInfo.ThumbnailSize;
|
||||
info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
|
||||
info.mImagePixWidth = ImageInfo.Width;
|
||||
info.mImagePixHeight = ImageInfo.Height;
|
||||
}
|
||||
ResetJpgfile();
|
||||
// Start with an empty image information structure.
|
||||
memset(&ImageInfo, 0, sizeof(ImageInfo));
|
||||
ImageInfo.FlashUsed = -1;
|
||||
ImageInfo.MeteringMode = -1;
|
||||
ImageInfo.Whitebalance = -1;
|
||||
strncpy(ImageInfo.FileName, (const char *)path, PATH_MAX);
|
||||
if (ReadJpegFile((const char*)path, READ_METADATA)) {
|
||||
Section_t* section = FindSection(M_EXIF);
|
||||
if (section) {
|
||||
info.mThumbCompressedSize = ImageInfo.ThumbnailSize;
|
||||
info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
|
||||
info.mImagePixWidth = ImageInfo.Width;
|
||||
info.mImagePixHeight = ImageInfo.Height;
|
||||
}
|
||||
DiscardData();
|
||||
}
|
||||
DiscardData();
|
||||
}
|
||||
|
||||
checkAndClearExceptionFromCallback(env, __FUNCTION__);
|
||||
|
||||
Reference in New Issue
Block a user