12f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood/*
22f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood * Copyright (C) 2011 The Android Open Source Project
32f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood *
42f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License");
52f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood * you may not use this file except in compliance with the License.
62f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood * You may obtain a copy of the License at
72f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood *
82f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood *      http://www.apache.org/licenses/LICENSE-2.0
92f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood *
102f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood * Unless required by applicable law or agreed to in writing, software
112f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS,
122f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood * See the License for the specific language governing permissions and
142f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood * limitations under the License.
152f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood */
162f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood
172f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwoodpackage android.os.storage;
182f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood
1904a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Lemeimport android.annotation.Nullable;
2013fe2a5330a5df662d7b1b136e7b08fe34c94a42Fabrice Di Meglioimport android.content.Context;
2104a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Lemeimport android.content.Intent;
224887789e44cdb16b042a35e8ec03983213e88ac6Jeff Sharkeyimport android.net.TrafficStats;
2304a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Lemeimport android.net.Uri;
2404a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Lemeimport android.os.Environment;
252f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwoodimport android.os.Parcel;
262f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwoodimport android.os.Parcelable;
27b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkeyimport android.os.UserHandle;
2804a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Lemeimport android.provider.DocumentsContract;
29b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkey
305aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkeyimport com.android.internal.util.IndentingPrintWriter;
311b8ef7e3165ff9aa52a4905dafc8d0f83e7403f9Jeff Sharkeyimport com.android.internal.util.Preconditions;
325aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey
335aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkeyimport java.io.CharArrayWriter;
34b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkeyimport java.io.File;
352f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood
362f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood/**
3704a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * Information about a shared/external storage volume for a specific user.
3804a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme *
3904a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * <p>
4004a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * A device always has one (and one only) primary storage volume, but it could have extra volumes,
4104a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * like SD cards and USB drives. This object represents the logical view of a storage
4204a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * volume for a specific user: different users might have different views for the same physical
4304a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * volume (for example, if the volume is a built-in emulated storage).
4404a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme *
451b8ef7e3165ff9aa52a4905dafc8d0f83e7403f9Jeff Sharkey * <p>
4604a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * The storage volume is not necessarily mounted, applications should use {@link #getState()} to
4704a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * verify its state.
4804a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme *
4904a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * <p>
5004a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * Applications willing to read or write to this storage volume needs to get a permission from the
5104a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * user first, which can be achieved in the following ways:
5204a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme *
5304a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * <ul>
5404a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * <li>To get access to standard directories (like the {@link Environment#DIRECTORY_PICTURES}), they
5504a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * can use the {@link #createAccessIntent(String)}. This is the recommend way, since it provides a
5604a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * simpler API and narrows the access to the given directory (and its descendants).
5753fcc756d06ed382e7b02b266631f7848d1b9c4fFelipe Leme * <li>To get access to any directory (and its descendants), they can use the Storage Acess
5853fcc756d06ed382e7b02b266631f7848d1b9c4fFelipe Leme * Framework APIs (such as {@link Intent#ACTION_OPEN_DOCUMENT} and
5953fcc756d06ed382e7b02b266631f7848d1b9c4fFelipe Leme * {@link Intent#ACTION_OPEN_DOCUMENT_TREE}, although these APIs do not guarantee the user will
6053fcc756d06ed382e7b02b266631f7848d1b9c4fFelipe Leme * select this specific volume.
6104a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * <li>To get read and write access to the primary storage volume, applications can declare the
6204a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} and
6304a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} permissions respectively, with the
6404a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * latter including the former. This approach is discouraged, since users may be hesitant to grant
6504a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * broad access to all files contained on a storage device.
6604a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * </ul>
6704a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme *
68c02bfae73e139f2a1c56cc6b051bfc7877b8cf1dJeff Sharkey * <p>It can be obtained through {@link StorageManager#getStorageVolumes()} and
69c02bfae73e139f2a1c56cc6b051bfc7877b8cf1dJeff Sharkey * {@link StorageManager#getPrimaryStorageVolume()} and also as an extra in some broadcasts
7004a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * (see {@link #EXTRA_STORAGE_VOLUME}).
71b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkey *
7204a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * <p>
7304a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * See {@link Environment#getExternalStorageDirectory()} for more info about shared/external
7404a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme * storage semantics.
752f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood */
7604a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme// NOTE: This is a legacy specialization of VolumeInfo which describes the volume for a specific
7704a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme// user, but is now part of the public API.
7850d1c044b5ce4b6fef532dc6e083cef903f554b2Jeff Sharkeypublic final class StorageVolume implements Parcelable {
792f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood
804887789e44cdb16b042a35e8ec03983213e88ac6Jeff Sharkey    private final String mId;
814887789e44cdb16b042a35e8ec03983213e88ac6Jeff Sharkey    private final int mStorageId;
82b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkey    private final File mPath;
831b8ef7e3165ff9aa52a4905dafc8d0f83e7403f9Jeff Sharkey    private final String mDescription;
849545dc020ea11649d70dcbe911a8e82a3254a4eaJeff Sharkey    private final boolean mPrimary;
852f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    private final boolean mRemovable;
862f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    private final boolean mEmulated;
874887789e44cdb16b042a35e8ec03983213e88ac6Jeff Sharkey    private final long mMtpReserveSize;
888e8b280bd19fa6cb69bb19e1d90cf03a47ba2d72Mike Lockwood    private final boolean mAllowMassStorage;
897a59dd2ce33b46cbc73eef964ddb4272ea1da8d1Mike Lockwood    private final long mMaxFileSize;
90b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkey    private final UserHandle mOwner;
911b8ef7e3165ff9aa52a4905dafc8d0f83e7403f9Jeff Sharkey    private final String mFsUuid;
924887789e44cdb16b042a35e8ec03983213e88ac6Jeff Sharkey    private final String mState;
935aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey
9404a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme    /**
9504a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * Name of the {@link Parcelable} extra in the {@link Intent#ACTION_MEDIA_REMOVED},
9604a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * {@link Intent#ACTION_MEDIA_UNMOUNTED}, {@link Intent#ACTION_MEDIA_CHECKING},
9704a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * {@link Intent#ACTION_MEDIA_NOFS}, {@link Intent#ACTION_MEDIA_MOUNTED},
9804a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * {@link Intent#ACTION_MEDIA_SHARED}, {@link Intent#ACTION_MEDIA_BAD_REMOVAL},
9904a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * {@link Intent#ACTION_MEDIA_UNMOUNTABLE}, and {@link Intent#ACTION_MEDIA_EJECT} broadcast that
10004a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * contains a {@link StorageVolume}.
10104a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     */
10204a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme    // Also sent on ACTION_MEDIA_UNSHARED, which is @hide
10304a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme    public static final String EXTRA_STORAGE_VOLUME = "android.os.storage.extra.STORAGE_VOLUME";
104a5250c93928e256738125b265e10c96c3575597eMike Lockwood
10534a9d5271915fb82c22811e6d17691a34b6c52c1Felipe Leme    /**
10634a9d5271915fb82c22811e6d17691a34b6c52c1Felipe Leme     * Name of the String extra used by {@link #createAccessIntent(String) createAccessIntent}.
10734a9d5271915fb82c22811e6d17691a34b6c52c1Felipe Leme     *
10834a9d5271915fb82c22811e6d17691a34b6c52c1Felipe Leme     * @hide
10934a9d5271915fb82c22811e6d17691a34b6c52c1Felipe Leme     */
11034a9d5271915fb82c22811e6d17691a34b6c52c1Felipe Leme    public static final String EXTRA_DIRECTORY_NAME = "android.os.storage.extra.DIRECTORY_NAME";
11134a9d5271915fb82c22811e6d17691a34b6c52c1Felipe Leme
11234a9d5271915fb82c22811e6d17691a34b6c52c1Felipe Leme    /**
11334a9d5271915fb82c22811e6d17691a34b6c52c1Felipe Leme     * Name of the intent used by {@link #createAccessIntent(String) createAccessIntent}.
11434a9d5271915fb82c22811e6d17691a34b6c52c1Felipe Leme     */
11534a9d5271915fb82c22811e6d17691a34b6c52c1Felipe Leme    private static final String ACTION_OPEN_EXTERNAL_DIRECTORY =
11634a9d5271915fb82c22811e6d17691a34b6c52c1Felipe Leme            "android.os.storage.action.OPEN_EXTERNAL_DIRECTORY";
11734a9d5271915fb82c22811e6d17691a34b6c52c1Felipe Leme
11804a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme    /** {@hide} */
1195af1835d678031d4a6615edc96ba58c82304b31dJeff Sharkey    public static final int STORAGE_ID_INVALID = 0x00000000;
12004a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme    /** {@hide} */
1215af1835d678031d4a6615edc96ba58c82304b31dJeff Sharkey    public static final int STORAGE_ID_PRIMARY = 0x00010001;
1225af1835d678031d4a6615edc96ba58c82304b31dJeff Sharkey
12304a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme    /** {@hide} */
1241b8ef7e3165ff9aa52a4905dafc8d0f83e7403f9Jeff Sharkey    public StorageVolume(String id, int storageId, File path, String description, boolean primary,
1254887789e44cdb16b042a35e8ec03983213e88ac6Jeff Sharkey            boolean removable, boolean emulated, long mtpReserveSize, boolean allowMassStorage,
1261b8ef7e3165ff9aa52a4905dafc8d0f83e7403f9Jeff Sharkey            long maxFileSize, UserHandle owner, String fsUuid, String state) {
1271b8ef7e3165ff9aa52a4905dafc8d0f83e7403f9Jeff Sharkey        mId = Preconditions.checkNotNull(id);
1284887789e44cdb16b042a35e8ec03983213e88ac6Jeff Sharkey        mStorageId = storageId;
1291b8ef7e3165ff9aa52a4905dafc8d0f83e7403f9Jeff Sharkey        mPath = Preconditions.checkNotNull(path);
1301b8ef7e3165ff9aa52a4905dafc8d0f83e7403f9Jeff Sharkey        mDescription = Preconditions.checkNotNull(description);
1319545dc020ea11649d70dcbe911a8e82a3254a4eaJeff Sharkey        mPrimary = primary;
1322f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood        mRemovable = removable;
1332f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood        mEmulated = emulated;
1344887789e44cdb16b042a35e8ec03983213e88ac6Jeff Sharkey        mMtpReserveSize = mtpReserveSize;
1358e8b280bd19fa6cb69bb19e1d90cf03a47ba2d72Mike Lockwood        mAllowMassStorage = allowMassStorage;
1367a59dd2ce33b46cbc73eef964ddb4272ea1da8d1Mike Lockwood        mMaxFileSize = maxFileSize;
1371b8ef7e3165ff9aa52a4905dafc8d0f83e7403f9Jeff Sharkey        mOwner = Preconditions.checkNotNull(owner);
1381b8ef7e3165ff9aa52a4905dafc8d0f83e7403f9Jeff Sharkey        mFsUuid = fsUuid;
1391b8ef7e3165ff9aa52a4905dafc8d0f83e7403f9Jeff Sharkey        mState = Preconditions.checkNotNull(state);
1402f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    }
1412f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood
1429545dc020ea11649d70dcbe911a8e82a3254a4eaJeff Sharkey    private StorageVolume(Parcel in) {
1434887789e44cdb16b042a35e8ec03983213e88ac6Jeff Sharkey        mId = in.readString();
1449545dc020ea11649d70dcbe911a8e82a3254a4eaJeff Sharkey        mStorageId = in.readInt();
145b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkey        mPath = new File(in.readString());
1461b8ef7e3165ff9aa52a4905dafc8d0f83e7403f9Jeff Sharkey        mDescription = in.readString();
147b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkey        mPrimary = in.readInt() != 0;
148b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkey        mRemovable = in.readInt() != 0;
149b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkey        mEmulated = in.readInt() != 0;
1504887789e44cdb16b042a35e8ec03983213e88ac6Jeff Sharkey        mMtpReserveSize = in.readLong();
151b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkey        mAllowMassStorage = in.readInt() != 0;
1529545dc020ea11649d70dcbe911a8e82a3254a4eaJeff Sharkey        mMaxFileSize = in.readLong();
153b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkey        mOwner = in.readParcelable(null);
1541b8ef7e3165ff9aa52a4905dafc8d0f83e7403f9Jeff Sharkey        mFsUuid = in.readString();
1551f706c6cd1cb841adadc2babc57a34e5728983ecJeff Sharkey        mState = in.readString();
156b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkey    }
157b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkey
15804a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme    /** {@hide} */
1594887789e44cdb16b042a35e8ec03983213e88ac6Jeff Sharkey    public String getId() {
1604887789e44cdb16b042a35e8ec03983213e88ac6Jeff Sharkey        return mId;
161fbfe55512596fd00c1fb51caa851e17dae60fd43Mike Lockwood    }
162fbfe55512596fd00c1fb51caa851e17dae60fd43Mike Lockwood
1632f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    /**
1642f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood     * Returns the mount path for the volume.
1652f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood     *
1662f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood     * @return the mount path
16704a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * @hide
1682f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood     */
1692f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    public String getPath() {
170b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkey        return mPath.toString();
171b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkey    }
172b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkey
17304a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme    /** {@hide} */
174b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkey    public File getPathFile() {
1752f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood        return mPath;
1762f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    }
1772f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood
1782f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    /**
17904a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * Returns a user-visible description of the volume.
1802f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood     *
1812f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood     * @return the volume description
1822f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood     */
18313fe2a5330a5df662d7b1b136e7b08fe34c94a42Fabrice Di Meglio    public String getDescription(Context context) {
1841b8ef7e3165ff9aa52a4905dafc8d0f83e7403f9Jeff Sharkey        return mDescription;
1852f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    }
1862f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood
18704a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme    /**
18804a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * Returns true if the volume is the primary shared/external storage, which is the volume
18904a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * backed by {@link Environment#getExternalStorageDirectory()}.
19004a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     */
1919545dc020ea11649d70dcbe911a8e82a3254a4eaJeff Sharkey    public boolean isPrimary() {
1929545dc020ea11649d70dcbe911a8e82a3254a4eaJeff Sharkey        return mPrimary;
1939545dc020ea11649d70dcbe911a8e82a3254a4eaJeff Sharkey    }
1949545dc020ea11649d70dcbe911a8e82a3254a4eaJeff Sharkey
1952f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    /**
1962f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood     * Returns true if the volume is removable.
1972f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood     *
1982f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood     * @return is removable
1992f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood     */
2002f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    public boolean isRemovable() {
2012f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood        return mRemovable;
2022f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    }
2032f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood
2042f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    /**
2052f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood     * Returns true if the volume is emulated.
2062f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood     *
2072f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood     * @return is removable
2082f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood     */
2092f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    public boolean isEmulated() {
2102f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood        return mEmulated;
2112f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    }
2122f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood
2132f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    /**
214fbfe55512596fd00c1fb51caa851e17dae60fd43Mike Lockwood     * Returns the MTP storage ID for the volume.
215fbfe55512596fd00c1fb51caa851e17dae60fd43Mike Lockwood     * this is also used for the storage_id column in the media provider.
216fbfe55512596fd00c1fb51caa851e17dae60fd43Mike Lockwood     *
217fbfe55512596fd00c1fb51caa851e17dae60fd43Mike Lockwood     * @return MTP storage ID
21804a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * @hide
219fbfe55512596fd00c1fb51caa851e17dae60fd43Mike Lockwood     */
220fbfe55512596fd00c1fb51caa851e17dae60fd43Mike Lockwood    public int getStorageId() {
221fbfe55512596fd00c1fb51caa851e17dae60fd43Mike Lockwood        return mStorageId;
222fbfe55512596fd00c1fb51caa851e17dae60fd43Mike Lockwood    }
223fbfe55512596fd00c1fb51caa851e17dae60fd43Mike Lockwood
224fbfe55512596fd00c1fb51caa851e17dae60fd43Mike Lockwood    /**
2252f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood     * Number of megabytes of space to leave unallocated by MTP.
2262f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood     * MTP will subtract this value from the free space it reports back
2272f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood     * to the host via GetStorageInfo, and will not allow new files to
2282f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood     * be added via MTP if there is less than this amount left free in the storage.
2292f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood     * If MTP has dedicated storage this value should be zero, but if MTP is
2302f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood     * sharing storage with the rest of the system, set this to a positive value
2312f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood     * to ensure that MTP activity does not result in the storage being
2322f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood     * too close to full.
2332f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood     *
2342f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood     * @return MTP reserve space
23504a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * @hide
2362f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood     */
2372f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    public int getMtpReserveSpace() {
2384887789e44cdb16b042a35e8ec03983213e88ac6Jeff Sharkey        return (int) (mMtpReserveSize / TrafficStats.MB_IN_BYTES);
2392f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    }
2402f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood
2418e8b280bd19fa6cb69bb19e1d90cf03a47ba2d72Mike Lockwood    /**
2428e8b280bd19fa6cb69bb19e1d90cf03a47ba2d72Mike Lockwood     * Returns true if this volume can be shared via USB mass storage.
2438e8b280bd19fa6cb69bb19e1d90cf03a47ba2d72Mike Lockwood     *
2448e8b280bd19fa6cb69bb19e1d90cf03a47ba2d72Mike Lockwood     * @return whether mass storage is allowed
24504a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * @hide
2468e8b280bd19fa6cb69bb19e1d90cf03a47ba2d72Mike Lockwood     */
2478e8b280bd19fa6cb69bb19e1d90cf03a47ba2d72Mike Lockwood    public boolean allowMassStorage() {
2488e8b280bd19fa6cb69bb19e1d90cf03a47ba2d72Mike Lockwood        return mAllowMassStorage;
2498e8b280bd19fa6cb69bb19e1d90cf03a47ba2d72Mike Lockwood    }
2508e8b280bd19fa6cb69bb19e1d90cf03a47ba2d72Mike Lockwood
2517a59dd2ce33b46cbc73eef964ddb4272ea1da8d1Mike Lockwood    /**
2527a59dd2ce33b46cbc73eef964ddb4272ea1da8d1Mike Lockwood     * Returns maximum file size for the volume, or zero if it is unbounded.
2537a59dd2ce33b46cbc73eef964ddb4272ea1da8d1Mike Lockwood     *
2547a59dd2ce33b46cbc73eef964ddb4272ea1da8d1Mike Lockwood     * @return maximum file size
25504a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * @hide
2567a59dd2ce33b46cbc73eef964ddb4272ea1da8d1Mike Lockwood     */
2577a59dd2ce33b46cbc73eef964ddb4272ea1da8d1Mike Lockwood    public long getMaxFileSize() {
2587a59dd2ce33b46cbc73eef964ddb4272ea1da8d1Mike Lockwood        return mMaxFileSize;
2597a59dd2ce33b46cbc73eef964ddb4272ea1da8d1Mike Lockwood    }
2607a59dd2ce33b46cbc73eef964ddb4272ea1da8d1Mike Lockwood
26104a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme    /** {@hide} */
262b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkey    public UserHandle getOwner() {
263b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkey        return mOwner;
264b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkey    }
265b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkey
26604a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme    /**
26704a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * Gets the volume UUID, if any.
26804a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     */
26904a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme    public @Nullable String getUuid() {
2701b8ef7e3165ff9aa52a4905dafc8d0f83e7403f9Jeff Sharkey        return mFsUuid;
2715aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey    }
2725aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey
2735aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey    /**
2745aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey     * Parse and return volume UUID as FAT volume ID, or return -1 if unable to
2755aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey     * parse or UUID is unknown.
27604a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * @hide
2775aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey     */
2785aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey    public int getFatVolumeId() {
2791b8ef7e3165ff9aa52a4905dafc8d0f83e7403f9Jeff Sharkey        if (mFsUuid == null || mFsUuid.length() != 9) {
2805aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey            return -1;
2815aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey        }
2825aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey        try {
2831b8ef7e3165ff9aa52a4905dafc8d0f83e7403f9Jeff Sharkey            return (int) Long.parseLong(mFsUuid.replace("-", ""), 16);
2845aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey        } catch (NumberFormatException e) {
2855aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey            return -1;
2865aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey        }
2875aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey    }
2885aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey
28904a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme    /** {@hide} */
2905aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey    public String getUserLabel() {
2911b8ef7e3165ff9aa52a4905dafc8d0f83e7403f9Jeff Sharkey        return mDescription;
2925aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey    }
2935aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey
29404a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme    /**
29504a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * Returns the current state of the volume.
29604a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     *
29704a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * @return one of {@link Environment#MEDIA_UNKNOWN}, {@link Environment#MEDIA_REMOVED},
29804a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     *         {@link Environment#MEDIA_UNMOUNTED}, {@link Environment#MEDIA_CHECKING},
29904a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     *         {@link Environment#MEDIA_NOFS}, {@link Environment#MEDIA_MOUNTED},
30004a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     *         {@link Environment#MEDIA_MOUNTED_READ_ONLY}, {@link Environment#MEDIA_SHARED},
30104a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     *         {@link Environment#MEDIA_BAD_REMOVAL}, or {@link Environment#MEDIA_UNMOUNTABLE}.
30204a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     */
3031f706c6cd1cb841adadc2babc57a34e5728983ecJeff Sharkey    public String getState() {
3041f706c6cd1cb841adadc2babc57a34e5728983ecJeff Sharkey        return mState;
3051f706c6cd1cb841adadc2babc57a34e5728983ecJeff Sharkey    }
3061f706c6cd1cb841adadc2babc57a34e5728983ecJeff Sharkey
30704a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme    /**
308db892b84e513f174d29f67d293435407a0ac7c6cFelipe Leme     * Builds an intent to give access to a standard storage directory or entire volume after
309db892b84e513f174d29f67d293435407a0ac7c6cFelipe Leme     * obtaining the user's approval.
31004a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * <p>
31104a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * When invoked, the system will ask the user to grant access to the requested directory (and
31204a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * its descendants). The result of the request will be returned to the activity through the
31304a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * {@code onActivityResult} method.
31404a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * <p>
31504a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * To gain access to descendants (child, grandchild, etc) documents, use
31604a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * {@link DocumentsContract#buildDocumentUriUsingTree(Uri, String)}, or
31704a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * {@link DocumentsContract#buildChildDocumentsUriUsingTree(Uri, String)} with the returned URI.
3182ac876945bfb388fed8b796c6d8c8e7f2e97f0d4Felipe Leme     * <p>
3192ac876945bfb388fed8b796c6d8c8e7f2e97f0d4Felipe Leme     * If your application only needs to store internal data, consider using
32004a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * {@link Context#getExternalFilesDirs(String) Context.getExternalFilesDirs},
3212ac876945bfb388fed8b796c6d8c8e7f2e97f0d4Felipe Leme     * {@link Context#getExternalCacheDirs()}, or {@link Context#getExternalMediaDirs()}, which
3222ac876945bfb388fed8b796c6d8c8e7f2e97f0d4Felipe Leme     * require no permissions to read or write.
3232ac876945bfb388fed8b796c6d8c8e7f2e97f0d4Felipe Leme     * <p>
3242ac876945bfb388fed8b796c6d8c8e7f2e97f0d4Felipe Leme     * Access to the entire volume is only available for non-primary volumes (for the primary
3252ac876945bfb388fed8b796c6d8c8e7f2e97f0d4Felipe Leme     * volume, apps can use the {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} and
3262ac876945bfb388fed8b796c6d8c8e7f2e97f0d4Felipe Leme     * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} permissions) and should be used
3272ac876945bfb388fed8b796c6d8c8e7f2e97f0d4Felipe Leme     * with caution, since users are more likely to deny access when asked for entire volume access
3282ac876945bfb388fed8b796c6d8c8e7f2e97f0d4Felipe Leme     * rather than specific directories.
32904a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     *
3302ac876945bfb388fed8b796c6d8c8e7f2e97f0d4Felipe Leme     * @param directoryName must be one of {@link Environment#DIRECTORY_MUSIC},
3312ac876945bfb388fed8b796c6d8c8e7f2e97f0d4Felipe Leme     *            {@link Environment#DIRECTORY_PODCASTS}, {@link Environment#DIRECTORY_RINGTONES},
3322ac876945bfb388fed8b796c6d8c8e7f2e97f0d4Felipe Leme     *            {@link Environment#DIRECTORY_ALARMS}, {@link Environment#DIRECTORY_NOTIFICATIONS},
3332ac876945bfb388fed8b796c6d8c8e7f2e97f0d4Felipe Leme     *            {@link Environment#DIRECTORY_PICTURES}, {@link Environment#DIRECTORY_MOVIES},
3342ac876945bfb388fed8b796c6d8c8e7f2e97f0d4Felipe Leme     *            {@link Environment#DIRECTORY_DOWNLOADS}, {@link Environment#DIRECTORY_DCIM}, or
3352ac876945bfb388fed8b796c6d8c8e7f2e97f0d4Felipe Leme     *            {@link Environment#DIRECTORY_DOCUMENTS}, or {code null} to request access to the
3362ac876945bfb388fed8b796c6d8c8e7f2e97f0d4Felipe Leme     *            entire volume.
3372ac876945bfb388fed8b796c6d8c8e7f2e97f0d4Felipe Leme     * @return intent to request access, or {@code null} if the requested directory is invalid for
3382ac876945bfb388fed8b796c6d8c8e7f2e97f0d4Felipe Leme     *         that volume.
33904a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     * @see DocumentsContract
34004a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme     */
3412ac876945bfb388fed8b796c6d8c8e7f2e97f0d4Felipe Leme    public @Nullable Intent createAccessIntent(String directoryName) {
3422ac876945bfb388fed8b796c6d8c8e7f2e97f0d4Felipe Leme        if ((isPrimary() && directoryName == null) ||
3432ac876945bfb388fed8b796c6d8c8e7f2e97f0d4Felipe Leme                (directoryName != null && !Environment.isStandardDirectory(directoryName))) {
3442ac876945bfb388fed8b796c6d8c8e7f2e97f0d4Felipe Leme            return null;
3452ac876945bfb388fed8b796c6d8c8e7f2e97f0d4Felipe Leme        }
34634a9d5271915fb82c22811e6d17691a34b6c52c1Felipe Leme        final Intent intent = new Intent(ACTION_OPEN_EXTERNAL_DIRECTORY);
34734a9d5271915fb82c22811e6d17691a34b6c52c1Felipe Leme        intent.putExtra(EXTRA_STORAGE_VOLUME, this);
34834a9d5271915fb82c22811e6d17691a34b6c52c1Felipe Leme        intent.putExtra(EXTRA_DIRECTORY_NAME, directoryName);
34904a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme        return intent;
35004a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme    }
35104a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme
3522f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    @Override
3532f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    public boolean equals(Object obj) {
3542f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood        if (obj instanceof StorageVolume && mPath != null) {
3552f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood            StorageVolume volume = (StorageVolume)obj;
3562f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood            return (mPath.equals(volume.mPath));
3572f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood        }
3582f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood        return false;
3592f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    }
3602f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood
3612f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    @Override
3622f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    public int hashCode() {
3632f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood        return mPath.hashCode();
3642f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    }
3652f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood
3662f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    @Override
3672f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    public String toString() {
36804a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme        final StringBuilder buffer = new StringBuilder("StorageVolume: ").append(mDescription);
36904a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme        if (mFsUuid != null) {
37004a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme            buffer.append(" (").append(mFsUuid).append(")");
37104a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme        }
37204a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme        return buffer.toString();
37304a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme    }
37404a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme
37504a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme    /** {@hide} */
37604a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme    // TODO(b/26742218): find out where toString() is called internally and replace these calls by
37704a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme    // dump().
37804a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme    public String dump() {
3795aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey        final CharArrayWriter writer = new CharArrayWriter();
3805aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey        dump(new IndentingPrintWriter(writer, "    ", 80));
3815aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey        return writer.toString();
3825aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey    }
3835aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey
38404a5d40cf35fb2c2fca2c1bfd573e5916d804ef6Felipe Leme    /** {@hide} */
3855aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey    public void dump(IndentingPrintWriter pw) {
3865aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey        pw.println("StorageVolume:");
3875aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey        pw.increaseIndent();
3884887789e44cdb16b042a35e8ec03983213e88ac6Jeff Sharkey        pw.printPair("mId", mId);
3895aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey        pw.printPair("mStorageId", mStorageId);
3905aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey        pw.printPair("mPath", mPath);
3911b8ef7e3165ff9aa52a4905dafc8d0f83e7403f9Jeff Sharkey        pw.printPair("mDescription", mDescription);
3925aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey        pw.printPair("mPrimary", mPrimary);
3935aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey        pw.printPair("mRemovable", mRemovable);
3945aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey        pw.printPair("mEmulated", mEmulated);
3954887789e44cdb16b042a35e8ec03983213e88ac6Jeff Sharkey        pw.printPair("mMtpReserveSize", mMtpReserveSize);
3965aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey        pw.printPair("mAllowMassStorage", mAllowMassStorage);
3975aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey        pw.printPair("mMaxFileSize", mMaxFileSize);
3985aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey        pw.printPair("mOwner", mOwner);
3991b8ef7e3165ff9aa52a4905dafc8d0f83e7403f9Jeff Sharkey        pw.printPair("mFsUuid", mFsUuid);
4001f706c6cd1cb841adadc2babc57a34e5728983ecJeff Sharkey        pw.printPair("mState", mState);
4015aca2b8dc4f4ff2d466a64587d06666c7bbd9749Jeff Sharkey        pw.decreaseIndent();
4022f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    }
4032f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood
4049545dc020ea11649d70dcbe911a8e82a3254a4eaJeff Sharkey    public static final Creator<StorageVolume> CREATOR = new Creator<StorageVolume>() {
4059545dc020ea11649d70dcbe911a8e82a3254a4eaJeff Sharkey        @Override
4062f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood        public StorageVolume createFromParcel(Parcel in) {
4079545dc020ea11649d70dcbe911a8e82a3254a4eaJeff Sharkey            return new StorageVolume(in);
4082f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood        }
4092f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood
4109545dc020ea11649d70dcbe911a8e82a3254a4eaJeff Sharkey        @Override
4112f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood        public StorageVolume[] newArray(int size) {
4122f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood            return new StorageVolume[size];
4132f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood        }
4142f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    };
4152f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood
4169545dc020ea11649d70dcbe911a8e82a3254a4eaJeff Sharkey    @Override
4172f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    public int describeContents() {
4182f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood        return 0;
4192f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    }
4202f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood
4219545dc020ea11649d70dcbe911a8e82a3254a4eaJeff Sharkey    @Override
4222f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    public void writeToParcel(Parcel parcel, int flags) {
4234887789e44cdb16b042a35e8ec03983213e88ac6Jeff Sharkey        parcel.writeString(mId);
4249545dc020ea11649d70dcbe911a8e82a3254a4eaJeff Sharkey        parcel.writeInt(mStorageId);
425b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkey        parcel.writeString(mPath.toString());
4261b8ef7e3165ff9aa52a4905dafc8d0f83e7403f9Jeff Sharkey        parcel.writeString(mDescription);
4279545dc020ea11649d70dcbe911a8e82a3254a4eaJeff Sharkey        parcel.writeInt(mPrimary ? 1 : 0);
4282f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood        parcel.writeInt(mRemovable ? 1 : 0);
4292f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood        parcel.writeInt(mEmulated ? 1 : 0);
4304887789e44cdb16b042a35e8ec03983213e88ac6Jeff Sharkey        parcel.writeLong(mMtpReserveSize);
4318e8b280bd19fa6cb69bb19e1d90cf03a47ba2d72Mike Lockwood        parcel.writeInt(mAllowMassStorage ? 1 : 0);
4327a59dd2ce33b46cbc73eef964ddb4272ea1da8d1Mike Lockwood        parcel.writeLong(mMaxFileSize);
433b049e212ab7fe8967893c202efcb30fecfdb82fbJeff Sharkey        parcel.writeParcelable(mOwner, flags);
4341b8ef7e3165ff9aa52a4905dafc8d0f83e7403f9Jeff Sharkey        parcel.writeString(mFsUuid);
4351f706c6cd1cb841adadc2babc57a34e5728983ecJeff Sharkey        parcel.writeString(mState);
4362f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood    }
4372f6a3885533a52758c2cd4f81f6123a712be8ae6Mike Lockwood}
438