Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 00fc90e3 authored by Kevin Rocard's avatar Kevin Rocard Committed by Automerger Merge Worker
Browse files

Merge changes I17264f0e,I0581978f am: 06c8be69 am: d9a6df39 am: 7a30e9f8 am: 326230d4

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1902510

Change-Id: Ica2a9bc91dbdf8ab878b0cbfa141e5935735ce6f
parents 9edeecff 326230d4
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -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;
                if (stringValue.startsWith("Android/")) {
                Log.d(TAG, "setDeviceProperty." + Integer.toHexString(property)
                        + "=" + stringValue);
                if (stringValue.startsWith("Android/")) {
                    mSkipThumbForHost = true;
                } else if (stringValue.startsWith("Windows/")) {
                    mHostIsWindows = true;
                }
                return MtpConstants.RESPONSE_OK;
        }
+14 −1
Original line number Diff line number Diff line
@@ -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();
    }
}
+42 −4
Original line number Diff line number Diff line
@@ -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;
    }
+4 −3
Original line number Diff line number Diff line
@@ -160,10 +160,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