MTP: Return error if user tries to copy a file >= 4GB to a FAT32 file system
Bug: 4561836 Change-Id: I2bffb93b032038f6c220c24c752ccd7ca66c23a0 Signed-off-by: Mike Lockwood <lockwood@android.com>
This commit is contained in:
@@ -34,6 +34,8 @@ public class StorageVolume implements Parcelable {
|
||||
private final int mMtpReserveSpace;
|
||||
private final boolean mAllowMassStorage;
|
||||
private int mStorageId;
|
||||
// maximum file size for the storage, or zero for no limit
|
||||
private final long mMaxFileSize;
|
||||
|
||||
// StorageVolume extra for ACTION_MEDIA_REMOVED, ACTION_MEDIA_UNMOUNTED, ACTION_MEDIA_CHECKING,
|
||||
// ACTION_MEDIA_NOFS, ACTION_MEDIA_MOUNTED, ACTION_MEDIA_SHARED, ACTION_MEDIA_UNSHARED,
|
||||
@@ -41,18 +43,20 @@ public class StorageVolume implements Parcelable {
|
||||
public static final String EXTRA_STORAGE_VOLUME = "storage_volume";
|
||||
|
||||
public StorageVolume(String path, String description, boolean removable,
|
||||
boolean emulated, int mtpReserveSpace, boolean allowMassStorage) {
|
||||
boolean emulated, int mtpReserveSpace, boolean allowMassStorage, long maxFileSize) {
|
||||
mPath = path;
|
||||
mDescription = description;
|
||||
mRemovable = removable;
|
||||
mEmulated = emulated;
|
||||
mMtpReserveSpace = mtpReserveSpace;
|
||||
mAllowMassStorage = allowMassStorage;
|
||||
mMaxFileSize = maxFileSize;
|
||||
}
|
||||
|
||||
// for parcelling only
|
||||
private StorageVolume(String path, String description, boolean removable,
|
||||
boolean emulated, int mtpReserveSpace, int storageId, boolean allowMassStorage) {
|
||||
boolean emulated, int mtpReserveSpace, int storageId,
|
||||
boolean allowMassStorage, long maxFileSize) {
|
||||
mPath = path;
|
||||
mDescription = description;
|
||||
mRemovable = removable;
|
||||
@@ -60,6 +64,7 @@ public class StorageVolume implements Parcelable {
|
||||
mMtpReserveSpace = mtpReserveSpace;
|
||||
mAllowMassStorage = allowMassStorage;
|
||||
mStorageId = storageId;
|
||||
mMaxFileSize = maxFileSize;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,6 +147,15 @@ public class StorageVolume implements Parcelable {
|
||||
return mAllowMassStorage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns maximum file size for the volume, or zero if it is unbounded.
|
||||
*
|
||||
* @return maximum file size
|
||||
*/
|
||||
public long getMaxFileSize() {
|
||||
return mMaxFileSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof StorageVolume && mPath != null) {
|
||||
@@ -171,9 +185,10 @@ public class StorageVolume implements Parcelable {
|
||||
int storageId = in.readInt();
|
||||
int mtpReserveSpace = in.readInt();
|
||||
int allowMassStorage = in.readInt();
|
||||
long maxFileSize = in.readLong();
|
||||
return new StorageVolume(path, description,
|
||||
removable == 1, emulated == 1,
|
||||
mtpReserveSpace, storageId, allowMassStorage == 1);
|
||||
removable == 1, emulated == 1, mtpReserveSpace,
|
||||
storageId, allowMassStorage == 1, maxFileSize);
|
||||
}
|
||||
|
||||
public StorageVolume[] newArray(int size) {
|
||||
@@ -193,5 +208,6 @@ public class StorageVolume implements Parcelable {
|
||||
parcel.writeInt(mStorageId);
|
||||
parcel.writeInt(mMtpReserveSpace);
|
||||
parcel.writeInt(mAllowMassStorage ? 1 : 0);
|
||||
parcel.writeLong(mMaxFileSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5318,6 +5318,8 @@
|
||||
<attr name="mtpReserve" format="integer" />
|
||||
<!-- true if the storage can be shared via USB mass storage -->
|
||||
<attr name="allowMassStorage" format="boolean" />
|
||||
<!-- maximum file size for the volume in megabytes, zero or unspecified if it is unbounded -->
|
||||
<attr name="maxFileSize" format="integer" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="SwitchPreference">
|
||||
|
||||
@@ -330,7 +330,6 @@ class MtpPropertyGroup {
|
||||
}
|
||||
|
||||
int count = (c == null ? 1 : c.getCount());
|
||||
Log.d(TAG, "count: " + count);
|
||||
MtpPropertyList result = new MtpPropertyList(count * mProperties.length,
|
||||
MtpConstants.RESPONSE_OK);
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ public class MtpStorage {
|
||||
private final String mDescription;
|
||||
private final long mReserveSpace;
|
||||
private final boolean mRemovable;
|
||||
private final long mMaxFileSize;
|
||||
|
||||
public MtpStorage(StorageVolume volume) {
|
||||
mStorageId = volume.getStorageId();
|
||||
@@ -39,6 +40,7 @@ public class MtpStorage {
|
||||
mDescription = volume.getDescription();
|
||||
mReserveSpace = volume.getMtpReserveSpace();
|
||||
mRemovable = volume.isRemovable();
|
||||
mMaxFileSize = volume.getMaxFileSize();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,4 +100,13 @@ public class MtpStorage {
|
||||
public final boolean isRemovable() {
|
||||
return mRemovable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns maximum file size for the storage, or zero if it is unbounded.
|
||||
*
|
||||
* @return maximum file size
|
||||
*/
|
||||
public long getMaxFileSize() {
|
||||
return mMaxFileSize;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ static jfieldID field_MtpStorage_path;
|
||||
static jfieldID field_MtpStorage_description;
|
||||
static jfieldID field_MtpStorage_reserveSpace;
|
||||
static jfieldID field_MtpStorage_removable;
|
||||
static jfieldID field_MtpStorage_maxFileSize;
|
||||
|
||||
static Mutex sMutex;
|
||||
|
||||
@@ -228,12 +229,14 @@ android_mtp_MtpServer_add_storage(JNIEnv *env, jobject thiz, jobject jstorage)
|
||||
jstring description = (jstring)env->GetObjectField(jstorage, field_MtpStorage_description);
|
||||
jlong reserveSpace = env->GetLongField(jstorage, field_MtpStorage_reserveSpace);
|
||||
jboolean removable = env->GetBooleanField(jstorage, field_MtpStorage_removable);
|
||||
jlong maxFileSize = env->GetLongField(jstorage, field_MtpStorage_maxFileSize);
|
||||
|
||||
const char *pathStr = env->GetStringUTFChars(path, NULL);
|
||||
if (pathStr != NULL) {
|
||||
const char *descriptionStr = env->GetStringUTFChars(description, NULL);
|
||||
if (descriptionStr != NULL) {
|
||||
MtpStorage* storage = new MtpStorage(storageID, pathStr, descriptionStr, reserveSpace, removable);
|
||||
MtpStorage* storage = new MtpStorage(storageID, pathStr, descriptionStr,
|
||||
reserveSpace, removable, maxFileSize);
|
||||
thread->addStorage(storage);
|
||||
env->ReleaseStringUTFChars(path, pathStr);
|
||||
env->ReleaseStringUTFChars(description, descriptionStr);
|
||||
@@ -312,6 +315,11 @@ int register_android_mtp_MtpServer(JNIEnv *env)
|
||||
LOGE("Can't find MtpStorage.mRemovable");
|
||||
return -1;
|
||||
}
|
||||
field_MtpStorage_maxFileSize = env->GetFieldID(clazz, "mMaxFileSize", "J");
|
||||
if (field_MtpStorage_maxFileSize == NULL) {
|
||||
LOGE("Can't find MtpStorage.mMaxFileSize");
|
||||
return -1;
|
||||
}
|
||||
clazz_MtpStorage = (jclass)env->NewGlobalRef(clazz);
|
||||
|
||||
clazz = env->FindClass("android/mtp/MtpServer");
|
||||
|
||||
@@ -871,6 +871,14 @@ MtpResponseCode MtpServer::doSendObjectInfo() {
|
||||
// check space first
|
||||
if (mSendObjectFileSize > storage->getFreeSpace())
|
||||
return MTP_RESPONSE_STORAGE_FULL;
|
||||
uint64_t maxFileSize = storage->getMaxFileSize();
|
||||
// check storage max file size
|
||||
if (maxFileSize != 0) {
|
||||
// if mSendObjectFileSize is 0xFFFFFFFF, then all we know is the file size
|
||||
// is >= 0xFFFFFFFF
|
||||
if (mSendObjectFileSize > maxFileSize || mSendObjectFileSize == 0xFFFFFFFF)
|
||||
return MTP_RESPONSE_OBJECT_TOO_LARGE;
|
||||
}
|
||||
|
||||
LOGD("path: %s parent: %d storageID: %08X", (const char*)path, parent, storageID);
|
||||
MtpObjectHandle handle = mDatabase->beginSendObject((const char*)path,
|
||||
|
||||
@@ -33,11 +33,13 @@
|
||||
namespace android {
|
||||
|
||||
MtpStorage::MtpStorage(MtpStorageID id, const char* filePath,
|
||||
const char* description, uint64_t reserveSpace, bool removable)
|
||||
const char* description, uint64_t reserveSpace,
|
||||
bool removable, uint64_t maxFileSize)
|
||||
: mStorageID(id),
|
||||
mFilePath(filePath),
|
||||
mDescription(description),
|
||||
mMaxCapacity(0),
|
||||
mMaxFileSize(maxFileSize),
|
||||
mReserveSpace(reserveSpace),
|
||||
mRemovable(removable)
|
||||
{
|
||||
|
||||
@@ -31,6 +31,7 @@ private:
|
||||
MtpString mFilePath;
|
||||
MtpString mDescription;
|
||||
uint64_t mMaxCapacity;
|
||||
uint64_t mMaxFileSize;
|
||||
// amount of free space to leave unallocated
|
||||
uint64_t mReserveSpace;
|
||||
bool mRemovable;
|
||||
@@ -38,7 +39,7 @@ private:
|
||||
public:
|
||||
MtpStorage(MtpStorageID id, const char* filePath,
|
||||
const char* description, uint64_t reserveSpace,
|
||||
bool removable);
|
||||
bool removable, uint64_t maxFileSize);
|
||||
virtual ~MtpStorage();
|
||||
|
||||
inline MtpStorageID getStorageID() const { return mStorageID; }
|
||||
@@ -50,6 +51,7 @@ public:
|
||||
const char* getDescription() const;
|
||||
inline const char* getPath() const { return (const char *)mFilePath; }
|
||||
inline bool isRemovable() const { return mRemovable; }
|
||||
inline uint64_t getMaxFileSize() const { return mMaxFileSize; }
|
||||
};
|
||||
|
||||
}; // namespace android
|
||||
|
||||
@@ -1075,18 +1075,22 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
|
||||
com.android.internal.R.styleable.Storage_mtpReserve, 0);
|
||||
boolean allowMassStorage = a.getBoolean(
|
||||
com.android.internal.R.styleable.Storage_allowMassStorage, false);
|
||||
// resource parser does not support longs, so XML value is in megabytes
|
||||
long maxFileSize = a.getInt(
|
||||
com.android.internal.R.styleable.Storage_maxFileSize, 0) * 1024L * 1024L;
|
||||
|
||||
Slog.d(TAG, "got storage path: " + path + " description: " + description +
|
||||
" primary: " + primary + " removable: " + removable +
|
||||
" emulated: " + emulated + " mtpReserve: " + mtpReserve +
|
||||
" allowMassStorage: " + allowMassStorage);
|
||||
" allowMassStorage: " + allowMassStorage +
|
||||
" maxFileSize: " + maxFileSize);
|
||||
if (path == null || description == null) {
|
||||
Slog.e(TAG, "path or description is null in readStorageList");
|
||||
} else {
|
||||
String pathString = path.toString();
|
||||
StorageVolume volume = new StorageVolume(pathString,
|
||||
description.toString(), removable, emulated,
|
||||
mtpReserve, allowMassStorage);
|
||||
mtpReserve, allowMassStorage, maxFileSize);
|
||||
if (primary) {
|
||||
if (mPrimaryVolume == null) {
|
||||
mPrimaryVolume = volume;
|
||||
|
||||
Reference in New Issue
Block a user