/*
 * 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
    // There is a minor bug which, alghough fixed in sc-dev (aosp/1834457),
    // cannot be propagated to the already released sc-release branche
    // (b/234145920), where mainline-modules are tested.
    // Skip this test in S to avoid failures in outdated targets.
    @SdkSuppress(minSdkVersion = 33, codeName = "T")
    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.
            assertThat(cr.openFileDescriptor(uriVideoFile2, "rw")).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);
            assertThat(cr.openFileDescriptor(uriOfOldFile, "rw")).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.
            assertThat(cr.openFileDescriptor(oldUri, "rw")).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());
    }
}
