Merge changes I17264f0e,I0581978f

* changes:
  Limit transcoding size workaround to windows
  Workaround to fixup MTP transcode file size
This commit is contained in:
Kevin Rocard 2022-02-04 11:25:53 +00:00 committed by Gerrit Code Review
commit 06c8be69b9
4 changed files with 67 additions and 11 deletions

View File

@ -103,6 +103,7 @@ public class MtpDatabase implements AutoCloseable {
private int mDeviceType;
private String mHostType;
private boolean mSkipThumbForHost = false;
private volatile boolean mHostIsWindows = false;
private MtpServer mServer;
private MtpStorageManager mManager;
@ -358,7 +359,7 @@ public class MtpDatabase implements AutoCloseable {
}
public void addStorage(StorageVolume storage) {
MtpStorage mtpStorage = mManager.addMtpStorage(storage);
MtpStorage mtpStorage = mManager.addMtpStorage(storage, () -> mHostIsWindows);
mStorageMap.put(storage.getPath(), mtpStorage);
if (mServer != null) {
mServer.addStorage(mtpStorage);
@ -413,6 +414,7 @@ public class MtpDatabase implements AutoCloseable {
}
mHostType = "";
mSkipThumbForHost = false;
mHostIsWindows = false;
}
@VisibleForNative
@ -736,10 +738,12 @@ public class MtpDatabase implements AutoCloseable {
: MtpConstants.RESPONSE_GENERAL_ERROR);
case MtpConstants.DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO:
mHostType = stringValue;
Log.d(TAG, "setDeviceProperty." + Integer.toHexString(property)
+ "=" + stringValue);
if (stringValue.startsWith("Android/")) {
Log.d(TAG, "setDeviceProperty." + Integer.toHexString(property)
+ "=" + stringValue);
mSkipThumbForHost = true;
} else if (stringValue.startsWith("Windows/")) {
mHostIsWindows = true;
}
return MtpConstants.RESPONSE_OK;
}

View File

@ -19,6 +19,8 @@ package android.mtp;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.storage.StorageVolume;
import java.util.function.Supplier;
/**
* This class represents a storage unit on an MTP device.
* Used only for MTP support in USB responder mode.
@ -33,14 +35,16 @@ public class MtpStorage {
private final boolean mRemovable;
private final long mMaxFileSize;
private final String mVolumeName;
private final Supplier<Boolean> mIsHostWindows;
public MtpStorage(StorageVolume volume, int storageId) {
public MtpStorage(StorageVolume volume, int storageId, Supplier<Boolean> isHostWindows) {
mStorageId = storageId;
mPath = volume.getPath();
mDescription = volume.getDescription(null);
mRemovable = volume.isRemovable();
mMaxFileSize = volume.getMaxFileSize();
mVolumeName = volume.getMediaStoreVolumeName();
mIsHostWindows = isHostWindows;
}
/**
@ -93,4 +97,13 @@ public class MtpStorage {
public String getVolumeName() {
return mVolumeName;
}
/**
* Returns true if the mtp host of this storage is Windows.
*
* @return is host Windows
*/
public boolean isHostWindows() {
return mIsHostWindows.get();
}
}

View File

@ -18,7 +18,11 @@ package android.mtp;
import android.media.MediaFile;
import android.os.FileObserver;
import android.os.SystemProperties;
import android.os.storage.StorageVolume;
import android.system.ErrnoException;
import android.system.Os;
import android.system.StructStat;
import android.util.Log;
import com.android.internal.util.Preconditions;
@ -35,6 +39,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Supplier;
/**
* MtpStorageManager provides functionality for listing, tracking, and notifying MtpServer of
@ -199,7 +204,38 @@ public class MtpStorageManager {
}
public long getSize() {
return mIsDir ? 0 : getPath().toFile().length();
return mIsDir ? 0 : maybeApplyTranscodeLengthWorkaround(getPath().toFile().length());
}
private long maybeApplyTranscodeLengthWorkaround(long length) {
// Windows truncates transferred files to the size advertised in the object property.
if (mStorage.isHostWindows() && isTranscodeMtpEnabled() && isFileTranscodeSupported()) {
// If the file supports transcoding, we double the returned size to accommodate
// the increase in size from transcoding to AVC. This is the same heuristic
// applied in the FUSE daemon (MediaProvider).
return length * 2;
}
return length;
}
private boolean isTranscodeMtpEnabled() {
return SystemProperties.getBoolean("sys.fuse.transcode_mtp", false);
}
private boolean isFileTranscodeSupported() {
// Check if the file supports transcoding by reading the |st_nlinks| struct stat
// field. This will be > 1 if the file supports transcoding. The FUSE daemon
// sets the field accordingly to enable the MTP stack workaround some Windows OS
// MTP client bug where they ignore the size returned as part of getting the MTP
// object, see MtpServer#doGetObject.
final Path path = getPath();
try {
StructStat stat = Os.stat(path.toString());
return stat.st_nlink > 1;
} catch (ErrnoException e) {
Log.w(TAG, "Failed to stat path: " + getPath() + ". Ignoring transcoding.");
return false;
}
}
public Path getPath() {
@ -420,10 +456,12 @@ public class MtpStorageManager {
* @param volume Storage to add.
* @return the associated MtpStorage
*/
public synchronized MtpStorage addMtpStorage(StorageVolume volume) {
public synchronized MtpStorage addMtpStorage(StorageVolume volume,
Supplier<Boolean> isHostWindows) {
int storageId = ((getNextStorageId() & 0x0000FFFF) << 16) + 1;
MtpStorage storage = new MtpStorage(volume, storageId);
MtpObject root = new MtpObject(storage.getPath(), storageId, storage, null, true);
MtpStorage storage = new MtpStorage(volume, storageId, isHostWindows);
MtpObject root = new MtpObject(storage.getPath(), storageId, storage, /* parent= */ null,
/* isDir= */ true);
mRoots.put(storageId, root);
return storage;
}

View File

@ -159,10 +159,11 @@ public class MtpStorageManagerTest {
Log.d(TAG, "sendObjectInfoChanged: " + id);
objectsInfoChanged.add(id);
}
}, null);
}, /* subdirectories= */ null);
mainMtpStorage = manager.addMtpStorage(mainStorage);
secondaryMtpStorage = manager.addMtpStorage(secondaryStorage);
mainMtpStorage = manager.addMtpStorage(mainStorage, /* isHostWindows= */ () -> false);
secondaryMtpStorage = manager.addMtpStorage(secondaryStorage,
/* isHostWindows= */ () -> false);
}
@After