/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.scopedstorage.cts.device;

import static android.app.AppOpsManager.permissionToOp;
import static android.os.ParcelFileDescriptor.MODE_CREATE;
import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
import static android.scopedstorage.cts.lib.RedactionTestHelper.assertExifMetadataMatch;
import static android.scopedstorage.cts.lib.RedactionTestHelper.assertExifMetadataMismatch;
import static android.scopedstorage.cts.lib.RedactionTestHelper.getExifMetadata;
import static android.scopedstorage.cts.lib.RedactionTestHelper.getExifMetadataFromRawResource;
import static android.scopedstorage.cts.lib.TestUtils.BYTES_DATA2;
import static android.scopedstorage.cts.lib.TestUtils.STR_DATA2;
import static android.scopedstorage.cts.lib.TestUtils.allowAppOpsToUid;
import static android.scopedstorage.cts.lib.TestUtils.assertCanRenameDirectory;
import static android.scopedstorage.cts.lib.TestUtils.assertCanRenameFile;
import static android.scopedstorage.cts.lib.TestUtils.assertCantInsertToOtherPrivateAppDirectories;
import static android.scopedstorage.cts.lib.TestUtils.assertCantRenameDirectory;
import static android.scopedstorage.cts.lib.TestUtils.assertCantRenameFile;
import static android.scopedstorage.cts.lib.TestUtils.assertCantUpdateToOtherPrivateAppDirectories;
import static android.scopedstorage.cts.lib.TestUtils.assertDirectoryContains;
import static android.scopedstorage.cts.lib.TestUtils.assertFileContent;
import static android.scopedstorage.cts.lib.TestUtils.assertMountMode;
import static android.scopedstorage.cts.lib.TestUtils.assertThrows;
import static android.scopedstorage.cts.lib.TestUtils.canOpen;
import static android.scopedstorage.cts.lib.TestUtils.canOpenFileAs;
import static android.scopedstorage.cts.lib.TestUtils.canQueryOnUri;
import static android.scopedstorage.cts.lib.TestUtils.checkPermission;
import static android.scopedstorage.cts.lib.TestUtils.createFileAs;
import static android.scopedstorage.cts.lib.TestUtils.deleteFileAs;
import static android.scopedstorage.cts.lib.TestUtils.deleteFileAsNoThrow;
import static android.scopedstorage.cts.lib.TestUtils.deleteRecursively;
import static android.scopedstorage.cts.lib.TestUtils.deleteRecursivelyAs;
import static android.scopedstorage.cts.lib.TestUtils.deleteWithMediaProvider;
import static android.scopedstorage.cts.lib.TestUtils.deleteWithMediaProviderNoThrow;
import static android.scopedstorage.cts.lib.TestUtils.denyAppOpsToUid;
import static android.scopedstorage.cts.lib.TestUtils.executeShellCommand;
import static android.scopedstorage.cts.lib.TestUtils.getAlarmsDir;
import static android.scopedstorage.cts.lib.TestUtils.getAndroidDataDir;
import static android.scopedstorage.cts.lib.TestUtils.getAndroidMediaDir;
import static android.scopedstorage.cts.lib.TestUtils.getAudiobooksDir;
import static android.scopedstorage.cts.lib.TestUtils.getContentResolver;
import static android.scopedstorage.cts.lib.TestUtils.getDcimDir;
import static android.scopedstorage.cts.lib.TestUtils.getDocumentsDir;
import static android.scopedstorage.cts.lib.TestUtils.getDownloadDir;
import static android.scopedstorage.cts.lib.TestUtils.getExternalFilesDir;
import static android.scopedstorage.cts.lib.TestUtils.getExternalMediaDir;
import static android.scopedstorage.cts.lib.TestUtils.getExternalStorageDir;
import static android.scopedstorage.cts.lib.TestUtils.getFileMimeTypeFromDatabase;
import static android.scopedstorage.cts.lib.TestUtils.getFileOwnerPackageFromDatabase;
import static android.scopedstorage.cts.lib.TestUtils.getFileRowIdFromDatabase;
import static android.scopedstorage.cts.lib.TestUtils.getFileSizeFromDatabase;
import static android.scopedstorage.cts.lib.TestUtils.getFileUri;
import static android.scopedstorage.cts.lib.TestUtils.getImageContentUri;
import static android.scopedstorage.cts.lib.TestUtils.getMoviesDir;
import static android.scopedstorage.cts.lib.TestUtils.getMusicDir;
import static android.scopedstorage.cts.lib.TestUtils.getNotificationsDir;
import static android.scopedstorage.cts.lib.TestUtils.getPicturesDir;
import static android.scopedstorage.cts.lib.TestUtils.getPodcastsDir;
import static android.scopedstorage.cts.lib.TestUtils.getRecordingsDir;
import static android.scopedstorage.cts.lib.TestUtils.getRingtonesDir;
import static android.scopedstorage.cts.lib.TestUtils.grantPermission;
import static android.scopedstorage.cts.lib.TestUtils.installApp;
import static android.scopedstorage.cts.lib.TestUtils.installAppWithStoragePermissions;
import static android.scopedstorage.cts.lib.TestUtils.isAppInstalled;
import static android.scopedstorage.cts.lib.TestUtils.listAs;
import static android.scopedstorage.cts.lib.TestUtils.openWithMediaProvider;
import static android.scopedstorage.cts.lib.TestUtils.queryFile;
import static android.scopedstorage.cts.lib.TestUtils.queryFileExcludingPending;
import static android.scopedstorage.cts.lib.TestUtils.queryImageFile;
import static android.scopedstorage.cts.lib.TestUtils.queryVideoFile;
import static android.scopedstorage.cts.lib.TestUtils.readExifMetadataFromTestApp;
import static android.scopedstorage.cts.lib.TestUtils.revokePermission;
import static android.scopedstorage.cts.lib.TestUtils.setAppOpsModeForUid;
import static android.scopedstorage.cts.lib.TestUtils.setAttrAs;
import static android.scopedstorage.cts.lib.TestUtils.trashFileAndAssert;
import static android.scopedstorage.cts.lib.TestUtils.uninstallApp;
import static android.scopedstorage.cts.lib.TestUtils.uninstallAppNoThrow;
import static android.scopedstorage.cts.lib.TestUtils.untrashFileAndAssert;
import static android.scopedstorage.cts.lib.TestUtils.updateDisplayNameWithMediaProvider;
import static android.scopedstorage.cts.lib.TestUtils.verifyInsertFromExternalMediaDirViaRelativePath_allowed;
import static android.scopedstorage.cts.lib.TestUtils.verifyInsertFromExternalPrivateDirViaRelativePath_denied;
import static android.scopedstorage.cts.lib.TestUtils.verifyUpdateToExternalMediaDirViaRelativePath_allowed;
import static android.scopedstorage.cts.lib.TestUtils.verifyUpdateToExternalPrivateDirsViaRelativePath_denied;
import static android.system.OsConstants.F_OK;
import static android.system.OsConstants.O_APPEND;
import static android.system.OsConstants.O_CREAT;
import static android.system.OsConstants.O_EXCL;
import static android.system.OsConstants.O_RDWR;
import static android.system.OsConstants.O_TRUNC;
import static android.system.OsConstants.R_OK;
import static android.system.OsConstants.S_IRWXU;
import static android.system.OsConstants.W_OK;

import static androidx.test.InstrumentationRegistry.getContext;
import static androidx.test.InstrumentationRegistry.getTargetContext;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;

import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;

import android.Manifest;
import android.app.AppOpsManager;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.pm.ProviderInfo;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.storage.StorageManager;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.system.ErrnoException;
import android.system.Os;
import android.system.StructStat;
import android.util.Log;

import androidx.annotation.Nullable;
import androidx.test.filters.SdkSuppress;

import com.android.cts.install.lib.TestApp;
import com.android.modules.utils.build.SdkLevel;

import com.google.common.io.Files;

import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

/**
 * Device-side test suite to verify scoped storage business logic.
 */
@RunWith(Parameterized.class)
public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
    public static final String STR_DATA1 = "Just some random text";

    public static final byte[] BYTES_DATA1 = STR_DATA1.getBytes();

    static final String TAG = "ScopedStorageDeviceTest";
    static final String THIS_PACKAGE_NAME = getContext().getPackageName();

    /**
     * To help avoid flaky tests, give ourselves a unique nonce to be used for
     * all filesystem paths, so that we don't risk conflicting with previous
     * test runs.
     */
    static final String NONCE = String.valueOf(System.nanoTime());

    static final String TEST_DIRECTORY_NAME = "ScopedStorageDeviceTestDirectory" + NONCE;

    static final String AUDIO_FILE_NAME = "ScopedStorageDeviceTest_file_" + NONCE + ".mp3";
    static final String PLAYLIST_FILE_NAME = "ScopedStorageDeviceTest_file_" + NONCE + ".m3u";
    static final String SUBTITLE_FILE_NAME = "ScopedStorageDeviceTest_file_" + NONCE + ".srt";
    static final String VIDEO_FILE_NAME = "ScopedStorageDeviceTest_file_" + NONCE + ".mp4";
    static final String IMAGE_FILE_NAME = "ScopedStorageDeviceTest_file_" + NONCE + ".jpg";
    static final String NONMEDIA_FILE_NAME = "ScopedStorageDeviceTest_file_" + NONCE + ".pdf";

    static final String FILE_CREATION_ERROR_MESSAGE = "No such file or directory";

    // The following apps are installed before the tests are run via a target_preparer.
    // See test config for details.
    // An app with READ_EXTERNAL_STORAGE and READ_MEDIA_* permissions
    private static final TestApp APP_A_HAS_RES =
            new TestApp(
                    "TestAppA",
                    "android.scopedstorage.cts.testapp.A.withres",
                    1,
                    false,
                    "CtsScopedStorageTestAppA.apk");
    // An app with no permissions
    private static final TestApp APP_B_NO_PERMS = new TestApp("TestAppB",
            "android.scopedstorage.cts.testapp.B.noperms", 1, false,
            "CtsScopedStorageTestAppB.apk");
    // An app that has file manager (MANAGE_EXTERNAL_STORAGE) permission.
    private static final TestApp APP_FM = new TestApp("TestAppFileManager",
            "android.scopedstorage.cts.testapp.filemanager", 1, false,
            "CtsScopedStorageTestAppFileManager.apk");
    // A legacy targeting app with RES and WES permissions
    private static final TestApp APP_D_LEGACY_HAS_RW = new TestApp("TestAppDLegacy",
            "android.scopedstorage.cts.testapp.D", 1, false, "CtsScopedStorageTestAppDLegacy.apk");

    // The following apps are not installed at test startup - please install before using.
    private static final TestApp APP_C = new TestApp("TestAppC",
            "android.scopedstorage.cts.testapp.C", 1, false, "CtsScopedStorageTestAppC.apk");
    private static final TestApp APP_C_LEGACY = new TestApp("TestAppCLegacy",
            "android.scopedstorage.cts.testapp.C", 1, false, "CtsScopedStorageTestAppCLegacy.apk");

    private static final String[] SYSTEM_GALERY_APPOPS = {
            AppOpsManager.OPSTR_WRITE_MEDIA_IMAGES, AppOpsManager.OPSTR_WRITE_MEDIA_VIDEO};
    private static final String OPSTR_MANAGE_EXTERNAL_STORAGE =
            permissionToOp(Manifest.permission.MANAGE_EXTERNAL_STORAGE);

    private static final String TRANSFORMS_DIR = ".transforms";
    private static final String TRANSFORMS_TRANSCODE_DIR = TRANSFORMS_DIR + "/" + "transcode";
    private static final String TRANSFORMS_SYNTHETIC_DIR = TRANSFORMS_DIR + "/" + "synthetic";

    @Parameter(0)
    public String mVolumeName;

    /** Parameters data. */
    @Parameters(name = "volume={0}")
    public static Iterable<? extends Object> data() {
        return ScopedStorageDeviceTest.getTestParameters();
    }

    @BeforeClass
    public static void setupApps() throws Exception {
        // File manager needs to be explicitly granted MES app op.
        final int fmUid =
                getContext().getPackageManager().getPackageUid(APP_FM.getPackageName(),
                        0);
        allowAppOpsToUid(fmUid, OPSTR_MANAGE_EXTERNAL_STORAGE);

        // Others are installed by target preparer with runtime permissions.
        // Verify.
        assertThat(checkPermission(APP_A_HAS_RES,
                Manifest.permission.READ_EXTERNAL_STORAGE)).isTrue();
        assertThat(checkPermission(APP_B_NO_PERMS,
                Manifest.permission.READ_EXTERNAL_STORAGE)).isFalse();
        assertThat(checkPermission(APP_D_LEGACY_HAS_RW,
                Manifest.permission.READ_EXTERNAL_STORAGE)).isTrue();
        assertThat(checkPermission(APP_D_LEGACY_HAS_RW,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)).isTrue();
    }

    @After
    public void tearDown() throws Exception {
        executeShellCommand("rm -r /sdcard/Android/data/com.android.shell");
    }

    @Before
    public void setupExternalStorage() {
        super.setupExternalStorage(mVolumeName);
        Log.i(TAG, "Using volume : " + mVolumeName);
    }

    /**
     * Test that we enforce certain media types can only be created in certain directories.
     */
    @Test
    public void testTypePathConformity() throws Exception {
        final File dcimDir = getDcimDir();
        final File documentsDir = getDocumentsDir();
        final File downloadDir = getDownloadDir();
        final File moviesDir = getMoviesDir();
        final File musicDir = getMusicDir();
        final File picturesDir = getPicturesDir();
        // Only audio files can be created in Music
        assertThrows(IOException.class, "Operation not permitted",
                () -> {
                    new File(musicDir, NONMEDIA_FILE_NAME).createNewFile();
                });
        assertThrows(IOException.class, "Operation not permitted",
                () -> {
                    new File(musicDir, VIDEO_FILE_NAME).createNewFile();
                });
        assertThrows(IOException.class, "Operation not permitted",
                () -> {
                    new File(musicDir, IMAGE_FILE_NAME).createNewFile();
                });
        // Only video files can be created in Movies
        assertThrows(IOException.class, "Operation not permitted",
                () -> {
                    new File(moviesDir, NONMEDIA_FILE_NAME).createNewFile();
                });
        assertThrows(IOException.class, "Operation not permitted",
                () -> {
                    new File(moviesDir, AUDIO_FILE_NAME).createNewFile();
                });
        assertThrows(IOException.class, "Operation not permitted",
                () -> {
                    new File(moviesDir, IMAGE_FILE_NAME).createNewFile();
                });
        // Only image and video files can be created in DCIM
        assertThrows(IOException.class, "Operation not permitted",
                () -> {
                    new File(dcimDir, NONMEDIA_FILE_NAME).createNewFile();
                });
        assertThrows(IOException.class, "Operation not permitted",
                () -> {
                    new File(dcimDir, AUDIO_FILE_NAME).createNewFile();
                });
        // Only image and video files can be created in Pictures
        assertThrows(IOException.class, "Operation not permitted",
                () -> {
                    new File(picturesDir, NONMEDIA_FILE_NAME).createNewFile();
                });
        assertThrows(IOException.class, "Operation not permitted",
                () -> {
                    new File(picturesDir, AUDIO_FILE_NAME).createNewFile();
                });
        assertThrows(IOException.class, "Operation not permitted",
                () -> {
                    new File(picturesDir, PLAYLIST_FILE_NAME).createNewFile();
                });
        assertThrows(IOException.class, "Operation not permitted",
                () -> {
                    new File(dcimDir, SUBTITLE_FILE_NAME).createNewFile();
                });

        assertCanCreateFile(new File(getAlarmsDir(), AUDIO_FILE_NAME));
        assertCanCreateFile(new File(getAudiobooksDir(), AUDIO_FILE_NAME));
        assertCanCreateFile(new File(dcimDir, IMAGE_FILE_NAME));
        assertCanCreateFile(new File(dcimDir, VIDEO_FILE_NAME));
        assertCanCreateFile(new File(documentsDir, AUDIO_FILE_NAME));
        assertCanCreateFile(new File(documentsDir, IMAGE_FILE_NAME));
        assertCanCreateFile(new File(documentsDir, NONMEDIA_FILE_NAME));
        assertCanCreateFile(new File(documentsDir, PLAYLIST_FILE_NAME));
        assertCanCreateFile(new File(documentsDir, SUBTITLE_FILE_NAME));
        assertCanCreateFile(new File(documentsDir, VIDEO_FILE_NAME));
        assertCanCreateFile(new File(downloadDir, AUDIO_FILE_NAME));
        assertCanCreateFile(new File(downloadDir, IMAGE_FILE_NAME));
        assertCanCreateFile(new File(downloadDir, NONMEDIA_FILE_NAME));
        assertCanCreateFile(new File(downloadDir, PLAYLIST_FILE_NAME));
        assertCanCreateFile(new File(downloadDir, SUBTITLE_FILE_NAME));
        assertCanCreateFile(new File(downloadDir, VIDEO_FILE_NAME));
        assertCanCreateFile(new File(moviesDir, VIDEO_FILE_NAME));
        assertCanCreateFile(new File(moviesDir, SUBTITLE_FILE_NAME));
        assertCanCreateFile(new File(musicDir, AUDIO_FILE_NAME));
        assertCanCreateFile(new File(musicDir, PLAYLIST_FILE_NAME));
        assertCanCreateFile(new File(getNotificationsDir(), AUDIO_FILE_NAME));
        assertCanCreateFile(new File(picturesDir, IMAGE_FILE_NAME));
        assertCanCreateFile(new File(picturesDir, VIDEO_FILE_NAME));
        assertCanCreateFile(new File(getPodcastsDir(), AUDIO_FILE_NAME));
        assertCanCreateFile(new File(getRingtonesDir(), AUDIO_FILE_NAME));

        // No file whatsoever can be created in the top level directory
        assertThrows(IOException.class, "Operation not permitted",
                () -> {
                    new File(getExternalStorageDir(), NONMEDIA_FILE_NAME).createNewFile();
                });
        assertThrows(IOException.class, "Operation not permitted",
                () -> {
                    new File(getExternalStorageDir(), AUDIO_FILE_NAME).createNewFile();
                });
        assertThrows(IOException.class, "Operation not permitted",
                () -> {
                    new File(getExternalStorageDir(), IMAGE_FILE_NAME).createNewFile();
                });
        assertThrows(IOException.class, "Operation not permitted",
                () -> {
                    new File(getExternalStorageDir(), VIDEO_FILE_NAME).createNewFile();
                });
    }

    /**
     * Test that we enforce certain media types can only be created in certain directories.
     */
    @Test
    @SdkSuppress(minSdkVersion = 31, codeName = "S")
    public void testTypePathConformity_recordingsDir() throws Exception {
        final File recordingsDir = getRecordingsDir();

        // Only audio files can be created in Recordings
        assertThrows(IOException.class, "Operation not permitted",
                () -> {
                    new File(recordingsDir, NONMEDIA_FILE_NAME).createNewFile();
                });
        assertThrows(IOException.class, "Operation not permitted",
                () -> {
                    new File(recordingsDir, VIDEO_FILE_NAME).createNewFile();
                });
        assertThrows(IOException.class, "Operation not permitted",
                () -> {
                    new File(recordingsDir, IMAGE_FILE_NAME).createNewFile();
                });

        assertCanCreateFile(new File(recordingsDir, AUDIO_FILE_NAME));
    }

    /**
     * Test that we can create a file in app's external files directory,
     * and that we can write and read to/from the file.
     */
    @Test
    public void testCreateFileInAppExternalDir() throws Exception {
        final File file = new File(getExternalFilesDir(), "text.txt");
        try {
            assertThat(file.createNewFile()).isTrue();
            assertThat(file.delete()).isTrue();
            // Ensure the file is properly deleted and can be created again
            assertThat(file.createNewFile()).isTrue();

            // Write to file
            try (FileOutputStream fos = new FileOutputStream(file)) {
                fos.write(BYTES_DATA1);
            }

            // Read the same data from file
            assertFileContent(file, BYTES_DATA1);
        } finally {
            file.delete();
        }
    }

    /**
     * Test that we can't create a file in another app's external files directory,
     * and that we'll get the same error regardless of whether the app exists or not.
     */
    @Test
    public void testCreateFileInOtherAppExternalDir() throws Exception {
        // Creating a file in a non existent package dir should return ENOENT, as expected
        final File nonexistentPackageFileDir = new File(
                getExternalFilesDir().getPath().replace(THIS_PACKAGE_NAME, "no.such.package"));
        final File file1 = new File(nonexistentPackageFileDir, NONMEDIA_FILE_NAME);
        assertThrows(
                IOException.class, FILE_CREATION_ERROR_MESSAGE, () -> {
                    file1.createNewFile();
                });

        // Creating a file in an existent package dir should give the same error string to avoid
        // leaking installed app names, and we know the following directory exists because shell
        // mkdirs it in test setup
        final File shellPackageFileDir = new File(
                getExternalFilesDir().getPath().replace(THIS_PACKAGE_NAME, "com.android.shell"));
        final File file2 = new File(shellPackageFileDir, NONMEDIA_FILE_NAME);
        assertThrows(
                IOException.class, FILE_CREATION_ERROR_MESSAGE, () -> {
                    file1.createNewFile();
                });
    }

    /**
     * Test that apps can't read/write files in another app's external files directory,
     * and can do so in their own app's external file directory.
     */
    @Test
    public void testReadWriteFilesInOtherAppExternalDir() throws Exception {
        final File videoFile = new File(getExternalFilesDir(), VIDEO_FILE_NAME);

        try {
            // Create a file in app's external files directory
            if (!videoFile.exists()) {
                assertThat(videoFile.createNewFile()).isTrue();
            }

            // App A should not be able to read/write to other app's external files directory.
            assertThat(canOpenFileAs(APP_A_HAS_RES, videoFile, false /* forWrite */)).isFalse();
            assertThat(canOpenFileAs(APP_A_HAS_RES, videoFile, true /* forWrite */)).isFalse();
            // App A should not be able to delete files in other app's external files
            // directory.
            assertThat(deleteFileAs(APP_A_HAS_RES, videoFile.getPath())).isFalse();

            // Apps should have read/write access in their own app's external files directory.
            assertThat(canOpen(videoFile, false /* forWrite */)).isTrue();
            assertThat(canOpen(videoFile, true /* forWrite */)).isTrue();
            // Apps should be able to delete files in their own app's external files directory.
            assertThat(videoFile.delete()).isTrue();
        } finally {
            videoFile.delete();
        }
    }

    /**
     * Test that we can contribute media without any permissions.
     */
    @Test
    public void testContributeMediaFile() throws Exception {
        final File imageFile = new File(getDcimDir(), IMAGE_FILE_NAME);

        try {
            assertThat(imageFile.createNewFile()).isTrue();

            // Ensure that the file was successfully added to the MediaProvider database
            assertThat(getFileOwnerPackageFromDatabase(imageFile)).isEqualTo(THIS_PACKAGE_NAME);

            // Try to write random data to the file
            try (FileOutputStream fos = new FileOutputStream(imageFile)) {
                fos.write(BYTES_DATA1);
                fos.write(BYTES_DATA2);
            }

            final byte[] expected = (STR_DATA1 + STR_DATA2).getBytes();
            assertFileContent(imageFile, expected);

            // Closing the file after writing will not trigger a MediaScan. Call scanFile to update
            // file's entry in MediaProvider's database.
            assertThat(MediaStore.scanFile(getContentResolver(), imageFile)).isNotNull();

            // Ensure that the scan was completed and the file's size was updated.
            assertThat(getFileSizeFromDatabase(imageFile)).isEqualTo(
                    BYTES_DATA1.length + BYTES_DATA2.length);
        } finally {
            imageFile.delete();
        }
        // Ensure that delete makes a call to MediaProvider to remove the file from its database.
        assertThat(getFileRowIdFromDatabase(imageFile)).isEqualTo(-1);
    }

    @Test
    public void testCreateAndDeleteEmptyDir() throws Exception {
        final File externalFilesDir = getExternalFilesDir();
        // Remove directory in order to create it again
        deleteRecursively(externalFilesDir);

        // Can create own external files dir
        assertThat(externalFilesDir.mkdir()).isTrue();

        final File dir1 = new File(externalFilesDir, "random_dir");
        // Can create dirs inside it
        assertThat(dir1.mkdir()).isTrue();

        final File dir2 = new File(dir1, "random_dir_inside_random_dir");
        // And create a dir inside the new dir
        assertThat(dir2.mkdir()).isTrue();

        // And can delete them all
        assertThat(deleteRecursively(dir2)).isTrue();
        assertThat(deleteRecursively(dir1)).isTrue();
        assertThat(deleteRecursively(externalFilesDir)).isTrue();

        // Can't create external dir for other apps
        final File nonexistentPackageFileDir = new File(
                externalFilesDir.getPath().replace(THIS_PACKAGE_NAME, "no.such.package"));
        final File shellPackageFileDir = new File(
                externalFilesDir.getPath().replace(THIS_PACKAGE_NAME, "com.android.shell"));

        assertThat(nonexistentPackageFileDir.mkdir()).isFalse();
        assertThat(shellPackageFileDir.mkdir()).isFalse();
    }

    @Test
    public void testCantAccessOtherAppsContents() throws Exception {
        final File mediaFile = new File(getPicturesDir(), IMAGE_FILE_NAME);
        final File nonMediaFile = new File(getDownloadDir(), NONMEDIA_FILE_NAME);
        try {
            assertThat(createFileAs(APP_B_NO_PERMS, mediaFile.getPath())).isTrue();
            assertThat(createFileAs(APP_B_NO_PERMS, nonMediaFile.getPath())).isTrue();

            // We can still see that the files exist
            assertThat(mediaFile.exists()).isTrue();
            assertThat(nonMediaFile.exists()).isTrue();

            // But we can't access their content
            assertThat(canOpen(mediaFile, /* forWrite */ false)).isFalse();
            assertThat(canOpen(nonMediaFile, /* forWrite */ true)).isFalse();
            assertThat(canOpen(mediaFile, /* forWrite */ false)).isFalse();
            assertThat(canOpen(nonMediaFile, /* forWrite */ true)).isFalse();
        } finally {
            deleteFileAsNoThrow(APP_B_NO_PERMS, nonMediaFile.getPath());
            deleteFileAsNoThrow(APP_B_NO_PERMS, mediaFile.getPath());
        }
    }

    @Test
    public void testCantDeleteOtherAppsContents() throws Exception {
        final File dirInDownload = new File(getDownloadDir(), TEST_DIRECTORY_NAME);
        final File mediaFile = new File(dirInDownload, IMAGE_FILE_NAME);
        final File nonMediaFile = new File(dirInDownload, NONMEDIA_FILE_NAME);
        try {
            assertThat(dirInDownload.mkdir()).isTrue();
            // Have another app create a media file in the directory
            assertThat(createFileAs(APP_B_NO_PERMS, mediaFile.getPath())).isTrue();

            // Can't delete the directory since it contains another app's content
            assertThat(dirInDownload.delete()).isFalse();
            // Can't delete another app's content
            assertThat(deleteRecursively(dirInDownload)).isFalse();

            // Have another app create a non-media file in the directory
            assertThat(createFileAs(APP_B_NO_PERMS, nonMediaFile.getPath())).isTrue();

            // Can't delete the directory since it contains another app's content
            assertThat(dirInDownload.delete()).isFalse();
            // Can't delete another app's content
            assertThat(deleteRecursively(dirInDownload)).isFalse();

            // Delete only the media file and keep the non-media file
            assertThat(deleteFileAs(APP_B_NO_PERMS, mediaFile.getPath())).isTrue();
            // Directory now has only the non-media file contributed by another app, so we still
            // can't delete it nor its content
            assertThat(dirInDownload.delete()).isFalse();
            assertThat(deleteRecursively(dirInDownload)).isFalse();

            // Delete the last file belonging to another app
            assertThat(deleteFileAs(APP_B_NO_PERMS, nonMediaFile.getPath())).isTrue();
            // Create our own file
            assertThat(nonMediaFile.createNewFile()).isTrue();

            // Now that the directory only has content that was contributed by us, we can delete it
            assertThat(deleteRecursively(dirInDownload)).isTrue();
        } finally {
            deleteFileAsNoThrow(APP_B_NO_PERMS, nonMediaFile.getPath());
            deleteFileAsNoThrow(APP_B_NO_PERMS, mediaFile.getPath());
            // At this point, we're not sure who created this file, so we'll have both apps
            // deleting it
            mediaFile.delete();
            deleteRecursively(dirInDownload);
        }
    }

    /**
     * Test that deleting uri corresponding to a file which was already deleted via filePath
     * doesn't result in a security exception.
     */
    @Test
    public void testDeleteAlreadyUnlinkedFile() throws Exception {
        final File nonMediaFile = new File(getDownloadDir(), NONMEDIA_FILE_NAME);
        try {
            assertTrue(nonMediaFile.createNewFile());
            final Uri uri = MediaStore.scanFile(getContentResolver(), nonMediaFile);
            assertNotNull(uri);

            // Delete the file via filePath
            assertTrue(nonMediaFile.delete());

            // If we delete nonMediaFile with ContentResolver#delete, it shouldn't result in a
            // security exception.
            assertThat(getContentResolver().delete(uri, Bundle.EMPTY)).isEqualTo(0);
        } finally {
            nonMediaFile.delete();
        }
    }

    /**
     * This test relies on the fact that {@link File#list} uses opendir internally, and that it
     * returns {@code null} if opendir fails.
     */
    @Test
    public void testOpendirRestrictions() throws Exception {
        // Opening a non existent package directory should fail, as expected
        final File nonexistentPackageFileDir = new File(
                getExternalFilesDir().getPath().replace(THIS_PACKAGE_NAME, "no.such.package"));
        assertThat(nonexistentPackageFileDir.list()).isNull();

        // Opening another package's external directory should fail as well, even if it exists
        final File shellPackageFileDir = new File(
                getExternalFilesDir().getPath().replace(THIS_PACKAGE_NAME, "com.android.shell"));
        assertThat(shellPackageFileDir.list()).isNull();

        // We can open our own external files directory
        final String[] filesList = getExternalFilesDir().list();
        assertThat(filesList).isNotNull();

        // We can open any public directory in external storage
        assertThat(getDcimDir().list()).isNotNull();
        assertThat(getDownloadDir().list()).isNotNull();
        assertThat(getMoviesDir().list()).isNotNull();
        assertThat(getMusicDir().list()).isNotNull();

        // We can open the root directory of external storage
        final String[] topLevelDirs = getExternalStorageDir().list();
        assertThat(topLevelDirs).isNotNull();
        // TODO(b/145287327): This check fails on a device with no visible files.
        // This can be fixed if we display default directories.
        // assertThat(topLevelDirs).isNotEmpty();
    }

    @Test
    public void testLowLevelFileIO() throws Exception {
        String filePath = new File(getDownloadDir(), NONMEDIA_FILE_NAME).toString();
        try {
            int createFlags = O_CREAT | O_RDWR;
            int createExclFlags = createFlags | O_EXCL;

            FileDescriptor fd = Os.open(filePath, createExclFlags, S_IRWXU);
            Os.close(fd);
            assertThrows(
                    ErrnoException.class, () -> {
                        Os.open(filePath, createExclFlags, S_IRWXU);
                    });

            fd = Os.open(filePath, createFlags, S_IRWXU);
            try {
                assertThat(Os.write(fd,
                        ByteBuffer.wrap(BYTES_DATA1))).isEqualTo(BYTES_DATA1.length);
                assertFileContent(fd, BYTES_DATA1);
            } finally {
                Os.close(fd);
            }
            // should just append the data
            fd = Os.open(filePath, createFlags | O_APPEND, S_IRWXU);
            try {
                assertThat(Os.write(fd,
                        ByteBuffer.wrap(BYTES_DATA2))).isEqualTo(BYTES_DATA2.length);
                final byte[] expected = (STR_DATA1 + STR_DATA2).getBytes();
                assertFileContent(fd, expected);
            } finally {
                Os.close(fd);
            }
            // should overwrite everything
            fd = Os.open(filePath, createFlags | O_TRUNC, S_IRWXU);
            try {
                final byte[] otherData = "this is different data".getBytes();
                assertThat(Os.write(fd, ByteBuffer.wrap(otherData))).isEqualTo(otherData.length);
                assertFileContent(fd, otherData);
            } finally {
                Os.close(fd);
            }
        } finally {
            new File(filePath).delete();
        }
    }

    /**
     * Test that media files from other packages are only visible to apps with storage permission.
     */
    @Test
    public void testListDirectoriesWithMediaFiles() throws Exception {
        final File dcimDir = getDcimDir();
        final File dir = new File(dcimDir, TEST_DIRECTORY_NAME);
        final File videoFile = new File(dir, VIDEO_FILE_NAME);
        final String videoFileName = videoFile.getName();
        try {
            if (!dir.exists()) {
                assertThat(dir.mkdir()).isTrue();
            }

            assertThat(createFileAs(APP_B_NO_PERMS, videoFile.getPath())).isTrue();
            // App B should see TEST_DIRECTORY in DCIM and new file in TEST_DIRECTORY.
            assertThat(listAs(APP_B_NO_PERMS, dcimDir.getPath())).contains(TEST_DIRECTORY_NAME);
            assertThat(listAs(APP_B_NO_PERMS, dir.getPath())).containsExactly(videoFileName);

            // App A has storage permission, so should see TEST_DIRECTORY in DCIM and new file
            // in TEST_DIRECTORY.
            assertThat(listAs(APP_A_HAS_RES, dcimDir.getPath())).contains(TEST_DIRECTORY_NAME);
            assertThat(listAs(APP_A_HAS_RES, dir.getPath())).containsExactly(videoFileName);

            // We are an app without storage permission; should see TEST_DIRECTORY in DCIM and
            // should not see new file in new TEST_DIRECTORY.
            assertThat(dcimDir.list()).asList().contains(TEST_DIRECTORY_NAME);
            assertThat(dir.list()).asList().doesNotContain(videoFileName);
        } finally {
            deleteFileAsNoThrow(APP_B_NO_PERMS, videoFile.getPath());
            deleteRecursively(dir);
        }
    }

    /**
     * Test that app can't see non-media files created by other packages
     */
    @Test
    public void testListDirectoriesWithNonMediaFiles() throws Exception {
        final File downloadDir = getDownloadDir();
        final File dir = new File(downloadDir, TEST_DIRECTORY_NAME);
        final File pdfFile = new File(dir, NONMEDIA_FILE_NAME);
        final String pdfFileName = pdfFile.getName();
        try {
            if (!dir.exists()) {
                assertThat(dir.mkdir()).isTrue();
            }

            // Have App B create non media file in the new directory.
            assertThat(createFileAs(APP_B_NO_PERMS, pdfFile.getPath())).isTrue();

            // App B should see TEST_DIRECTORY in downloadDir and new non media file in
            // TEST_DIRECTORY.
            assertThat(listAs(APP_B_NO_PERMS, downloadDir.getPath())).contains(TEST_DIRECTORY_NAME);
            assertThat(listAs(APP_B_NO_PERMS, dir.getPath())).containsExactly(pdfFileName);

            // APP A with storage permission should see TEST_DIRECTORY in downloadDir
            // and should not see non media file in TEST_DIRECTORY.
            assertThat(listAs(APP_A_HAS_RES, downloadDir.getPath())).contains(TEST_DIRECTORY_NAME);
            assertThat(listAs(APP_A_HAS_RES, dir.getPath())).doesNotContain(pdfFileName);
        } finally {
            deleteFileAsNoThrow(APP_B_NO_PERMS, pdfFile.getPath());
            deleteRecursively(dir);
        }
    }

    /**
     * Test that app can only see its directory in Android/data.
     */
    @Test
    public void testListFilesFromExternalFilesDirectory() throws Exception {
        final String packageName = THIS_PACKAGE_NAME;
        final File nonmediaFile = new File(getExternalFilesDir(), NONMEDIA_FILE_NAME);

        try {
            // Create a file in app's external files directory
            if (!nonmediaFile.exists()) {
                assertThat(nonmediaFile.createNewFile()).isTrue();
            }
            // App should see its directory and directories of shared packages. App should see all
            // files and directories in its external directory.
            assertDirectoryContains(nonmediaFile.getParentFile(), nonmediaFile);

            // App A should not see other app's external files directory despite RES.
            assertThrows(IOException.class,
                    () -> listAs(APP_A_HAS_RES, getAndroidDataDir().getPath()));
            assertThrows(IOException.class,
                    () -> listAs(APP_A_HAS_RES, getExternalFilesDir().getPath()));
        } finally {
            nonmediaFile.delete();
        }
    }

    /**
     * Test that app can see files and directories in Android/media.
     */
    @Test
    public void testListFilesFromExternalMediaDirectory() throws Exception {
        final File videoFile = new File(getExternalMediaDir(), VIDEO_FILE_NAME);

        try {
            // Create a file in app's external media directory
            if (!videoFile.exists()) {
                assertThat(videoFile.createNewFile()).isTrue();
            }

            // App should see its directory and other app's external media directories with media
            // files.
            assertDirectoryContains(videoFile.getParentFile(), videoFile);

            // App A with storage permission should see other app's external media directory.
            // Apps with READ_EXTERNAL_STORAGE can list files in other app's external media
            // directory.
            assertThat(listAs(APP_A_HAS_RES, getAndroidMediaDir().getPath()))
                    .contains(THIS_PACKAGE_NAME);
            assertThat(listAs(APP_A_HAS_RES, getExternalMediaDir().getPath()))
                    .containsExactly(videoFile.getName());
        } finally {
            videoFile.delete();
        }
    }

    @Test
    public void testMetaDataRedaction() throws Exception {
        File jpgFile = new File(getPicturesDir(), "img_metadata.jpg");
        try {
            if (jpgFile.exists()) {
                assertThat(jpgFile.delete()).isTrue();
            }

            HashMap<String, String> originalExif =
                    getExifMetadataFromRawResource(R.raw.img_with_metadata);

            try (InputStream in =
                         getContext().getResources().openRawResource(R.raw.img_with_metadata);
                FileOutputStream out = new FileOutputStream(jpgFile)) {
                // Dump the image we have to external storage
                FileUtils.copy(in, out);
                // Sync file to disk to ensure file is fully written to the lower fs attempting to
                // open for redaction. Otherwise, the FUSE daemon might not accurately parse the
                // EXIF tags and might misleadingly think there are not tags to redact
                out.getFD().sync();

                HashMap<String, String> exif = getExifMetadata(jpgFile);
                assertExifMetadataMatch(exif, originalExif);

                HashMap<String, String> exifFromTestApp =
                        readExifMetadataFromTestApp(APP_A_HAS_RES, jpgFile.getPath());
                // App does not have AML; shouldn't have access to the same metadata.
                assertExifMetadataMismatch(exifFromTestApp, originalExif);

                // TODO(b/146346138): Test that if we give APP_A write URI permission,
                //  it would be able to access the metadata.
            } // Intentionally keep the original streams open during the test so bytes are more
            // likely to be in the VFS cache from both file opens
        } finally {
            jpgFile.delete();
        }
    }

    @Test
    public void testOpenFilePathFirstWriteContentResolver() throws Exception {
        String displayName = "open_file_path_write_content_resolver.jpg";
        File file = new File(getDcimDir(), displayName);

        try {
            assertThat(file.createNewFile()).isTrue();

            try (ParcelFileDescriptor readPfd = ParcelFileDescriptor.open(file, MODE_READ_WRITE);
                 ParcelFileDescriptor writePfd = openWithMediaProvider(file, "rw")) {
                assertRWR(readPfd, writePfd);
                assertUpperFsFd(writePfd); // With cache
            }
        } finally {
            file.delete();
        }
    }

    @Test
    public void testOpenContentResolverFirstWriteContentResolver() throws Exception {
        String displayName = "open_content_resolver_write_content_resolver.jpg";
        File file = new File(getDcimDir(), displayName);

        try {
            assertThat(file.createNewFile()).isTrue();

            try (ParcelFileDescriptor writePfd = openWithMediaProvider(file, "rw");
                 ParcelFileDescriptor readPfd = ParcelFileDescriptor.open(file, MODE_READ_WRITE)) {
                assertRWR(readPfd, writePfd);
                assertLowerFsFdWithPassthrough(file.getPath(), writePfd);
            }
        } finally {
            file.delete();
        }
    }

    @Test
    public void testOpenFilePathFirstWriteFilePath() throws Exception {
        String displayName = "open_file_path_write_file_path.jpg";
        File file = new File(getDcimDir(), displayName);

        try {
            assertThat(file.createNewFile()).isTrue();

            try (ParcelFileDescriptor writePfd = ParcelFileDescriptor.open(file, MODE_READ_WRITE);
                 ParcelFileDescriptor readPfd = openWithMediaProvider(file, "rw")) {
                assertRWR(readPfd, writePfd);
                assertUpperFsFd(readPfd); // With cache
            }
        } finally {
            file.delete();
        }
    }

    @Test
    public void testOpenContentResolverFirstWriteFilePath() throws Exception {
        String displayName = "open_content_resolver_write_file_path.jpg";
        File file = new File(getDcimDir(), displayName);

        try {
            assertThat(file.createNewFile()).isTrue();

            try (ParcelFileDescriptor readPfd = openWithMediaProvider(file, "rw");
                 ParcelFileDescriptor writePfd = ParcelFileDescriptor.open(file, MODE_READ_WRITE)) {
                assertRWR(readPfd, writePfd);
                assertLowerFsFdWithPassthrough(file.getPath(), readPfd);
            }
        } finally {
            file.delete();
        }
    }

    @Test
    public void testOpenContentResolverWriteOnly() throws Exception {
        String displayName = "open_content_resolver_write_only.jpg";
        File file = new File(getDcimDir(), displayName);

        try {
            assertThat(file.createNewFile()).isTrue();

            // We upgrade 'w' only to 'rw'
            try (ParcelFileDescriptor writePfd = openWithMediaProvider(file, "w");
                 ParcelFileDescriptor readPfd = openWithMediaProvider(file, "rw")) {
                assertRWR(readPfd, writePfd);
                assertRWR(writePfd, readPfd); // Can read on 'w' only pfd
                assertLowerFsFdWithPassthrough(file.getPath(), writePfd);
                assertLowerFsFdWithPassthrough(file.getPath(), readPfd);
            }
        } finally {
            file.delete();
        }
    }

    @Test
    public void testOpenContentResolverDup() throws Exception {
        String displayName = "open_content_resolver_dup.jpg";
        File file = new File(getDcimDir(), displayName);

        try {
            file.delete();
            assertThat(file.createNewFile()).isTrue();

            // Even if we close the original fd, since we have a dup open
            // the FUSE IO should still bypass the cache
            try (ParcelFileDescriptor writePfd = openWithMediaProvider(file, "rw");
                 ParcelFileDescriptor writePfdDup = writePfd.dup();
                 ParcelFileDescriptor readPfd = ParcelFileDescriptor.open(file, MODE_READ_WRITE)) {
                writePfd.close();

                assertRWR(readPfd, writePfdDup);
                assertLowerFsFdWithPassthrough(file.getPath(), writePfdDup);
            }
        } finally {
            file.delete();
        }
    }

    @Test
    public void testOpenContentResolverClose() throws Exception {
        String displayName = "open_content_resolver_close.jpg";
        File file = new File(getDcimDir(), displayName);

        try {
            byte[] readBuffer = new byte[10];
            byte[] writeBuffer = new byte[10];
            Arrays.fill(writeBuffer, (byte) 1);

            assertThat(file.createNewFile()).isTrue();

            // Lower fs open and write
            ParcelFileDescriptor writePfd = openWithMediaProvider(file, "rw");
            Os.pwrite(writePfd.getFileDescriptor(), writeBuffer, 0, 10, 0);

            // Close so upper fs open will not use direct_io
            writePfd.close();

            // Upper fs open and read without direct_io
            try (ParcelFileDescriptor readPfd = ParcelFileDescriptor.open(file, MODE_READ_WRITE)) {
                Os.pread(readPfd.getFileDescriptor(), readBuffer, 0, 10, 0);

                // Last write on lower fs is visible via upper fs
                assertThat(readBuffer).isEqualTo(writeBuffer);
                assertThat(readPfd.getStatSize()).isEqualTo(writeBuffer.length);
            }
        } finally {
            file.delete();
        }
    }

    @Test
    public void testContentResolverDelete() throws Exception {
        String displayName = "content_resolver_delete.jpg";
        File file = new File(getDcimDir(), displayName);

        try {
            assertThat(file.createNewFile()).isTrue();

            deleteWithMediaProvider(file);

            assertThat(file.exists()).isFalse();
            assertThat(file.createNewFile()).isTrue();
        } finally {
            file.delete();
        }
    }

    @Test
    public void testContentResolverUpdate() throws Exception {
        String oldDisplayName = "content_resolver_update_old.jpg";
        String newDisplayName = "content_resolver_update_new.jpg";
        File oldFile = new File(getDcimDir(), oldDisplayName);
        File newFile = new File(getDcimDir(), newDisplayName);

        try {
            assertThat(oldFile.createNewFile()).isTrue();
            // Publish the pending oldFile before updating with MediaProvider. Not publishing the
            // file will make MP consider pending from FUSE as explicit IS_PENDING
            final Uri uri = MediaStore.scanFile(getContentResolver(), oldFile);
            assertNotNull(uri);

            updateDisplayNameWithMediaProvider(uri,
                    Environment.DIRECTORY_DCIM, oldDisplayName, newDisplayName);

            assertThat(oldFile.exists()).isFalse();
            assertThat(oldFile.createNewFile()).isTrue();
            assertThat(newFile.exists()).isTrue();
            assertThat(newFile.createNewFile()).isFalse();
        } finally {
            oldFile.delete();
            newFile.delete();
        }
    }

    void writeAndCheckMtime(final boolean append) throws Exception {
        File file = new File(getDcimDir(), "update_modifies_mtime.jpg");

        try {
            assertThat(file.createNewFile()).isTrue();
            assertThat(file.exists()).isTrue();

            final long creationTime = file.lastModified();

            // File should exist
            assertNotEquals(creationTime, 0L);

            // Sleep a bit more than 1 second because although
            // File::lastModified() represents the duration in milliseconds,
            // has 1 second precision.
            // With lower sleep durations the test results flakey...
            Thread.sleep(2000);

            // Modification time should be the same as long the file has not
            // been modified
            assertEquals(creationTime, file.lastModified());

            // Sleep a bit more than 1 second because although
            // File::lastModified() represents the duration in milliseconds,
            // has 1 second precision.
            // With lower sleep durations the test results flakey...
            Thread.sleep(2000);

            // Assert we can write to the file
            try (FileOutputStream fos = new FileOutputStream(file, append)) {
                fos.write(BYTES_DATA1);
                fos.close();
            }

            final long modificationTime = file.lastModified();

            // As the file has been written, modification time should have
            // changed
            assertNotEquals(modificationTime, 0L);
            assertNotEquals(modificationTime, creationTime);
        } finally {
            file.delete();
        }
    }

    @Test
    public void testAppendUpdatesMtime() throws Exception {
        writeAndCheckMtime(true);
    }

    @Test
    public void testWriteUpdatesMtime() throws Exception {
        writeAndCheckMtime(false);
    }

    @Test
    @SdkSuppress(minSdkVersion = 31, codeName = "S")
    public void testDefaultNoIsolatedStorageFlag() throws Exception {
        assertThat(Environment.isExternalStorageLegacy()).isFalse();
    }

    @Test
    public void testCreateLowerCaseDeleteUpperCase() throws Exception {
        File upperCase = new File(getDownloadDir(), "CREATE_LOWER_DELETE_UPPER");
        File lowerCase = new File(getDownloadDir(), "create_lower_delete_upper");

        createDeleteCreate(lowerCase, upperCase);
    }

    @Test
    public void testCreateUpperCaseDeleteLowerCase() throws Exception {
        File upperCase = new File(getDownloadDir(), "CREATE_UPPER_DELETE_LOWER");
        File lowerCase = new File(getDownloadDir(), "create_upper_delete_lower");

        createDeleteCreate(upperCase, lowerCase);
    }

    @Test
    public void testCreateMixedCaseDeleteDifferentMixedCase() throws Exception {
        File mixedCase1 = new File(getDownloadDir(), "CrEaTe_MiXeD_dElEtE_mIxEd");
        File mixedCase2 = new File(getDownloadDir(), "cReAtE_mIxEd_DeLeTe_MiXeD");

        createDeleteCreate(mixedCase1, mixedCase2);
    }

    @Test
    public void testAndroidDataObbDoesNotForgetMount() throws Exception {
        File dataDir = getContext().getExternalFilesDir(null);
        File upperCaseDataDir = new File(dataDir.getPath().replace("Android/data", "ANDROID/DATA"));

        File obbDir = getContext().getObbDir();
        File upperCaseObbDir = new File(obbDir.getPath().replace("Android/obb", "ANDROID/OBB"));


        StructStat beforeDataStruct = Os.stat(dataDir.getPath());
        StructStat beforeObbStruct = Os.stat(obbDir.getPath());

        assertThat(dataDir.exists()).isTrue();
        assertThat(upperCaseDataDir.exists()).isTrue();
        assertThat(obbDir.exists()).isTrue();
        assertThat(upperCaseObbDir.exists()).isTrue();

        StructStat afterDataStruct = Os.stat(upperCaseDataDir.getPath());
        StructStat afterObbStruct = Os.stat(upperCaseObbDir.getPath());

        assertThat(beforeDataStruct.st_dev).isEqualTo(afterDataStruct.st_dev);
        assertThat(beforeObbStruct.st_dev).isEqualTo(afterObbStruct.st_dev);
    }

    @Test
    public void testCacheConsistencyForCaseInsensitivity() throws Exception {
        File upperCaseFile = new File(getDownloadDir(), "CACHE_CONSISTENCY_FOR_CASE_INSENSITIVITY");
        File lowerCaseFile = new File(getDownloadDir(), "cache_consistency_for_case_insensitivity");

        try {
            ParcelFileDescriptor upperCasePfd =
                    ParcelFileDescriptor.open(upperCaseFile, MODE_READ_WRITE | MODE_CREATE);
            ParcelFileDescriptor lowerCasePfd =
                    ParcelFileDescriptor.open(lowerCaseFile, MODE_READ_WRITE | MODE_CREATE);

            assertRWR(upperCasePfd, lowerCasePfd);
            assertRWR(lowerCasePfd, upperCasePfd);
        } finally {
            upperCaseFile.delete();
            lowerCaseFile.delete();
        }
    }

    @Test
    public void testInsertDefaultPrimaryCaseInsensitiveCheck() throws Exception {
        final File podcastsDir = getPodcastsDir();
        final File podcastsDirLowerCase =
                new File(getExternalStorageDir(), Environment.DIRECTORY_PODCASTS.toLowerCase());
        final File fileInPodcastsDirLowerCase = new File(podcastsDirLowerCase, AUDIO_FILE_NAME);
        try {
            // Delete the directory if it already exists
            if (podcastsDir.exists()) {
                deleteRecursivelyAsLegacyApp(podcastsDir);
            }
            assertThat(podcastsDir.exists()).isFalse();
            assertThat(podcastsDirLowerCase.exists()).isFalse();

            // Create the directory with lower case
            assertThat(podcastsDirLowerCase.mkdir()).isTrue();
            // Because of case-insensitivity, even though directory is created
            // with lower case, we should be able to see both directory names.
            assertThat(podcastsDirLowerCase.exists()).isTrue();
            assertThat(podcastsDir.exists()).isTrue();

            // File creation with lower case path of podcasts directory should not fail
            assertThat(fileInPodcastsDirLowerCase.createNewFile()).isTrue();
        } finally {
            fileInPodcastsDirLowerCase.delete();
            deleteAsLegacyApp(podcastsDirLowerCase);
            podcastsDir.mkdirs();
        }
    }

    private void createDeleteCreate(File create, File delete) throws Exception {
        try {
            assertThat(create.createNewFile()).isTrue();
            // Wait for the kernel to update the dentry cache.
            Thread.sleep(100);

            assertThat(delete.delete()).isTrue();
            // Wait for the kernel to clean up the dentry cache.
            Thread.sleep(100);

            assertThat(create.createNewFile()).isTrue();
            // Wait for the kernel to update the dentry cache.
            Thread.sleep(100);
        } finally {
            create.delete();
            delete.delete();
        }
    }

    @Test
    public void testReadStorageInvalidation() throws Exception {
        if (SdkLevel.isAtLeastT()) {
            testAppOpInvalidation(
                APP_C,
                new File(getDcimDir(), "read_storage.jpg"),
                Manifest.permission.READ_MEDIA_IMAGES,
                AppOpsManager.OPSTR_READ_MEDIA_IMAGES,
                /* forWrite */ false);
        } else {
            testAppOpInvalidation(APP_C, new File(getDcimDir(), "read_storage.jpg"),
                Manifest.permission.READ_EXTERNAL_STORAGE,
                AppOpsManager.OPSTR_READ_EXTERNAL_STORAGE, /* forWrite */ false);
        }
    }

    @Test
    public void testWriteStorageInvalidation() throws Exception {
        testAppOpInvalidation(APP_C_LEGACY, new File(getDcimDir(), "write_storage.jpg"),
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                AppOpsManager.OPSTR_WRITE_EXTERNAL_STORAGE, /* forWrite */ true);
    }

    @Test
    public void testManageStorageInvalidation() throws Exception {
        testAppOpInvalidation(APP_C, new File(getDownloadDir(), "manage_storage.pdf"),
                /* permission */ null, OPSTR_MANAGE_EXTERNAL_STORAGE, /* forWrite */ true);
    }

    @Test
    public void testWriteImagesInvalidation() throws Exception {
        testAppOpInvalidation(APP_C, new File(getDcimDir(), "write_images.jpg"),
                /* permission */ null, AppOpsManager.OPSTR_WRITE_MEDIA_IMAGES, /* forWrite */ true);
    }

    @Test
    public void testWriteVideoInvalidation() throws Exception {
        testAppOpInvalidation(APP_C, new File(getDcimDir(), "write_video.mp4"),
                /* permission */ null, AppOpsManager.OPSTR_WRITE_MEDIA_VIDEO, /* forWrite */ true);
    }

    @Test
    public void testAccessMediaLocationInvalidation() throws Exception {
        File imgFile = new File(getDcimDir(), "access_media_location.jpg");

        try {
            // Setup image with sensitive data on external storage
            HashMap<String, String> originalExif =
                    getExifMetadataFromRawResource(R.raw.img_with_metadata);
            try (InputStream in =
                         getContext().getResources().openRawResource(R.raw.img_with_metadata);
                FileOutputStream out = new FileOutputStream(imgFile)) {
                // Dump the image we have to external storage
                FileUtils.copy(in, out);
                // Sync file to disk to ensure file is fully written to the lower fs.
                out.getFD().sync();
            }
            HashMap<String, String> exif = getExifMetadata(imgFile);
            assertExifMetadataMatch(exif, originalExif);

            // Install test app
            installAppWithStoragePermissions(APP_C);

            // Grant A_M_L and verify access to sensitive data
            grantPermission(APP_C.getPackageName(), Manifest.permission.ACCESS_MEDIA_LOCATION);
            HashMap<String, String> exifFromTestApp =
                    readExifMetadataFromTestApp(APP_C, imgFile.getPath());
            assertExifMetadataMatch(exifFromTestApp, originalExif);

            // Revoke A_M_L and verify sensitive data redaction
            revokePermission(
                    APP_C.getPackageName(), Manifest.permission.ACCESS_MEDIA_LOCATION);
            // revokePermission waits for permission status to be updated, but MediaProvider still
            // needs to get permission change callback and clear its permission cache.
            Thread.sleep(500);
            exifFromTestApp = readExifMetadataFromTestApp(APP_C, imgFile.getPath());
            assertExifMetadataMismatch(exifFromTestApp, originalExif);

            // Re-grant A_M_L and verify access to sensitive data
            grantPermission(APP_C.getPackageName(), Manifest.permission.ACCESS_MEDIA_LOCATION);
            // grantPermission waits for permission status to be updated, but MediaProvider still
            // needs to get permission change callback and clear its permission cache.
            Thread.sleep(500);
            exifFromTestApp = readExifMetadataFromTestApp(APP_C, imgFile.getPath());
            assertExifMetadataMatch(exifFromTestApp, originalExif);
        } finally {
            imgFile.delete();
            uninstallAppNoThrow(APP_C);
        }
    }

    @Test
    public void testAppUpdateInvalidation() throws Exception {
        File file = new File(getDcimDir(), "app_update.jpg");
        try {
            assertThat(file.createNewFile()).isTrue();

            // Install legacy
            installAppWithStoragePermissions(APP_C_LEGACY);
            grantPermission(APP_C_LEGACY.getPackageName(),
                    Manifest.permission.WRITE_EXTERNAL_STORAGE); // Grants write access for legacy

            // Legacy app can read and write media files contributed by others
            assertThat(canOpenFileAs(APP_C_LEGACY, file, /* forWrite */ false)).isTrue();
            assertThat(canOpenFileAs(APP_C_LEGACY, file, /* forWrite */ true)).isTrue();

            // Update to non-legacy
            installAppWithStoragePermissions(APP_C);
            grantPermission(APP_C_LEGACY.getPackageName(),
                    Manifest.permission.WRITE_EXTERNAL_STORAGE); // No effect for non-legacy

            // Non-legacy app can read media files contributed by others
            assertThat(canOpenFileAs(APP_C, file, /* forWrite */ false)).isTrue();
            // But cannot write
            assertThat(canOpenFileAs(APP_C, file, /* forWrite */ true)).isFalse();
        } finally {
            file.delete();
            uninstallAppNoThrow(APP_C);
        }
    }

    @Test
    public void testAppReinstallInvalidation() throws Exception {
        File file = new File(getDcimDir(), "app_reinstall.jpg");

        try {
            assertThat(file.createNewFile()).isTrue();

            // Install
            installAppWithStoragePermissions(APP_C);
            assertThat(canOpenFileAs(APP_C, file, /* forWrite */ false)).isTrue();

            // Re-install
            uninstallAppNoThrow(APP_C);
            installApp(APP_C);
            assertThat(canOpenFileAs(APP_C, file, /* forWrite */ false)).isFalse();
        } finally {
            file.delete();
            uninstallAppNoThrow(APP_C);
        }
    }

    private void testAppOpInvalidation(TestApp app, File file, @Nullable String permission,
            String opstr, boolean forWrite) throws Exception {
        boolean alreadyInstalled = true;
        try {
            if (!isAppInstalled(app)) {
                alreadyInstalled = false;
                installApp(app);
            }
            assertThat(file.createNewFile()).isTrue();
            assertAppOpInvalidation(app, file, permission, opstr, forWrite);
        } finally {
            file.delete();
            if (!alreadyInstalled) {
                // only uninstall if we installed this app here
                uninstallApp(app);
            }
        }
    }

    /** If {@code permission} is null, appops are flipped, otherwise permissions are flipped */
    private void assertAppOpInvalidation(TestApp app, File file, @Nullable String permission,
            String opstr, boolean forWrite) throws Exception {
        String packageName = app.getPackageName();
        int uid = getContext().getPackageManager().getPackageUid(packageName, 0);

        // Deny
        if (permission != null) {
            revokePermission(packageName, permission);
        } else {
            denyAppOpsToUid(uid, opstr);
            // TODO(191724755): Poll for AppOp state change instead
            Thread.sleep(200);
        }
        assertThat(canOpenFileAs(app, file, forWrite)).isFalse();

        // Grant
        if (permission != null) {
            grantPermission(packageName, permission);
        } else {
            allowAppOpsToUid(uid, opstr);
            // TODO(191724755): Poll for AppOp state change instead
            Thread.sleep(200);
        }
        assertThat(canOpenFileAs(app, file, forWrite)).isTrue();
        // Deny
        if (permission != null) {
            revokePermission(packageName, permission);
        } else {
            denyAppOpsToUid(uid, opstr);
            // TODO(191724755): Poll for AppOp state change instead
            Thread.sleep(200);
        }
        assertThat(canOpenFileAs(app, file, forWrite)).isFalse();
    }

    @Test
    @SdkSuppress(minSdkVersion = 31, codeName = "S")
    public void testDisableOpResetForSystemGallery() throws Exception {
        final File otherAppImageFile = new File(getDcimDir(), "other_" + IMAGE_FILE_NAME);
        final File otherAppVideoFile = new File(getDcimDir(), "other_" + VIDEO_FILE_NAME);

        try {
            allowAppOpsToUid(Process.myUid(), SYSTEM_GALERY_APPOPS);

            // Have another app create an image file
            assertThat(createFileAs(APP_B_NO_PERMS, otherAppImageFile.getPath())).isTrue();
            assertThat(otherAppImageFile.exists()).isTrue();

            // Have another app create a video file
            assertThat(createFileAs(APP_B_NO_PERMS, otherAppVideoFile.getPath())).isTrue();
            assertThat(otherAppVideoFile.exists()).isTrue();

            assertCanWriteAndRead(otherAppImageFile, BYTES_DATA1);
            assertCanWriteAndRead(otherAppVideoFile, BYTES_DATA1);

            // Reset app op should not reset System Gallery privileges
            executeShellCommand("appops reset " + THIS_PACKAGE_NAME);

            // Assert we can still write to images/videos
            assertCanWriteAndRead(otherAppImageFile, BYTES_DATA2);
            assertCanWriteAndRead(otherAppVideoFile, BYTES_DATA2);

        } finally {
            deleteFileAsNoThrow(APP_B_NO_PERMS, otherAppImageFile.getAbsolutePath());
            deleteFileAsNoThrow(APP_B_NO_PERMS, otherAppVideoFile.getAbsolutePath());
            denyAppOpsToUid(Process.myUid(), SYSTEM_GALERY_APPOPS);
        }
    }

    @Test
    public void testSystemGalleryAppHasFullAccessToImages() throws Exception {
        final File otherAppImageFile = new File(getDcimDir(), "other_" + IMAGE_FILE_NAME);
        final File topLevelImageFile = new File(getExternalStorageDir(), IMAGE_FILE_NAME);
        final File imageInAnObviouslyWrongPlace = new File(getMusicDir(), IMAGE_FILE_NAME);

        try {
            allowAppOpsToUid(Process.myUid(), SYSTEM_GALERY_APPOPS);

            // Have another app create an image file
            assertThat(createFileAs(APP_B_NO_PERMS, otherAppImageFile.getPath())).isTrue();
            assertThat(otherAppImageFile.exists()).isTrue();

            // Assert we can write to the file
            try (FileOutputStream fos = new FileOutputStream(otherAppImageFile)) {
                fos.write(BYTES_DATA1);
            }

            // Assert we can read from the file
            assertFileContent(otherAppImageFile, BYTES_DATA1);

            // Assert we can delete the file
            assertThat(otherAppImageFile.delete()).isTrue();
            assertThat(otherAppImageFile.exists()).isFalse();

            // Can create an image anywhere
            assertCanCreateFile(topLevelImageFile);
            assertCanCreateFile(imageInAnObviouslyWrongPlace);

            // Put the file back in its place and let APP B delete it
            assertThat(otherAppImageFile.createNewFile()).isTrue();
        } finally {
            deleteFileAsNoThrow(APP_B_NO_PERMS, otherAppImageFile.getAbsolutePath());
            otherAppImageFile.delete();
            denyAppOpsToUid(Process.myUid(), SYSTEM_GALERY_APPOPS);
        }
    }

    @Test
    public void testSystemGalleryAppHasNoFullAccessToAudio() throws Exception {
        final File otherAppAudioFile = new File(getMusicDir(), "other_" + AUDIO_FILE_NAME);
        final File topLevelAudioFile = new File(getExternalStorageDir(), AUDIO_FILE_NAME);
        final File audioInAnObviouslyWrongPlace = new File(getPicturesDir(), AUDIO_FILE_NAME);

        try {
            allowAppOpsToUid(Process.myUid(), SYSTEM_GALERY_APPOPS);

            // Have another app create an audio file
            assertThat(createFileAs(APP_B_NO_PERMS, otherAppAudioFile.getPath())).isTrue();
            assertThat(otherAppAudioFile.exists()).isTrue();

            // Assert we can't access the file
            assertThat(canOpen(otherAppAudioFile, /* forWrite */ false)).isFalse();
            assertThat(canOpen(otherAppAudioFile, /* forWrite */ true)).isFalse();

            // Assert we can't delete the file
            assertThat(otherAppAudioFile.delete()).isFalse();

            // Can't create an audio file where it doesn't belong
            assertThrows(IOException.class, "Operation not permitted",
                    () -> {
                        topLevelAudioFile.createNewFile();
                    });
            assertThrows(IOException.class, "Operation not permitted",
                    () -> {
                        audioInAnObviouslyWrongPlace.createNewFile();
                    });
        } finally {
            deleteFileAs(APP_B_NO_PERMS, otherAppAudioFile.getPath());
            topLevelAudioFile.delete();
            audioInAnObviouslyWrongPlace.delete();
            denyAppOpsToUid(Process.myUid(), SYSTEM_GALERY_APPOPS);
        }
    }

    @Test
    public void testSystemGalleryCanRenameImagesAndVideos() throws Exception {
        final File otherAppVideoFile = new File(getDcimDir(), "other_" + VIDEO_FILE_NAME);
        final File imageFile = new File(getPicturesDir(), IMAGE_FILE_NAME);
        final File videoFile = new File(getPicturesDir(), VIDEO_FILE_NAME);
        final File topLevelVideoFile = new File(getExternalStorageDir(), VIDEO_FILE_NAME);
        final File musicFile = new File(getMusicDir(), AUDIO_FILE_NAME);
        try {
            allowAppOpsToUid(Process.myUid(), SYSTEM_GALERY_APPOPS);

            // Have another app create a video file
            assertThat(createFileAs(APP_B_NO_PERMS, otherAppVideoFile.getPath())).isTrue();
            assertThat(otherAppVideoFile.exists()).isTrue();

            // Write some data to the file
            try (FileOutputStream fos = new FileOutputStream(otherAppVideoFile)) {
                fos.write(BYTES_DATA1);
            }
            assertFileContent(otherAppVideoFile, BYTES_DATA1);

            // Assert we can rename the file and ensure the file has the same content
            assertCanRenameFile(otherAppVideoFile, videoFile);
            assertFileContent(videoFile, BYTES_DATA1);
            // We can even move it to the top level directory
            assertCanRenameFile(videoFile, topLevelVideoFile);
            assertFileContent(topLevelVideoFile, BYTES_DATA1);
            // And we can even convert it into an image file, because why not?
            assertCanRenameFile(topLevelVideoFile, imageFile);
            assertFileContent(imageFile, BYTES_DATA1);

            // We can convert it to a music file, but we won't have access to music file after
            // renaming.
            assertThat(imageFile.renameTo(musicFile)).isTrue();
            assertThat(getFileRowIdFromDatabase(musicFile)).isEqualTo(-1);
        } finally {
            deleteFileAsNoThrow(APP_B_NO_PERMS, otherAppVideoFile.getAbsolutePath());
            imageFile.delete();
            videoFile.delete();
            topLevelVideoFile.delete();
            executeShellCommand("rm  " + musicFile.getAbsolutePath());
            MediaStore.scanFile(getContentResolver(), musicFile);
            denyAppOpsToUid(Process.myUid(), SYSTEM_GALERY_APPOPS);
        }
    }

    /**
     * Test that basic file path restrictions are enforced on file rename.
     */
    @Test
    public void testRenameFile() throws Exception {
        final File downloadDir = getDownloadDir();
        final File nonMediaDir = new File(downloadDir, TEST_DIRECTORY_NAME);
        final File pdfFile1 = new File(downloadDir, NONMEDIA_FILE_NAME);
        final File pdfFile2 = new File(nonMediaDir, NONMEDIA_FILE_NAME);
        final File videoFile1 = new File(getDcimDir(), VIDEO_FILE_NAME);
        final File videoFile2 = new File(getMoviesDir(), VIDEO_FILE_NAME);
        final File videoFile3 = new File(downloadDir, VIDEO_FILE_NAME);

        try {
            // Renaming non media file to media directory is not allowed.
            assertThat(pdfFile1.createNewFile()).isTrue();
            assertCantRenameFile(pdfFile1, new File(getDcimDir(), NONMEDIA_FILE_NAME));
            assertCantRenameFile(pdfFile1, new File(getMusicDir(), NONMEDIA_FILE_NAME));
            assertCantRenameFile(pdfFile1, new File(getMoviesDir(), NONMEDIA_FILE_NAME));

            // Renaming non media files to non media directories is allowed.
            if (!nonMediaDir.exists()) {
                assertThat(nonMediaDir.mkdirs()).isTrue();
            }
            // App can rename pdfFile to non media directory.
            assertCanRenameFile(pdfFile1, pdfFile2);

            assertThat(videoFile1.createNewFile()).isTrue();
            // App can rename video file to Movies directory
            assertCanRenameFile(videoFile1, videoFile2);
            // App can rename video file to Download directory
            assertCanRenameFile(videoFile2, videoFile3);
        } finally {
            pdfFile1.delete();
            pdfFile2.delete();
            videoFile1.delete();
            videoFile2.delete();
            videoFile3.delete();
            deleteRecursively(nonMediaDir);
        }
    }

    /**
     * Test that renaming file to different mime type is allowed.
     */
    @Test
    public void testRenameFileType() throws Exception {
        final File pdfFile = new File(getDownloadDir(), NONMEDIA_FILE_NAME);
        final File videoFile = new File(getDcimDir(), VIDEO_FILE_NAME);
        try {
            assertThat(pdfFile.createNewFile()).isTrue();
            assertThat(videoFile.exists()).isFalse();
            // Moving pdfFile to DCIM directory is not allowed.
            assertCantRenameFile(pdfFile, new File(getDcimDir(), NONMEDIA_FILE_NAME));
            // However, moving pdfFile to DCIM directory with changing the mime type to video is
            // allowed.
            assertCanRenameFile(pdfFile, videoFile);

            // On rename, MediaProvider database entry for pdfFile should be updated with new
            // videoFile path and mime type should be updated to video/mp4.
            assertThat(getFileMimeTypeFromDatabase(videoFile)).isEqualTo("video/mp4");
        } finally {
            pdfFile.delete();
            videoFile.delete();
        }
    }

    /**
     * Test that renaming files overwrites files in newPath.
     */
    @Test
    public void testRenameAndReplaceFile() throws Exception {
        final File videoFile1 = new File(getDcimDir(), VIDEO_FILE_NAME);
        final File videoFile2 = new File(getMoviesDir(), VIDEO_FILE_NAME);
        final ContentResolver cr = getContentResolver();
        try {
            assertThat(videoFile1.createNewFile()).isTrue();
            assertThat(videoFile2.createNewFile()).isTrue();
            final Uri uriVideoFile1 = MediaStore.scanFile(cr, videoFile1);
            final Uri uriVideoFile2 = MediaStore.scanFile(cr, videoFile2);

            // Renaming a file which replaces file in newPath videoFile2 is allowed.
            assertCanRenameFile(videoFile1, videoFile2);

            // Uri of videoFile2 should be accessible after rename.
            try (ParcelFileDescriptor pfd = cr.openFileDescriptor(uriVideoFile2, "rw")) {
                assertThat(pfd).isNotNull();
            }

            // Uri of videoFile1 should not be accessible after rename.
            assertThrows(FileNotFoundException.class,
                    () -> {
                        cr.openFileDescriptor(uriVideoFile1, "rw");
                    });
        } finally {
            videoFile1.delete();
            videoFile2.delete();
        }
    }

    /**
     * Test that ScanFile() after renaming file extension updates the right
     * MIME type from the file metadata.
     */
    @Test
    public void testScanUpdatesMimeTypeForRenameFileExtension() throws Exception {
        final String audioFileName = "ScopedStorageDeviceTest_" + NONCE;
        final File mpegFile = new File(getMusicDir(), audioFileName + ".mp3");
        final File nonMpegFile = new File(getMusicDir(), audioFileName + ".snd");
        try {
            // Copy audio content to mpegFile
            try (InputStream in =
                         getContext().getResources().openRawResource(R.raw.test_audio);
                 FileOutputStream out = new FileOutputStream(mpegFile)) {
                FileUtils.copy(in, out);
                out.getFD().sync();
            }
            assertThat(MediaStore.scanFile(getContentResolver(), mpegFile)).isNotNull();
            assertThat(getFileMimeTypeFromDatabase(mpegFile)).isEqualTo("audio/mpeg");

            // This rename changes MIME type from audio/mpeg to audio/basic
            assertCanRenameFile(mpegFile, nonMpegFile);
            assertThat(getFileMimeTypeFromDatabase(nonMpegFile)).isNotEqualTo("audio/mpeg");

            assertThat(MediaStore.scanFile(getContentResolver(), nonMpegFile)).isNotNull();
            // Above scan should read file metadata and update the MIME type to audio/mpeg
            assertThat(getFileMimeTypeFromDatabase(nonMpegFile)).isEqualTo("audio/mpeg");
        } finally {
            mpegFile.delete();
            nonMpegFile.delete();
        }
    }

    /**
     * Test that app without write permission for file can't update the file.
     */
    @Test
    public void testRenameFileNotOwned() throws Exception {
        final File videoFile1 = new File(getDcimDir(), VIDEO_FILE_NAME);
        final File videoFile2 = new File(getMoviesDir(), VIDEO_FILE_NAME);
        try {
            assertThat(createFileAs(APP_B_NO_PERMS, videoFile1.getAbsolutePath())).isTrue();
            // App can't rename a file owned by APP B.
            assertCantRenameFile(videoFile1, videoFile2);

            assertThat(videoFile2.createNewFile()).isTrue();
            // App can't rename a file to videoFile1 which is owned by APP B.
            assertCantRenameFile(videoFile2, videoFile1);
            // TODO(b/146346138): Test that app with right URI permission should be able to rename
            // the corresponding file
        } finally {
            deleteFileAsNoThrow(APP_B_NO_PERMS, videoFile1.getAbsolutePath());
            videoFile2.delete();
        }
    }

    /**
     * Test that renaming directories is allowed and aligns to default directory restrictions.
     */
    @Test
    public void testRenameDirectory() throws Exception {
        final File dcimDir = getDcimDir();
        final File downloadDir = getDownloadDir();
        final String nonMediaDirectoryName = TEST_DIRECTORY_NAME + "NonMedia";
        final File nonMediaDirectory = new File(downloadDir, nonMediaDirectoryName);
        final File pdfFile = new File(nonMediaDirectory, NONMEDIA_FILE_NAME);

        final String mediaDirectoryName = TEST_DIRECTORY_NAME + "Media";
        final File mediaDirectory1 = new File(dcimDir, mediaDirectoryName);
        final File videoFile1 = new File(mediaDirectory1, VIDEO_FILE_NAME);
        final File mediaDirectory2 = new File(downloadDir, mediaDirectoryName);
        final File videoFile2 = new File(mediaDirectory2, VIDEO_FILE_NAME);
        final File mediaDirectory3 = new File(getMoviesDir(), TEST_DIRECTORY_NAME);
        final File videoFile3 = new File(mediaDirectory3, VIDEO_FILE_NAME);
        final File mediaDirectory4 = new File(mediaDirectory3, mediaDirectoryName);

        try {
            if (!nonMediaDirectory.exists()) {
                assertThat(nonMediaDirectory.mkdirs()).isTrue();
            }
            assertThat(pdfFile.createNewFile()).isTrue();
            // Move directory with pdf file to DCIM directory is not allowed.
            assertThat(nonMediaDirectory.renameTo(new File(dcimDir, nonMediaDirectoryName)))
                    .isFalse();

            if (!mediaDirectory1.exists()) {
                assertThat(mediaDirectory1.mkdirs()).isTrue();
            }
            assertThat(videoFile1.createNewFile()).isTrue();
            // Renaming to and from default directories is not allowed.
            assertThat(mediaDirectory1.renameTo(dcimDir)).isFalse();
            // Moving top level default directories is not allowed.
            assertCantRenameDirectory(downloadDir, new File(dcimDir, TEST_DIRECTORY_NAME), null);

            // Moving media directory to Download directory is allowed.
            assertCanRenameDirectory(mediaDirectory1, mediaDirectory2, new File[] {videoFile1},
                    new File[] {videoFile2});

            // Moving media directory to Movies directory and renaming directory in new path is
            // allowed.
            assertCanRenameDirectory(mediaDirectory2, mediaDirectory3, new File[] {videoFile2},
                    new File[] {videoFile3});

            // Can't rename a mediaDirectory to non empty non Media directory.
            assertCantRenameDirectory(mediaDirectory3, nonMediaDirectory, new File[] {videoFile3});
            // Can't rename a file to a directory.
            assertCantRenameFile(videoFile3, mediaDirectory3);
            // Can't rename a directory to file.
            assertCantRenameDirectory(mediaDirectory3, pdfFile, null);
            if (!mediaDirectory4.exists()) {
                assertThat(mediaDirectory4.mkdir()).isTrue();
            }
            // Can't rename a directory to subdirectory of itself.
            assertCantRenameDirectory(mediaDirectory3, mediaDirectory4, new File[] {videoFile3});

        } finally {
            pdfFile.delete();
            deleteRecursively(nonMediaDirectory);

            videoFile1.delete();
            videoFile2.delete();
            videoFile3.delete();
            deleteRecursively(mediaDirectory1);
            deleteRecursively(mediaDirectory2);
            deleteRecursively(mediaDirectory3);
            deleteRecursively(mediaDirectory4);
        }
    }

    /**
     * Test that renaming directory checks file ownership permissions.
     */
    @Test
    public void testRenameDirectoryNotOwned() throws Exception {
        final String mediaDirectoryName = TEST_DIRECTORY_NAME + "Media";
        File mediaDirectory1 = new File(getDcimDir(), mediaDirectoryName);
        File mediaDirectory2 = new File(getMoviesDir(), mediaDirectoryName);
        File videoFile = new File(mediaDirectory1, VIDEO_FILE_NAME);

        try {
            if (!mediaDirectory1.exists()) {
                assertThat(mediaDirectory1.mkdirs()).isTrue();
            }
            assertThat(createFileAs(APP_B_NO_PERMS, videoFile.getAbsolutePath())).isTrue();
            // App doesn't have access to videoFile1, can't rename mediaDirectory1.
            assertThat(mediaDirectory1.renameTo(mediaDirectory2)).isFalse();
            assertThat(videoFile.exists()).isTrue();
            // Test app can delete the file since the file is not moved to new directory.
            assertThat(deleteFileAs(APP_B_NO_PERMS, videoFile.getAbsolutePath())).isTrue();
        } finally {
            deleteFileAsNoThrow(APP_B_NO_PERMS, videoFile.getAbsolutePath());
            deleteRecursively(mediaDirectory1);
            deleteRecursively(mediaDirectory2);
        }
    }

    /**
     * Test renaming empty directory is allowed
     */
    @Test
    public void testRenameEmptyDirectory() throws Exception {
        final String emptyDirectoryName = TEST_DIRECTORY_NAME + "Media";
        File emptyDirectoryOldPath = new File(getDcimDir(), emptyDirectoryName);
        File emptyDirectoryNewPath = new File(getMoviesDir(), TEST_DIRECTORY_NAME + "23456");
        try {
            if (emptyDirectoryOldPath.exists()) {
                executeShellCommand("rm -r " + emptyDirectoryOldPath.getPath());
            }
            assertThat(emptyDirectoryOldPath.mkdirs()).isTrue();
            assertCanRenameDirectory(emptyDirectoryOldPath, emptyDirectoryNewPath, null, null);
        } finally {
            deleteRecursively(emptyDirectoryOldPath);
            deleteRecursively(emptyDirectoryNewPath);
        }
    }

    /**
     * Test that apps can create and delete hidden file.
     */
    @Test
    public void testCanCreateHiddenFile() throws Exception {
        final File hiddenImageFile = new File(getDownloadDir(), ".hiddenFile" + IMAGE_FILE_NAME);
        try {
            assertThat(hiddenImageFile.createNewFile()).isTrue();
            // Write to hidden file is allowed.
            try (FileOutputStream fos = new FileOutputStream(hiddenImageFile)) {
                fos.write(BYTES_DATA1);
            }
            assertFileContent(hiddenImageFile, BYTES_DATA1);

            assertNotMediaTypeImage(hiddenImageFile);

            assertDirectoryContains(getDownloadDir(), hiddenImageFile);
            assertThat(getFileRowIdFromDatabase(hiddenImageFile)).isNotEqualTo(-1);

            // We can delete hidden file
            assertThat(hiddenImageFile.delete()).isTrue();
            assertThat(hiddenImageFile.exists()).isFalse();
        } finally {
            hiddenImageFile.delete();
        }
    }

    /**
     * Test that FUSE upper-fs is consistent with lower-fs after the lower-fs fd is closed.
     */
    @Test
    public void testInodeStatConsistency() throws Exception {
        File file = new File(getDcimDir(), IMAGE_FILE_NAME);

        try {
            byte[] writeBuffer = new byte[10];
            Arrays.fill(writeBuffer, (byte) 1);

            assertThat(file.createNewFile()).isTrue();
            // Scanning a file is essential as files created via filepath will be marked
            // as isPending, and we do not set listener for pending files as it can lead to
            // performance overhead. See: I34611f0ee897dc676e7653beb7943aa6de58c55a.
            MediaStore.scanFile(getContentResolver(), file);

            // File operation #1 (to lower-fs)
            ParcelFileDescriptor writePfd = openWithMediaProvider(file, "rw");

            // File operation #2 (to fuse). This caches the inode for the file.
            file.exists();

            // Write bytes directly to lower-fs
            Os.pwrite(writePfd.getFileDescriptor(), writeBuffer, 0, 10, 0);

            // Close should invalidate inode cache for this file.
            writePfd.close();
            Thread.sleep(1000);

            long fuseFileSize = file.length();
            assertThat(writeBuffer.length).isEqualTo(fuseFileSize);
        } finally {
            file.delete();
        }
    }

    /**
     * Test that apps can rename a hidden file.
     */
    @Test
    public void testCanRenameHiddenFile() throws Exception {
        final String hiddenFileName = ".hidden" + IMAGE_FILE_NAME;
        final File hiddenImageFile1 = new File(getDcimDir(), hiddenFileName);
        final File hiddenImageFile2 = new File(getDownloadDir(), hiddenFileName);
        final File imageFile = new File(getDownloadDir(), IMAGE_FILE_NAME);
        try {
            assertThat(hiddenImageFile1.createNewFile()).isTrue();
            assertCanRenameFile(hiddenImageFile1, hiddenImageFile2);
            assertNotMediaTypeImage(hiddenImageFile2);

            // We can also rename hidden file to non-hidden
            assertCanRenameFile(hiddenImageFile2, imageFile);
            assertIsMediaTypeImage(imageFile);

            // We can rename non-hidden file to hidden
            assertCanRenameFile(imageFile, hiddenImageFile1);
            assertNotMediaTypeImage(hiddenImageFile1);
        } finally {
            hiddenImageFile1.delete();
            hiddenImageFile2.delete();
            imageFile.delete();
        }
    }

    /**
     * Test that files in hidden directory have MEDIA_TYPE=MEDIA_TYPE_NONE
     */
    @Test
    public void testHiddenDirectory() throws Exception {
        final File hiddenDir = new File(getDownloadDir(), ".hidden" + TEST_DIRECTORY_NAME);
        final File hiddenImageFile = new File(hiddenDir, IMAGE_FILE_NAME);
        final File nonHiddenDir = new File(getDownloadDir(), TEST_DIRECTORY_NAME);
        final File imageFile = new File(nonHiddenDir, IMAGE_FILE_NAME);
        try {
            if (!hiddenDir.exists()) {
                assertThat(hiddenDir.mkdir()).isTrue();
            }
            assertThat(hiddenImageFile.createNewFile()).isTrue();

            assertNotMediaTypeImage(hiddenImageFile);

            // Renaming hiddenDir to nonHiddenDir makes the imageFile non-hidden and vice versa
            assertCanRenameDirectory(
                    hiddenDir, nonHiddenDir, new File[] {hiddenImageFile}, new File[] {imageFile});
            assertIsMediaTypeImage(imageFile);

            assertCanRenameDirectory(
                    nonHiddenDir, hiddenDir, new File[] {imageFile}, new File[] {hiddenImageFile});
            assertNotMediaTypeImage(hiddenImageFile);
        } finally {
            hiddenImageFile.delete();
            imageFile.delete();
            deleteRecursively(hiddenDir);
            deleteRecursively(nonHiddenDir);
        }
    }

    /**
     * Test that files in directory with nomedia have MEDIA_TYPE=MEDIA_TYPE_NONE
     */
    @Test
    public void testHiddenDirectory_nomedia() throws Exception {
        final File directoryNoMedia = new File(getDownloadDir(), "nomedia" + TEST_DIRECTORY_NAME);
        final File noMediaFile = new File(directoryNoMedia, ".nomedia");
        final File imageFile = new File(directoryNoMedia, IMAGE_FILE_NAME);
        final File videoFile = new File(directoryNoMedia, VIDEO_FILE_NAME);
        try {
            if (!directoryNoMedia.exists()) {
                assertThat(directoryNoMedia.mkdir()).isTrue();
            }
            assertThat(noMediaFile.createNewFile()).isTrue();
            assertThat(imageFile.createNewFile()).isTrue();

            assertNotMediaTypeImage(imageFile);

            // Deleting the .nomedia file makes the parent directory non hidden.
            noMediaFile.delete();
            MediaStore.scanFile(getContentResolver(), directoryNoMedia);
            assertIsMediaTypeImage(imageFile);

            // Creating the .nomedia file makes the parent directory hidden again
            assertThat(noMediaFile.createNewFile()).isTrue();
            MediaStore.scanFile(getContentResolver(), directoryNoMedia);
            assertNotMediaTypeImage(imageFile);

            // Renaming the .nomedia file to non hidden file makes the parent directory non hidden.
            assertCanRenameFile(noMediaFile, videoFile);
            assertIsMediaTypeImage(imageFile);
        } finally {
            noMediaFile.delete();
            imageFile.delete();
            videoFile.delete();
            deleteRecursively(directoryNoMedia);
        }
    }

    /**
     * Test that only file manager and app that created the hidden file can list it.
     */
    @Test
    public void testListHiddenFile() throws Exception {
        final File dcimDir = getDcimDir();
        final String hiddenImageFileName = ".hidden" + IMAGE_FILE_NAME;
        final File hiddenImageFile = new File(dcimDir, hiddenImageFileName);
        try {
            assertThat(hiddenImageFile.createNewFile()).isTrue();
            assertNotMediaTypeImage(hiddenImageFile);

            assertDirectoryContains(dcimDir, hiddenImageFile);

            // TestApp with read permissions can't see the hidden image file created by other app
            assertThat(listAs(APP_A_HAS_RES, dcimDir.getAbsolutePath()))
                    .doesNotContain(hiddenImageFileName);

            // But file manager can
            assertThat(listAs(APP_FM, dcimDir.getAbsolutePath()))
                    .contains(hiddenImageFileName);

            // Gallery cannot see the hidden image file created by other app
            final int resAppUid =
                    getContext().getPackageManager().getPackageUid(APP_A_HAS_RES.getPackageName(),
                            0);
            try {
                allowAppOpsToUid(resAppUid, SYSTEM_GALERY_APPOPS);
                assertThat(listAs(APP_A_HAS_RES, dcimDir.getAbsolutePath()))
                        .doesNotContain(hiddenImageFileName);
            } finally {
                denyAppOpsToUid(resAppUid, SYSTEM_GALERY_APPOPS);
            }
        } finally {
            hiddenImageFile.delete();
        }
    }

    @Test
    public void testOpenPendingAndTrashed() throws Exception {
        final File pendingImageFile = new File(getDcimDir(), IMAGE_FILE_NAME);
        final File trashedVideoFile = new File(getPicturesDir(), VIDEO_FILE_NAME);
        final File pendingPdfFile = new File(getDocumentsDir(), NONMEDIA_FILE_NAME);
        final File trashedPdfFile = new File(getDownloadDir(), NONMEDIA_FILE_NAME);
        Uri pendingImgaeFileUri = null;
        Uri trashedVideoFileUri = null;
        Uri pendingPdfFileUri = null;
        Uri trashedPdfFileUri = null;
        try {
            pendingImgaeFileUri = createPendingFile(pendingImageFile);
            assertOpenPendingOrTrashed(pendingImgaeFileUri, /*isImageOrVideo*/ true);

            pendingPdfFileUri = createPendingFile(pendingPdfFile);
            assertOpenPendingOrTrashed(pendingPdfFileUri, /*isImageOrVideo*/ false);

            trashedVideoFileUri = createTrashedFile(trashedVideoFile);
            assertOpenPendingOrTrashed(trashedVideoFileUri, /*isImageOrVideo*/ true);

            trashedPdfFileUri = createTrashedFile(trashedPdfFile);
            assertOpenPendingOrTrashed(trashedPdfFileUri, /*isImageOrVideo*/ false);

        } finally {
            deleteFiles(pendingImageFile, pendingImageFile, trashedVideoFile,
                    trashedPdfFile);
            deleteWithMediaProviderNoThrow(pendingImgaeFileUri, trashedVideoFileUri,
                    pendingPdfFileUri, trashedPdfFileUri);
        }
    }

    @Test
    public void testListPendingAndTrashed() throws Exception {
        final File imageFile = new File(getDcimDir(), IMAGE_FILE_NAME);
        final File pdfFile = new File(getDownloadDir(), NONMEDIA_FILE_NAME);
        Uri imageFileUri = null;
        Uri pdfFileUri = null;
        try {
            imageFileUri = createPendingFile(imageFile);
            // Check that only owner package, file manager and system gallery can list pending image
            // file.
            assertListPendingOrTrashed(imageFileUri, imageFile, /*isImageOrVideo*/ true);

            trashFileAndAssert(imageFileUri);
            // Check that only owner package, file manager and system gallery can list trashed image
            // file.
            assertListPendingOrTrashed(imageFileUri, imageFile, /*isImageOrVideo*/ true);

            pdfFileUri = createPendingFile(pdfFile);
            // Check that only owner package, file manager can list pending non media file.
            assertListPendingOrTrashed(pdfFileUri, pdfFile, /*isImageOrVideo*/ false);

            trashFileAndAssert(pdfFileUri);
            // Check that only owner package, file manager can list trashed non media file.
            assertListPendingOrTrashed(pdfFileUri, pdfFile, /*isImageOrVideo*/ false);
        } finally {
            deleteWithMediaProviderNoThrow(imageFileUri, pdfFileUri);
            deleteFiles(imageFile, pdfFile);
        }
    }

    @Test
    public void testDeletePendingAndTrashed_ownerCanDelete() throws Exception {
        final File pendingVideoFile = new File(getDcimDir(), VIDEO_FILE_NAME);
        final File trashedImageFile = new File(getPicturesDir(), IMAGE_FILE_NAME);
        final File pendingPdfFile = new File(getDownloadDir(), NONMEDIA_FILE_NAME);
        final File trashedPdfFile = new File(getDocumentsDir(), NONMEDIA_FILE_NAME);
        // Actual path of the file gets rewritten for pending and trashed files.
        String pendingVideoFilePath = null;
        String trashedImageFilePath = null;
        String pendingPdfFilePath = null;
        String trashedPdfFilePath = null;
        try {
            pendingVideoFilePath = getFilePathFromUri(createPendingFile(pendingVideoFile));
            trashedImageFilePath = getFilePathFromUri(createTrashedFile(trashedImageFile));
            pendingPdfFilePath = getFilePathFromUri(createPendingFile(pendingPdfFile));
            trashedPdfFilePath = getFilePathFromUri(createTrashedFile(trashedPdfFile));

            // App can delete its own pending and trashed file.
            assertCanDeletePaths(pendingVideoFilePath, trashedImageFilePath, pendingPdfFilePath,
                    trashedPdfFilePath);
        } finally {
            deletePaths(pendingVideoFilePath, trashedImageFilePath, pendingPdfFilePath,
                    trashedPdfFilePath);
            deleteFiles(pendingVideoFile, trashedImageFile, pendingPdfFile, trashedPdfFile);
        }
    }

    @Test
    public void testDeletePendingAndTrashed_otherAppCantDelete() throws Exception {
        final File pendingVideoFile = new File(getDcimDir(), VIDEO_FILE_NAME);
        final File trashedImageFile = new File(getPicturesDir(), IMAGE_FILE_NAME);
        final File pendingPdfFile = new File(getDownloadDir(), NONMEDIA_FILE_NAME);
        final File trashedPdfFile = new File(getDocumentsDir(), NONMEDIA_FILE_NAME);
        // Actual path of the file gets rewritten for pending and trashed files.
        String pendingVideoFilePath = null;
        String trashedImageFilePath = null;
        String pendingPdfFilePath = null;
        String trashedPdfFilePath = null;
        try {
            pendingVideoFilePath = getFilePathFromUri(createPendingFile(pendingVideoFile));
            trashedImageFilePath = getFilePathFromUri(createTrashedFile(trashedImageFile));
            pendingPdfFilePath = getFilePathFromUri(createPendingFile(pendingPdfFile));
            trashedPdfFilePath = getFilePathFromUri(createTrashedFile(trashedPdfFile));

            // App can't delete other app's pending and trashed file.
            assertCantDeletePathsAs(APP_A_HAS_RES, pendingVideoFilePath, trashedImageFilePath,
                    pendingPdfFilePath, trashedPdfFilePath);
        } finally {
            deletePaths(pendingVideoFilePath, trashedImageFilePath, pendingPdfFilePath,
                    trashedPdfFilePath);
            deleteFiles(pendingVideoFile, trashedImageFile, pendingPdfFile, trashedPdfFile);
        }
    }

    @Test
    public void testDeletePendingAndTrashed_fileManagerCanDelete() throws Exception {
        final File pendingVideoFile = new File(getDcimDir(), VIDEO_FILE_NAME);
        final File trashedImageFile = new File(getPicturesDir(), IMAGE_FILE_NAME);
        final File pendingPdfFile = new File(getDownloadDir(), NONMEDIA_FILE_NAME);
        final File trashedPdfFile = new File(getDocumentsDir(), NONMEDIA_FILE_NAME);
        // Actual path of the file gets rewritten for pending and trashed files.
        String pendingVideoFilePath = null;
        String trashedImageFilePath = null;
        String pendingPdfFilePath = null;
        String trashedPdfFilePath = null;
        try {
            pendingVideoFilePath = getFilePathFromUri(createPendingFile(pendingVideoFile));
            trashedImageFilePath = getFilePathFromUri(createTrashedFile(trashedImageFile));
            pendingPdfFilePath = getFilePathFromUri(createPendingFile(pendingPdfFile));
            trashedPdfFilePath = getFilePathFromUri(createTrashedFile(trashedPdfFile));

            // File Manager can delete any pending and trashed file
            assertCanDeletePathsAs(APP_FM, pendingVideoFilePath, trashedImageFilePath,
                    pendingPdfFilePath, trashedPdfFilePath);
        } finally {
            deletePaths(pendingVideoFilePath, trashedImageFilePath, pendingPdfFilePath,
                    trashedPdfFilePath);
            deleteFiles(pendingVideoFile, trashedImageFile, pendingPdfFile, trashedPdfFile);
        }
    }

    @Test
    public void testDeletePendingAndTrashed_systemGalleryCanDeleteMedia() throws Exception {
        final File pendingVideoFile = new File(getDcimDir(), VIDEO_FILE_NAME);
        final File trashedImageFile = new File(getPicturesDir(), IMAGE_FILE_NAME);
        final File pendingPdfFile = new File(getDownloadDir(), NONMEDIA_FILE_NAME);
        final File trashedPdfFile = new File(getDocumentsDir(), NONMEDIA_FILE_NAME);
        // Actual path of the file gets rewritten for pending and trashed files.
        String pendingVideoFilePath = null;
        String trashedImageFilePath = null;
        String pendingPdfFilePath = null;
        String trashedPdfFilePath = null;
        try {
            pendingVideoFilePath = getFilePathFromUri(createPendingFile(pendingVideoFile));
            trashedImageFilePath = getFilePathFromUri(createTrashedFile(trashedImageFile));
            pendingPdfFilePath = getFilePathFromUri(createPendingFile(pendingPdfFile));
            trashedPdfFilePath = getFilePathFromUri(createTrashedFile(trashedPdfFile));

            // System Gallery can delete any pending and trashed image or video file.
            final int resAppUid =
                    getContext().getPackageManager().getPackageUid(APP_A_HAS_RES.getPackageName(),
                            0);
            try {
                allowAppOpsToUid(resAppUid, SYSTEM_GALERY_APPOPS);
                assertTrue(isMediaTypeImageOrVideo(new File(pendingVideoFilePath)));
                assertTrue(isMediaTypeImageOrVideo(new File(trashedImageFilePath)));
                assertCanDeletePathsAs(APP_A_HAS_RES, pendingVideoFilePath, trashedImageFilePath);

                // System Gallery can't delete other app's pending and trashed pdf file.
                assertFalse(isMediaTypeImageOrVideo(new File(pendingPdfFilePath)));
                assertFalse(isMediaTypeImageOrVideo(new File(trashedPdfFilePath)));
                assertCantDeletePathsAs(APP_A_HAS_RES, pendingPdfFilePath, trashedPdfFilePath);
            } finally {
                denyAppOpsToUid(resAppUid, SYSTEM_GALERY_APPOPS);
            }
        } finally {
            deletePaths(pendingVideoFilePath, trashedImageFilePath, pendingPdfFilePath,
                    trashedPdfFilePath);
            deleteFiles(pendingVideoFile, trashedImageFile, pendingPdfFile, trashedPdfFile);
        }
    }

    @Test
    public void testSystemGalleryCanTrashOtherAndroidMediaFiles() throws Exception {
        final File otherVideoFile = new File(getAndroidMediaDir(),
                String.format("%s/%s", APP_B_NO_PERMS.getPackageName(), VIDEO_FILE_NAME));
        try {
            allowAppOpsToUid(Process.myUid(), SYSTEM_GALERY_APPOPS);

            assertThat(createFileAs(APP_B_NO_PERMS, otherVideoFile.getAbsolutePath())).isTrue();

            final Uri otherVideoUri = MediaStore.scanFile(getContentResolver(), otherVideoFile);
            assertNotNull(otherVideoUri);

            trashFileAndAssert(otherVideoUri);
            untrashFileAndAssert(otherVideoUri);
        } finally {
            otherVideoFile.delete();
            denyAppOpsToUid(Process.myUid(), SYSTEM_GALERY_APPOPS);
        }
    }

    @Test
    public void testSystemGalleryCanUpdateOtherAndroidMediaFiles() throws Exception {
        final File otherImageFile = new File(getAndroidMediaDir(),
                String.format("%s/%s", APP_B_NO_PERMS.getPackageName(), IMAGE_FILE_NAME));
        final File updatedImageFileInDcim = new File(getDcimDir(), IMAGE_FILE_NAME);
        try {
            allowAppOpsToUid(Process.myUid(), SYSTEM_GALERY_APPOPS);

            assertThat(createFileAs(APP_B_NO_PERMS, otherImageFile.getAbsolutePath())).isTrue();

            final Uri otherImageUri = MediaStore.scanFile(getContentResolver(), otherImageFile);
            assertNotNull(otherImageUri);

            final ContentValues values = new ContentValues();
            values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM);
            // Test that we can move the file to "DCIM/"
            assertWithMessage("Result of ContentResolver#update for " + otherImageUri
                    + " with values " + values)
                    .that(getContentResolver().update(otherImageUri, values, Bundle.EMPTY))
                    .isEqualTo(1);
            assertThat(updatedImageFileInDcim.exists()).isTrue();
            assertThat(otherImageFile.exists()).isFalse();

            values.clear();
            values.put(MediaStore.MediaColumns.RELATIVE_PATH,
                    "Android/media/" + APP_B_NO_PERMS.getPackageName());
            // Test that we can move the file back to other app's owned path
            assertWithMessage("Result of ContentResolver#update for " + otherImageUri
                    + " with values " + values)
                    .that(getContentResolver().update(otherImageUri, values, Bundle.EMPTY))
                    .isEqualTo(1);
            assertThat(otherImageFile.exists()).isTrue();
        } finally {
            otherImageFile.delete();
            updatedImageFileInDcim.delete();
            denyAppOpsToUid(Process.myUid(), SYSTEM_GALERY_APPOPS);
        }
    }

    @Test
    public void testQueryOtherAppsFiles() throws Exception {
        final File otherAppPdf = new File(getDownloadDir(), "other" + NONMEDIA_FILE_NAME);
        final File otherAppImg = new File(getDcimDir(), "other" + IMAGE_FILE_NAME);
        final File otherAppMusic = new File(getMusicDir(), "other" + AUDIO_FILE_NAME);
        final File otherHiddenFile = new File(getPicturesDir(), ".otherHiddenFile.jpg");
        try {
            // Apps can't query other app's pending file, hence create file and publish it.
            assertCreatePublishedFilesAs(
                    APP_B_NO_PERMS, otherAppImg, otherAppMusic, otherAppPdf, otherHiddenFile);

            // Since the test doesn't have READ_EXTERNAL_STORAGE nor any other special permissions,
            // it can't query for another app's contents.
            assertCantQueryFile(otherAppImg);
            assertCantQueryFile(otherAppMusic);
            assertCantQueryFile(otherAppPdf);
            assertCantQueryFile(otherHiddenFile);
        } finally {
            deleteFilesAs(APP_B_NO_PERMS, otherAppImg, otherAppMusic, otherAppPdf, otherHiddenFile);
        }
    }

    @Test
    public void testSystemGalleryQueryOtherAppsFiles() throws Exception {
        final File otherAppPdf = new File(getDownloadDir(), "other" + NONMEDIA_FILE_NAME);
        final File otherAppImg = new File(getDcimDir(), "other" + IMAGE_FILE_NAME);
        final File otherAppMusic = new File(getMusicDir(), "other" + AUDIO_FILE_NAME);
        final File otherHiddenFile = new File(getPicturesDir(), ".otherHiddenFile.jpg");
        try {
            // Apps can't query other app's pending file, hence create file and publish it.
            assertCreatePublishedFilesAs(
                    APP_B_NO_PERMS, otherAppImg, otherAppMusic, otherAppPdf, otherHiddenFile);

            // System gallery apps have access to video and image files
            allowAppOpsToUid(Process.myUid(), SYSTEM_GALERY_APPOPS);

            assertCanQueryAndOpenFile(otherAppImg, "rw");
            // System gallery doesn't have access to hidden image files of other app
            assertCantQueryFile(otherHiddenFile);
            // But no access to PDFs or music files
            assertCantQueryFile(otherAppMusic);
            assertCantQueryFile(otherAppPdf);
        } finally {
            denyAppOpsToUid(Process.myUid(), SYSTEM_GALERY_APPOPS);
            deleteFilesAs(APP_B_NO_PERMS, otherAppImg, otherAppMusic, otherAppPdf, otherHiddenFile);
        }
    }

    /**
     * Test that System Gallery app can rename any directory under the default directories
     * designated for images and videos, even if they contain other apps' contents that
     * System Gallery doesn't have read access to.
     */
    @Test
    public void testSystemGalleryCanRenameImageAndVideoDirs() throws Exception {
        final File dirInDcim = new File(getDcimDir(), TEST_DIRECTORY_NAME);
        final File dirInPictures = new File(getPicturesDir(), TEST_DIRECTORY_NAME);
        final File dirInPodcasts = new File(getPodcastsDir(), TEST_DIRECTORY_NAME);
        final File otherAppImageFile1 = new File(dirInDcim, "other_" + IMAGE_FILE_NAME);
        final File otherAppVideoFile1 = new File(dirInDcim, "other_" + VIDEO_FILE_NAME);
        final File otherAppPdfFile1 = new File(dirInDcim, "other_" + NONMEDIA_FILE_NAME);
        final File otherAppImageFile2 = new File(dirInPictures, "other_" + IMAGE_FILE_NAME);
        final File otherAppVideoFile2 = new File(dirInPictures, "other_" + VIDEO_FILE_NAME);
        final File otherAppPdfFile2 = new File(dirInPictures, "other_" + NONMEDIA_FILE_NAME);
        try {
            assertThat(dirInDcim.exists() || dirInDcim.mkdir()).isTrue();

            executeShellCommand("touch " + otherAppPdfFile1);
            MediaStore.scanFile(getContentResolver(), otherAppPdfFile1);

            allowAppOpsToUid(Process.myUid(), SYSTEM_GALERY_APPOPS);

            assertCreateFilesAs(APP_A_HAS_RES, otherAppImageFile1, otherAppVideoFile1);

            // System gallery privileges don't go beyond DCIM, Movies and Pictures boundaries.
            assertCantRenameDirectory(dirInDcim, dirInPodcasts, /*oldFilesList*/ null);

            // Rename should succeed, but System Gallery still can't access that PDF file!
            assertCanRenameDirectory(dirInDcim, dirInPictures,
                    new File[] {otherAppImageFile1, otherAppVideoFile1},
                    new File[] {otherAppImageFile2, otherAppVideoFile2});
            assertThat(getFileRowIdFromDatabase(otherAppPdfFile1)).isEqualTo(-1);
            assertThat(getFileRowIdFromDatabase(otherAppPdfFile2)).isEqualTo(-1);
        } finally {
            executeShellCommand("rm " + otherAppPdfFile1);
            executeShellCommand("rm " + otherAppPdfFile2);
            MediaStore.scanFile(getContentResolver(), otherAppPdfFile1);
            MediaStore.scanFile(getContentResolver(), otherAppPdfFile2);
            otherAppImageFile1.delete();
            otherAppImageFile2.delete();
            otherAppVideoFile1.delete();
            otherAppVideoFile2.delete();
            otherAppPdfFile1.delete();
            otherAppPdfFile2.delete();
            deleteRecursively(dirInDcim);
            deleteRecursively(dirInPictures);
            denyAppOpsToUid(Process.myUid(), SYSTEM_GALERY_APPOPS);
        }
    }

    /**
     * Test that row ID corresponding to deleted path is restored on subsequent create.
     */
    @Test
    public void testCreateCanRestoreDeletedRowId() throws Exception {
        final File imageFile = new File(getDcimDir(), IMAGE_FILE_NAME);
        final ContentResolver cr = getContentResolver();

        try {
            assertThat(imageFile.createNewFile()).isTrue();
            final long oldRowId = getFileRowIdFromDatabase(imageFile);
            assertThat(oldRowId).isNotEqualTo(-1);
            final Uri uriOfOldFile = MediaStore.scanFile(cr, imageFile);
            assertThat(uriOfOldFile).isNotNull();

            assertThat(imageFile.delete()).isTrue();
            // We should restore old row Id corresponding to deleted imageFile.
            assertThat(imageFile.createNewFile()).isTrue();
            assertThat(getFileRowIdFromDatabase(imageFile)).isEqualTo(oldRowId);
            try (ParcelFileDescriptor pfd =  cr.openFileDescriptor(uriOfOldFile, "rw")) {
                assertThat(pfd).isNotNull();
            }


            assertThat(imageFile.delete()).isTrue();
            assertThat(createFileAs(APP_B_NO_PERMS, imageFile.getAbsolutePath())).isTrue();

            final Uri uriOfNewFile = MediaStore.scanFile(getContentResolver(), imageFile);
            assertThat(uriOfNewFile).isNotNull();
            // We shouldn't restore deleted row Id if delete & create are called from different apps
            assertThat(Integer.getInteger(uriOfNewFile.getLastPathSegment()))
                    .isNotEqualTo(oldRowId);
        } finally {
            imageFile.delete();
            deleteFileAsNoThrow(APP_B_NO_PERMS, imageFile.getAbsolutePath());
        }
    }

    /**
     * Test that row ID corresponding to deleted path is restored on subsequent rename.
     */
    @Test
    public void testRenameCanRestoreDeletedRowId() throws Exception {
        final File imageFile = new File(getDcimDir(), IMAGE_FILE_NAME);
        final File temporaryFile = new File(getDownloadDir(), IMAGE_FILE_NAME + "_.tmp");
        final ContentResolver cr = getContentResolver();

        try {
            assertThat(imageFile.createNewFile()).isTrue();
            final Uri oldUri = MediaStore.scanFile(cr, imageFile);
            assertThat(oldUri).isNotNull();

            Files.copy(imageFile, temporaryFile);
            assertThat(imageFile.delete()).isTrue();
            assertCanRenameFile(temporaryFile, imageFile);

            final Uri newUri = MediaStore.scanFile(cr, imageFile);
            assertThat(newUri).isNotNull();
            assertThat(newUri.getLastPathSegment()).isEqualTo(oldUri.getLastPathSegment());
            // oldUri of imageFile is still accessible after delete and rename.
            try (ParcelFileDescriptor pfd = cr.openFileDescriptor(oldUri, "rw")) {
                assertThat(pfd).isNotNull();
            }
        } finally {
            imageFile.delete();
            temporaryFile.delete();
        }
    }

    @Test
    public void testCantCreateOrRenameFileWithInvalidName() throws Exception {
        File invalidFile = new File(getDownloadDir(), "<>");
        File validFile = new File(getDownloadDir(), NONMEDIA_FILE_NAME);
        try {
            assertThrows(IOException.class, "Operation not permitted",
                    () -> {
                        invalidFile.createNewFile();
                    });

            assertThat(validFile.createNewFile()).isTrue();
            // We can't rename a file to a file name with invalid FAT characters.
            assertCantRenameFile(validFile, invalidFile);
        } finally {
            invalidFile.delete();
            validFile.delete();
        }
    }

    @Test
    public void testRenameWithSpecialChars() throws Exception {
        final String specialCharsSuffix = "'`~!@#$%^& ()_+-={}[];'.)";

        final File fileSpecialChars =
                new File(getDownloadDir(), NONMEDIA_FILE_NAME + specialCharsSuffix);

        final File dirSpecialChars =
                new File(getDownloadDir(), TEST_DIRECTORY_NAME + specialCharsSuffix);
        final File file1 = new File(dirSpecialChars, NONMEDIA_FILE_NAME);
        final File fileSpecialChars1 =
                new File(dirSpecialChars, NONMEDIA_FILE_NAME + specialCharsSuffix);

        final File renamedDir = new File(getDocumentsDir(), TEST_DIRECTORY_NAME);
        final File file2 = new File(renamedDir, NONMEDIA_FILE_NAME);
        final File fileSpecialChars2 =
                new File(renamedDir, NONMEDIA_FILE_NAME + specialCharsSuffix);
        try {
            assertTrue(fileSpecialChars.createNewFile());
            if (!dirSpecialChars.exists()) {
                assertTrue(dirSpecialChars.mkdir());
            }
            assertTrue(file1.createNewFile());

            // We can rename file name with special characters
            assertCanRenameFile(fileSpecialChars, fileSpecialChars1);

            // We can rename directory name with special characters
            assertCanRenameDirectory(dirSpecialChars, renamedDir,
                    new File[] {file1, fileSpecialChars1}, new File[] {file2, fileSpecialChars2});
        } finally {
            file1.delete();
            file2.delete();
            fileSpecialChars.delete();
            fileSpecialChars1.delete();
            fileSpecialChars2.delete();
            deleteRecursively(dirSpecialChars);
            deleteRecursively(renamedDir);
        }
    }

    /**
     * Test that IS_PENDING is set for files created via filepath
     */
    @Test
    public void testPendingFromFuse() throws Exception {
        final File pendingFile = new File(getDcimDir(), IMAGE_FILE_NAME);
        final File otherPendingFile = new File(getDcimDir(), VIDEO_FILE_NAME);
        try {
            assertTrue(pendingFile.createNewFile());
            // Newly created file should have IS_PENDING set
            try (Cursor c = queryFile(pendingFile, MediaStore.MediaColumns.IS_PENDING)) {
                assertTrue(c.moveToFirst());
                assertThat(c.getInt(0)).isEqualTo(1);
            }

            // If we query with MATCH_EXCLUDE, we should still see this pendingFile
            try (Cursor c = queryFileExcludingPending(pendingFile,
                    MediaStore.MediaColumns.IS_PENDING)) {
                assertThat(c.getCount()).isEqualTo(1);
                assertTrue(c.moveToFirst());
                assertThat(c.getInt(0)).isEqualTo(1);
            }

            assertNotNull(MediaStore.scanFile(getContentResolver(), pendingFile));

            // IS_PENDING should be unset after the scan
            try (Cursor c = queryFile(pendingFile, MediaStore.MediaColumns.IS_PENDING)) {
                assertTrue(c.moveToFirst());
                assertThat(c.getInt(0)).isEqualTo(0);
            }

            assertCreateFilesAs(APP_A_HAS_RES, otherPendingFile);
            // We can't query other apps pending file from FUSE with MATCH_EXCLUDE
            try (Cursor c = queryFileExcludingPending(otherPendingFile,
                    MediaStore.MediaColumns.IS_PENDING)) {
                assertThat(c.getCount()).isEqualTo(0);
            }
        } finally {
            pendingFile.delete();
            deleteFileAsNoThrow(APP_A_HAS_RES, otherPendingFile.getAbsolutePath());
        }
    }

    /**
     * Test that we don't allow renaming to top level directory
     */
    @Test
    public void testCantRenameToTopLevelDirectory() throws Exception {
        final File topLevelDir1 = new File(getExternalStorageDir(), TEST_DIRECTORY_NAME + "_1");
        final File topLevelDir2 = new File(getExternalStorageDir(), TEST_DIRECTORY_NAME + "_2");
        final File nonTopLevelDir = new File(getDcimDir(), TEST_DIRECTORY_NAME);
        try {
            createDirectoryAsLegacyApp(topLevelDir1);
            assertTrue(topLevelDir1.exists());

            // We can't rename a top level directory to a top level directory
            assertCantRenameDirectory(topLevelDir1, topLevelDir2, null);

            // However, we can rename a top level directory to non-top level directory.
            assertCanRenameDirectory(topLevelDir1, nonTopLevelDir, null, null);

            // We can't rename a non-top level directory to a top level directory.
            assertCantRenameDirectory(nonTopLevelDir, topLevelDir2, null);
        } finally {
            deleteAsLegacyApp(topLevelDir1);
            deleteAsLegacyApp(topLevelDir2);
            deleteRecursively(nonTopLevelDir);
        }
    }

    @Test
    public void testCanCreateDefaultDirectory() throws Exception {
        final File podcastsDir = getPodcastsDir();
        try {
            if (podcastsDir.exists()) {
                deleteAsLegacyApp(podcastsDir);
            }
            assertThat(podcastsDir.mkdir()).isTrue();
        } finally {
            createDirectoryAsLegacyApp(podcastsDir);
        }
    }

    /**
     * b/168830497: Test that app can write to file in DCIM/Camera even with .nomedia presence
     */
    @Test
    public void testCanWriteToDCIMCameraWithNomedia() throws Exception {
        final File cameraDir = new File(getDcimDir(), "Camera");
        final File nomediaFile = new File(cameraDir, ".nomedia");
        Uri targetUri = null;

        try {
            // Recreate required file and directory
            if (cameraDir.exists()) {
                // This is a work around to address a known inode cache inconsistency issue
                // that occurs when test runs for the second time.
                deleteAsLegacyApp(cameraDir);
            }

            createDirectoryAsLegacyApp(cameraDir);
            assertTrue(cameraDir.exists());

            createFileAsLegacyApp(nomediaFile);
            assertTrue(nomediaFile.exists());

            ContentValues values = new ContentValues();
            values.put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM/Camera");
            targetUri = getContentResolver().insert(getImageContentUri(), values, Bundle.EMPTY);
            assertNotNull(targetUri);

            try (ParcelFileDescriptor pfd =
                         getContentResolver().openFileDescriptor(targetUri, "w")) {
                assertThat(pfd).isNotNull();
                Os.write(pfd.getFileDescriptor(), ByteBuffer.wrap(BYTES_DATA1));
            }

            assertFileContent(new File(getFilePathFromUri(targetUri)), BYTES_DATA1);
        } finally {
            deleteWithMediaProviderNoThrow(targetUri);
            deleteAsLegacyApp(nomediaFile);
            deleteAsLegacyApp(cameraDir);
        }
    }

    /**
     * b/182479650: Test that Screenshots directory is not hidden because of .nomedia presence
     */
    @Test
    public void testNoMediaDoesntHideSpecialDirectories() throws Exception {
        for (File directory : new File [] {
                getDcimDir(),
                getDownloadDir(),
                new File(getDcimDir(), "Camera"),
                new File(getPicturesDir(), Environment.DIRECTORY_SCREENSHOTS),
                new File(getMoviesDir(), Environment.DIRECTORY_SCREENSHOTS),
                new File(getExternalStorageDir(), Environment.DIRECTORY_SCREENSHOTS)
        }) {
            assertNoMediaDoesntHideSpecialDirectories(directory);
        }
    }

    private void assertNoMediaDoesntHideSpecialDirectories(File directory) throws Exception {
        final File nomediaFile = new File(directory, ".nomedia");
        final File videoFile = new File(directory, VIDEO_FILE_NAME);
        Log.d(TAG, "Directory " + directory);

        try {
            // Recreate required file and directory
            if (!directory.exists()) {
                Log.d(TAG, "mkdir directory " + directory);
                createDirectoryAsLegacyApp(directory);
            }
            assertWithMessage("Exists " + directory).that(directory.exists()).isTrue();

            Log.d(TAG, "CreateFileAs " + nomediaFile);
            createFileAsLegacyApp(nomediaFile);
            assertWithMessage("Exists " + nomediaFile).that(nomediaFile.exists()).isTrue();

            createFileAsLegacyApp(videoFile);
            assertWithMessage("Exists " + videoFile).that(videoFile.exists()).isTrue();
            final Uri targetUri = MediaStore.scanFile(getContentResolver(), videoFile);
            assertWithMessage("Scan result for " + videoFile).that(targetUri)
                    .isNotNull();

            assertWithMessage("Uri path segment for " + targetUri)
                    .that(targetUri.getPathSegments()).contains("video");

            // Verify that the imageFile is not hidden because of .nomedia presence
            assertWithMessage("Query as other app ")
                    .that(canQueryOnUri(APP_A_HAS_RES, targetUri)).isTrue();
        } finally {
            deleteAsLegacyApp(videoFile);
            deleteAsLegacyApp(nomediaFile);
            deleteAsLegacyApp(directory);
        }
    }

    /**
     * Test that readdir lists unsupported file types in default directories.
     */
    @Test
    public void testListUnsupportedFileType() throws Exception {
        final File pdfFile = new File(getDcimDir(), NONMEDIA_FILE_NAME);
        final File videoFile = new File(getMusicDir(), VIDEO_FILE_NAME);
        try {
            // TEST_APP_A with storage permission should not see pdf file in DCIM
            createFileAsLegacyApp(pdfFile);
            assertThat(pdfFile.exists()).isTrue();
            assertThat(MediaStore.scanFile(getContentResolver(), pdfFile)).isNotNull();

            assertThat(listAs(APP_A_HAS_RES, getDcimDir().getPath()))
                    .doesNotContain(NONMEDIA_FILE_NAME);

            createFileAsLegacyApp(videoFile);
            // We don't insert files to db for files created by shell.
            assertThat(MediaStore.scanFile(getContentResolver(), videoFile)).isNotNull();
            // TEST_APP_A with storage permission should see video file in Music directory.
            assertThat(listAs(APP_A_HAS_RES, getMusicDir().getPath())).contains(VIDEO_FILE_NAME);
        } finally {
            deleteAsLegacyApp(pdfFile);
            deleteAsLegacyApp(videoFile);
            MediaStore.scanFile(getContentResolver(), pdfFile);
            MediaStore.scanFile(getContentResolver(), videoFile);
        }
    }

    /**
     * Test that normal apps cannot access Android/data and Android/obb dirs of other apps
     */
    @Test
    public void testCantAccessOtherAppsExternalDirs() throws Exception {
        File[] obbDirs = getContext().getObbDirs();
        File[] dataDirs = getContext().getExternalFilesDirs(null);
        for (File obbDir : obbDirs) {
            final File otherAppExternalObbDir = new File(obbDir.getPath().replace(
                    THIS_PACKAGE_NAME, APP_B_NO_PERMS.getPackageName()));
            final File file = new File(otherAppExternalObbDir, NONMEDIA_FILE_NAME);
            try {
                assertThat(createFileAs(APP_B_NO_PERMS, file.getPath())).isTrue();
                assertCannotReadOrWrite(file);
            } finally {
                deleteFileAsNoThrow(APP_B_NO_PERMS, file.getAbsolutePath());
            }
        }
        for (File dataDir : dataDirs) {
            final File otherAppExternalDataDir = new File(dataDir.getPath().replace(
                    THIS_PACKAGE_NAME, APP_B_NO_PERMS.getPackageName()));
            final File file = new File(otherAppExternalDataDir, NONMEDIA_FILE_NAME);
            try {
                assertThat(createFileAs(APP_B_NO_PERMS, file.getPath())).isTrue();
                assertCannotReadOrWrite(file);
            } finally {
                deleteFileAsNoThrow(APP_B_NO_PERMS, file.getAbsolutePath());
            }
        }
    }

    /**
     * Test that apps can't set attributes on another app's files.
     */
    @Test
    public void testCantSetAttrOtherAppsFile() throws Exception {
        // This path's permission is checked in MediaProvider (directory/external media dir)
        final File externalMediaPath = new File(getExternalMediaDir(), VIDEO_FILE_NAME);

        try {
            // Create the files
            if (!externalMediaPath.exists()) {
                assertThat(externalMediaPath.createNewFile()).isTrue();
            }

            // APP A should not be able to setattr to other app's files.
            assertWithMessage(
                    "setattr on directory/external media path [%s]", externalMediaPath.getPath())
                    .that(setAttrAs(APP_A_HAS_RES, externalMediaPath.getPath()))
                    .isFalse();
        } finally {
            externalMediaPath.delete();
        }
    }

    /**
     * b/171768780: Test that scan doesn't skip scanning renamed hidden file.
     */
    @Test
    public void testScanUpdatesMetadataForRenamedHiddenFile() throws Exception {
        final File hiddenFile = new File(getPicturesDir(), ".hidden_" + IMAGE_FILE_NAME);
        final File jpgFile = new File(getPicturesDir(), IMAGE_FILE_NAME);
        try {
            // Copy the image content to hidden file
            try (InputStream in =
                         getContext().getResources().openRawResource(R.raw.img_with_metadata);
                 FileOutputStream out = new FileOutputStream(hiddenFile)) {
                FileUtils.copy(in, out);
                out.getFD().sync();
            }
            Uri scanUri = MediaStore.scanFile(getContentResolver(), hiddenFile);
            assertNotNull(scanUri);

            // Rename hidden file to non-hidden
            assertCanRenameFile(hiddenFile, jpgFile);

            try (Cursor c = queryFile(jpgFile, MediaStore.MediaColumns.DATE_TAKEN)) {
                assertTrue(c.moveToFirst());
                // The file is not scanned yet, hence the metadata is not updated yet.
                assertThat(c.getString(0)).isNull();
            }

            // Scan the file to update the metadata for renamed hidden file.
            scanUri = MediaStore.scanFile(getContentResolver(), jpgFile);
            assertNotNull(scanUri);

            // Scan should be able to update metadata even if File.lastModifiedTime hasn't changed.
            try (Cursor c = queryFile(jpgFile, MediaStore.MediaColumns.DATE_TAKEN)) {
                assertTrue(c.moveToFirst());
                assertThat(c.getString(0)).isNotNull();
            }
        } finally {
            hiddenFile.delete();
            jpgFile.delete();
        }
    }

    /**
     * Tests that System Gallery apps cannot insert files in other app's private directories.
     */
    @Test
    public void testCantInsertFilesInOtherAppPrivateDir_hasSystemGallery() throws Exception {
        int uid = Process.myUid();
        try {
            setAppOpsModeForUid(uid, AppOpsManager.MODE_ALLOWED, SYSTEM_GALERY_APPOPS);
            assertCantInsertToOtherPrivateAppDirectories(IMAGE_FILE_NAME,
                    /* throwsExceptionForDataValue */ false, APP_B_NO_PERMS, THIS_PACKAGE_NAME);
        } finally {
            setAppOpsModeForUid(uid, AppOpsManager.MODE_ERRORED, SYSTEM_GALERY_APPOPS);
        }
    }

    /**
     * Tests that System Gallery apps cannot update files in other app's private directories.
     */
    @Test
    public void testCantUpdateFilesInOtherAppPrivateDir_hasSystemGallery() throws Exception {
        int uid = Process.myUid();
        try {
            setAppOpsModeForUid(uid, AppOpsManager.MODE_ALLOWED, SYSTEM_GALERY_APPOPS);
            assertCantUpdateToOtherPrivateAppDirectories(IMAGE_FILE_NAME,
                    /* throwsExceptionForDataValue */ false, APP_B_NO_PERMS, THIS_PACKAGE_NAME);
        } finally {
            setAppOpsModeForUid(uid, AppOpsManager.MODE_ERRORED, SYSTEM_GALERY_APPOPS);
        }
    }

    /**
     * This test is for operations to the calling app's own private packages.
     */
    @Test
    public void testInsertFromExternalDirsViaRelativePath() throws Exception {
        verifyInsertFromExternalMediaDirViaRelativePath_allowed();
        verifyInsertFromExternalPrivateDirViaRelativePath_denied();
    }

    /**
     * This test is for operations to the calling app's own private packages.
     */
    @Test
    public void testUpdateToExternalDirsViaRelativePath() throws Exception {
        verifyUpdateToExternalMediaDirViaRelativePath_allowed();
        verifyUpdateToExternalPrivateDirsViaRelativePath_denied();
    }

    /**
     * This test is for operations to the calling app's own private packages.
     */
    @Test
    public void testInsertFromExternalDirsViaRelativePathAsSystemGallery() throws Exception {
        int uid = Process.myUid();
        try {
            setAppOpsModeForUid(uid, AppOpsManager.MODE_ALLOWED, SYSTEM_GALERY_APPOPS);
            verifyInsertFromExternalMediaDirViaRelativePath_allowed();
            verifyInsertFromExternalPrivateDirViaRelativePath_denied();
        } finally {
            setAppOpsModeForUid(uid, AppOpsManager.MODE_ERRORED, SYSTEM_GALERY_APPOPS);
        }
    }

    /**
     * This test is for operations to the calling app's own private packages.
     */
    @Test
    public void testUpdateToExternalDirsViaRelativePathAsSystemGallery() throws Exception {
        int uid = Process.myUid();
        try {
            setAppOpsModeForUid(uid, AppOpsManager.MODE_ALLOWED, SYSTEM_GALERY_APPOPS);
            verifyUpdateToExternalMediaDirViaRelativePath_allowed();
            verifyUpdateToExternalPrivateDirsViaRelativePath_denied();
        } finally {
            setAppOpsModeForUid(uid, AppOpsManager.MODE_ERRORED, SYSTEM_GALERY_APPOPS);
        }
    }

    @Test
    public void testDeferredScanHidesPartialDatabaseRows() throws Exception {
        ContentValues values = new ContentValues();
        values.put(MediaStore.MediaColumns.IS_PENDING, 1);
        // Insert a pending row
        final Uri targetUri = getContentResolver().insert(getImageContentUri(), values, null);
        try (InputStream in =
                     getContext().getResources().openRawResource(R.raw.img_with_metadata)) {
            try (ParcelFileDescriptor pfd =
                         getContentResolver().openFileDescriptor(targetUri, "w")) {
                // Write image content to the file
                FileUtils.copy(in, new ParcelFileDescriptor.AutoCloseOutputStream(pfd));
            }
        }

        // Verify that metadata is not updated yet.
        try (Cursor c = getContentResolver().query(targetUri, new String[] {
                MediaStore.Images.ImageColumns.DATE_TAKEN}, null, null)) {
            assertThat(c.moveToFirst()).isTrue();
            assertThat(c.getString(0)).isNull();
        }
        // Get file path to use in the next query().
        final String imageFilePath = getFilePathFromUri(targetUri);

        values.put(MediaStore.MediaColumns.IS_PENDING, 0);
        Bundle extras = new Bundle();
        extras.putBoolean(MediaStore.QUERY_ARG_DEFER_SCAN, true);
        // Publish the file, but, defer the scan on update().
        assertThat(getContentResolver().update(targetUri, values, extras)).isEqualTo(1);

        // The update() above can return before scanning is complete. Verify that either we don't
        // see the file in published files or if the file appears in the collection, it means that
        // deferred scan is now complete, hence verify metadata is intact.
        try (Cursor c = getContentResolver().query(getImageContentUri(),
                new String[] {MediaStore.Images.ImageColumns.DATE_TAKEN},
                MediaStore.Files.FileColumns.DATA + "=?", new String[] {imageFilePath}, null)) {
            if (c.getCount() == 1) {
                // If the file appears in media collection as published file, verify that metadata
                // is correct.
                assertThat(c.moveToFirst()).isTrue();
                assertThat(c.getString(0)).isNotNull();
                Log.i(TAG, "Verified that deferred scan on " + imageFilePath + " is complete"
                        + " and hence metadata is updated");

            } else {
                assertThat(c.getCount()).isEqualTo(0);
                Log.i(TAG, "Verified that " + imageFilePath + " was excluded in default query");
            }
        }
    }

    @Test
    @SdkSuppress(minSdkVersion = 31, codeName = "S")
    public void testTransformsDirFileOperations() throws Exception {
        final String path = Environment.getExternalStorageDirectory() + "/" + TRANSFORMS_DIR;
        final File file = new File(path);
        assertThat(file.exists()).isTrue();
        testTransformsDirCommon(file);
    }

    @Test
    @SdkSuppress(minSdkVersion = 31, codeName = "S")
    public void testTransformsSyntheticDirFileOperations() throws Exception {
        final String path =
                Environment.getExternalStorageDirectory() + "/" + TRANSFORMS_SYNTHETIC_DIR;
        final File file = new File(path);
        assertThat(file.exists()).isTrue();
        testTransformsDirCommon(file);
    }

    @Test
    @SdkSuppress(minSdkVersion = 31, codeName = "S")
    public void testTransformsTranscodeDirFileOperations() throws Exception {
        final String path =
                Environment.getExternalStorageDirectory() + "/" + TRANSFORMS_TRANSCODE_DIR;
        final File file = new File(path);
        assertThat(file.exists()).isFalse();
        testTransformsDirCommon(file);
    }


    /**
     * Test mount modes for a platform signed app with ACCESS_MTP permission.
     */
    @Test
    @SdkSuppress(minSdkVersion = 31, codeName = "S")
    public void testMTPAppWithPlatformSignatureMountMode() throws Exception {
        final String shellPackageName = "com.android.shell";
        final int uid = getContext().getPackageManager().getPackageUid(shellPackageName, 0);
        assertMountMode(shellPackageName, uid, StorageManager.MOUNT_MODE_EXTERNAL_ANDROID_WRITABLE);
    }

    /**
     * Test mount modes for ExternalStorageProvider and DownloadsProvider.
     */
    @Test
    @SdkSuppress(minSdkVersion = 31, codeName = "S")
    public void testExternalStorageProviderAndDownloadsProvider() throws Exception {
        assertWritableMountModeForProvider(DocumentsContract.EXTERNAL_STORAGE_PROVIDER_AUTHORITY);
        assertWritableMountModeForProvider(DocumentsContract.DOWNLOADS_PROVIDER_AUTHORITY);
    }

    private void assertWritableMountModeForProvider(String auth) {
        final ProviderInfo provider = getContext().getPackageManager()
                .resolveContentProvider(auth, 0);
        int uid = provider.applicationInfo.uid;
        final String packageName = provider.applicationInfo.packageName;

        assertMountMode(packageName, uid, StorageManager.MOUNT_MODE_EXTERNAL_ANDROID_WRITABLE);
    }

    private boolean canRenameFile(File file) {
        return file.renameTo(new File(file.getAbsolutePath() + "test"));
    }

    private void testTransformsDirCommon(File file) throws Exception {
        assertThat(file.delete()).isFalse();
        assertThat(canRenameFile(file)).isFalse();

        final File newFile = new File(file.getAbsolutePath(), "test");
        assertThat(newFile.mkdir()).isFalse();
        assertThrows(IOException.class, () -> newFile.createNewFile());
    }

    private void assertCanWriteAndRead(File file, byte[] data) throws Exception {
        // Assert we can write to images/videos
        try (FileOutputStream fos = new FileOutputStream(file)) {
            fos.write(data);
        }
        assertFileContent(file, data);
    }

    /**
     * Checks restrictions for opening pending and trashed files by different apps. Assumes that
     * given {@code testApp} is already installed and has READ_EXTERNAL_STORAGE permission. This
     * method doesn't uninstall given {@code testApp} at the end.
     */
    private void assertOpenPendingOrTrashed(Uri uri, boolean isImageOrVideo)
            throws Exception {
        final File pendingOrTrashedFile = new File(getFilePathFromUri(uri));

        // App can open its pending or trashed file for read or write
        assertTrue(canOpen(pendingOrTrashedFile, /*forWrite*/ false));
        assertTrue(canOpen(pendingOrTrashedFile, /*forWrite*/ true));

        // App with READ_EXTERNAL_STORAGE can't open other app's pending or trashed file for read or
        // write
        assertFalse(canOpenFileAs(APP_A_HAS_RES, pendingOrTrashedFile, /*forWrite*/ false));
        assertFalse(canOpenFileAs(APP_A_HAS_RES, pendingOrTrashedFile, /*forWrite*/ true));

        assertTrue(canOpenFileAs(APP_FM, pendingOrTrashedFile, /*forWrite*/ false));
        assertTrue(canOpenFileAs(APP_FM, pendingOrTrashedFile, /*forWrite*/ true));

        final int resAppUid =
                getContext().getPackageManager().getPackageUid(APP_A_HAS_RES.getPackageName(), 0);
        try {
            allowAppOpsToUid(resAppUid, SYSTEM_GALERY_APPOPS);
            if (isImageOrVideo) {
                // System Gallery can open any pending or trashed image/video file for read or write
                assertTrue(isMediaTypeImageOrVideo(pendingOrTrashedFile));
                assertTrue(canOpenFileAs(APP_A_HAS_RES, pendingOrTrashedFile, /*forWrite*/ false));
                assertTrue(canOpenFileAs(APP_A_HAS_RES, pendingOrTrashedFile, /*forWrite*/ true));
            } else {
                // System Gallery can't open other app's pending or trashed non-media file for read
                // or write
                assertFalse(isMediaTypeImageOrVideo(pendingOrTrashedFile));
                assertFalse(canOpenFileAs(APP_A_HAS_RES, pendingOrTrashedFile, /*forWrite*/ false));
                assertFalse(canOpenFileAs(APP_A_HAS_RES, pendingOrTrashedFile, /*forWrite*/ true));
            }
        } finally {
            denyAppOpsToUid(resAppUid, SYSTEM_GALERY_APPOPS);
        }
    }

    /**
     * Checks restrictions for listing pending and trashed files by different apps.
     */
    private void assertListPendingOrTrashed(Uri uri, File file, boolean isImageOrVideo)
            throws Exception {
        final String parentDirPath = file.getParent();
        assertTrue(new File(parentDirPath).isDirectory());

        final List<String> listedFileNames = Arrays.asList(new File(parentDirPath).list());
        assertThat(listedFileNames).doesNotContain(file);

        final File pendingOrTrashedFile = new File(getFilePathFromUri(uri));

        assertThat(listedFileNames).contains(pendingOrTrashedFile.getName());

        // App with READ_EXTERNAL_STORAGE can't see other app's pending or trashed file.
        assertThat(listAs(APP_A_HAS_RES, parentDirPath)).doesNotContain(
                pendingOrTrashedFile.getName());

        final int resAppUid =
                getContext().getPackageManager().getPackageUid(APP_A_HAS_RES.getPackageName(), 0);
        // File Manager can see any pending or trashed file.
        assertThat(listAs(APP_FM, parentDirPath)).contains(pendingOrTrashedFile.getName());


        try {
            allowAppOpsToUid(resAppUid, SYSTEM_GALERY_APPOPS);
            if (isImageOrVideo) {
                // System Gallery can see any pending or trashed image/video file.
                assertTrue(isMediaTypeImageOrVideo(pendingOrTrashedFile));
                assertThat(listAs(APP_A_HAS_RES, parentDirPath)).contains(
                        pendingOrTrashedFile.getName());
            } else {
                // System Gallery can't see other app's pending or trashed non media file.
                assertFalse(isMediaTypeImageOrVideo(pendingOrTrashedFile));
                assertThat(listAs(APP_A_HAS_RES, parentDirPath))
                        .doesNotContain(pendingOrTrashedFile.getName());
            }
        } finally {
            denyAppOpsToUid(resAppUid, SYSTEM_GALERY_APPOPS);
        }
    }

    private Uri createPendingFile(File pendingFile) throws Exception {
        assertTrue(pendingFile.createNewFile());

        final ContentResolver cr = getContentResolver();
        final Uri trashedFileUri = MediaStore.scanFile(cr, pendingFile);
        assertNotNull(trashedFileUri);

        final ContentValues values = new ContentValues();
        values.put(MediaStore.MediaColumns.IS_PENDING, 1);
        assertEquals(1, cr.update(trashedFileUri, values, Bundle.EMPTY));

        return trashedFileUri;
    }

    private Uri createTrashedFile(File trashedFile) throws Exception {
        assertTrue(trashedFile.createNewFile());

        final ContentResolver cr = getContentResolver();
        final Uri trashedFileUri = MediaStore.scanFile(cr, trashedFile);
        assertNotNull(trashedFileUri);

        trashFileAndAssert(trashedFileUri);
        return trashedFileUri;
    }

    /**
     * Gets file path corresponding to the db row pointed by {@code uri}. If {@code uri} points to
     * multiple db rows, file path is extracted from the first db row of the database query result.
     */
    private String getFilePathFromUri(Uri uri) {
        final String[] projection = new String[] {MediaStore.MediaColumns.DATA};
        try (Cursor c = getContentResolver().query(uri, projection, null, null)) {
            assertTrue(c.moveToFirst());
            return c.getString(0);
        }
    }

    private boolean isMediaTypeImageOrVideo(File file) {
        return queryImageFile(file).getCount() == 1 || queryVideoFile(file).getCount() == 1;
    }

    private static void assertIsMediaTypeImage(File file) {
        final Cursor c = queryImageFile(file);
        assertEquals(1, c.getCount());
    }

    private static void assertNotMediaTypeImage(File file) {
        final Cursor c = queryImageFile(file);
        assertEquals(0, c.getCount());
    }

    private static void assertCantQueryFile(File file) {
        assertThat(getFileUri(file)).isNull();
        // Confirm that file exists in the database.
        assertNotNull(MediaStore.scanFile(getContentResolver(), file));
    }

    private static void assertCreateFilesAs(TestApp testApp, File... files) throws Exception {
        for (File file : files) {
            assertFalse("File already exists: " + file, file.exists());
            assertTrue("Failed to create file " + file + " on behalf of "
                    + testApp.getPackageName(), createFileAs(testApp, file.getPath()));
        }
    }

    /**
     * Makes {@code testApp} create {@code files}. Publishes {@code files} by scanning the file.
     * Pending files from FUSE are not visible to other apps via MediaStore APIs. We have to publish
     * the file or make the file non-pending to make the file visible to other apps.
     * <p>
     * Note that this method can only be used for scannable files.
     */
    private static void assertCreatePublishedFilesAs(TestApp testApp, File... files)
            throws Exception {
        for (File file : files) {
            assertTrue("Failed to create published file " + file + " on behalf of "
                    + testApp.getPackageName(), createFileAs(testApp, file.getPath()));
            assertNotNull("Failed to scan " + file,
                    MediaStore.scanFile(getContentResolver(), file));
        }
    }


    private static void deleteFilesAs(TestApp testApp, File... files) throws Exception {
        for (File file : files) {
            deleteFileAs(testApp, file.getPath());
        }
    }
    private static void assertCanDeletePathsAs(TestApp testApp, String... filePaths)
            throws Exception {
        for (String path: filePaths) {
            assertTrue("Failed to delete file " + path + " on behalf of "
                    + testApp.getPackageName(), deleteFileAs(testApp, path));
        }
    }

    private static void assertCantDeletePathsAs(TestApp testApp, String... filePaths)
            throws Exception {
        for (String path: filePaths) {
            assertFalse("Deleting " + path + " on behalf of " + testApp.getPackageName()
                    + " was expected to fail", deleteFileAs(testApp, path));
        }
    }

    private void deleteFiles(File... files) {
        for (File file: files) {
            if (file == null) continue;
            file.delete();
        }
    }

    private void deletePaths(String... paths) {
        for (String path: paths) {
            if (path == null) continue;
            new File(path).delete();
        }
    }

    private static void assertCanDeletePaths(String... filePaths) {
        for (String filePath : filePaths) {
            assertTrue("Failed to delete " + filePath,
                    new File(filePath).delete());
        }
    }

    /**
     * For possible values of {@code mode}, look at {@link android.content.ContentProvider#openFile}
     */
    private static void assertCanQueryAndOpenFile(File file, String mode) throws IOException {
        // This call performs the query
        final Uri fileUri = getFileUri(file);
        // The query succeeds iff it didn't return null
        assertThat(fileUri).isNotNull();
        // Now we assert that we can open the file through ContentResolver
        try (ParcelFileDescriptor pfd =
                     getContentResolver().openFileDescriptor(fileUri, mode)) {
            assertThat(pfd).isNotNull();
        }
    }

    /**
     * Assert that the last read in: read - write - read using {@code readFd} and {@code writeFd}
     * see the last write. {@code readFd} and {@code writeFd} are fds pointing to the same
     * underlying file on disk but may be derived from different mount points and in that case
     * have separate VFS caches.
     */
    private void assertRWR(ParcelFileDescriptor readPfd, ParcelFileDescriptor writePfd)
            throws Exception {
        FileDescriptor readFd = readPfd.getFileDescriptor();
        FileDescriptor writeFd = writePfd.getFileDescriptor();

        byte[] readBuffer = new byte[10];
        byte[] writeBuffer = new byte[10];
        Arrays.fill(writeBuffer, (byte) 1);

        // Write so readFd has content to read from next
        Os.pwrite(readFd, readBuffer, 0, 10, 0);
        // Read so readBuffer is in readFd's mount VFS cache
        Os.pread(readFd, readBuffer, 0, 10, 0);

        // Assert that readBuffer is zeroes
        assertThat(readBuffer).isEqualTo(new byte[10]);

        // Write so writeFd and readFd should now see writeBuffer
        Os.pwrite(writeFd, writeBuffer, 0, 10, 0);

        // Read so the last write can be verified on readFd
        Os.pread(readFd, readBuffer, 0, 10, 0);

        // Assert that the last write is indeed visible via readFd
        assertThat(readBuffer).isEqualTo(writeBuffer);
        assertThat(readPfd.getStatSize()).isEqualTo(writePfd.getStatSize());
    }

    private void assertStartsWith(String actual, String prefix) throws Exception {
        String message = "String \"" + actual + "\" should start with \"" + prefix + "\"";

        assertWithMessage(message).that(actual).startsWith(prefix);
    }

    private void assertLowerFsFd(ParcelFileDescriptor pfd) throws Exception {
        String path = Os.readlink("/proc/self/fd/" + pfd.getFd());
        String prefix = "/storage";

        assertStartsWith(path, prefix);
    }

    private void assertUpperFsFd(ParcelFileDescriptor pfd) throws Exception {
        String path = Os.readlink("/proc/self/fd/" + pfd.getFd());
        String prefix = "/mnt/user";

        assertStartsWith(path, prefix);
    }

    private void assertLowerFsFdWithPassthrough(final String path, ParcelFileDescriptor pfd)
            throws Exception {
        final ContentResolver resolver = getTargetContext().getContentResolver();
        final Bundle res = resolver.call(MediaStore.AUTHORITY, "uses_fuse_passthrough", path, null);
        boolean passthroughEnabled = res.getBoolean("uses_fuse_passthrough_result");

        if (passthroughEnabled) {
            assertUpperFsFd(pfd);
        } else {
            assertLowerFsFd(pfd);
        }
    }

    private static void assertCanCreateFile(File file) throws IOException {
        // If the file somehow managed to survive a previous run, then the test app was uninstalled
        // and MediaProvider will remove our its ownership of the file, so it's not guaranteed that
        // we can create nor delete it.
        if (!file.exists()) {
            assertThat(file.createNewFile()).isTrue();
            assertThat(file.delete()).isTrue();
        } else {
            Log.w(TAG,
                    "Couldn't assertCanCreateFile(" + file + ") because file existed prior to "
                            + "running the test!");
        }
    }

    private static void assertCannotReadOrWrite(File file)
            throws Exception {
        // App data directories have different 'x' bits on upgrading vs new devices. Let's not
        // check 'exists', by passing checkExists=false. But assert this app cannot read or write
        // the other app's file.
        assertAccess(file, false /* value is moot */, false /* canRead */,
                false /* canWrite */, false /* checkExists */);
    }

    private static void assertAccess(File file, boolean exists, boolean canRead, boolean canWrite)
            throws Exception {
        assertAccess(file, exists, canRead, canWrite, true /* checkExists */);
    }

    private static void assertAccess(File file, boolean exists, boolean canRead, boolean canWrite,
            boolean checkExists) throws Exception {
        if (checkExists) {
            assertThat(file.exists()).isEqualTo(exists);
        }
        assertThat(file.canRead()).isEqualTo(canRead);
        assertThat(file.canWrite()).isEqualTo(canWrite);
        if (file.isDirectory()) {
            if (checkExists) {
                assertThat(file.canExecute()).isEqualTo(exists);
            }
        } else {
            assertThat(file.canExecute()).isFalse(); // Filesytem is mounted with MS_NOEXEC
        }

        // Test some combinations of mask.
        assertAccess(file, R_OK, canRead);
        assertAccess(file, W_OK, canWrite);
        assertAccess(file, R_OK | W_OK, canRead && canWrite);
        assertAccess(file, W_OK | F_OK, canWrite);

        if (checkExists) {
            assertAccess(file, F_OK, exists);
        }
    }

    private static void assertAccess(File file, int mask, boolean expected) throws Exception {
        if (expected) {
            assertThat(Os.access(file.getAbsolutePath(), mask)).isTrue();
        } else {
            assertThrows(ErrnoException.class, () -> {
                Os.access(file.getAbsolutePath(), mask);
            });
        }
    }

    /**
     * Creates a file at any location on storage (except external app data directory).
     * The owner of the file is not the caller app.
     */
    private void createFileAsLegacyApp(File file) throws Exception {
        // Use a legacy app to create this file, since it could be outside shared storage.
        Log.d(TAG, "Creating file " + file);
        assertThat(createFileAs(APP_D_LEGACY_HAS_RW, file.getAbsolutePath())).isTrue();
    }

    /**
     * Creates a file at any location on storage (except external app data directory).
     * The owner of the file is not the caller app.
     */
    private void createDirectoryAsLegacyApp(File file) throws Exception {
        // Use a legacy app to create this file, since it could be outside shared storage.
        Log.d(TAG, "Creating directory " + file);
        // Create a tmp file in the target directory, this would also create the required
        // directory, then delete the tmp file. It would leave only new directory.
        assertThat(createFileAs(APP_D_LEGACY_HAS_RW, file.getAbsolutePath() + "/tmp.txt")).isTrue();
        assertThat(deleteFileAs(APP_D_LEGACY_HAS_RW, file.getAbsolutePath() + "/tmp.txt")).isTrue();
    }

    /**
     * Deletes a file or directory at any location on storage (except external app data directory).
     */
    private void deleteAsLegacyApp(File file) throws Exception {
        // Use a legacy app to delete this file, since it could be outside shared storage.
        Log.d(TAG, "Deleting file " + file);
        deleteFileAs(APP_D_LEGACY_HAS_RW, file.getAbsolutePath());
    }

    /**
     * Deletes the given file/directory recursively. If the file is a directory, then deletes all
     * of its children (files or directories) recursively.
     */
    private void deleteRecursivelyAsLegacyApp(File dir) throws Exception {
        // Use a legacy app to delete this directory, since it could be outside shared storage.
        Log.d(TAG, "Deleting directory " + dir);
        deleteRecursivelyAs(APP_D_LEGACY_HAS_RW, dir.getAbsolutePath());
    }
}
