/*
 * Copyright (C) 2019 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 com.android.providers.media.util;

import static android.os.ParcelFileDescriptor.MODE_APPEND;
import static android.os.ParcelFileDescriptor.MODE_CREATE;
import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
import static android.os.ParcelFileDescriptor.MODE_TRUNCATE;
import static android.os.ParcelFileDescriptor.MODE_WRITE_ONLY;
import static android.system.OsConstants.F_OK;
import static android.system.OsConstants.O_ACCMODE;
import static android.system.OsConstants.O_APPEND;
import static android.system.OsConstants.O_CLOEXEC;
import static android.system.OsConstants.O_CREAT;
import static android.system.OsConstants.O_NOFOLLOW;
import static android.system.OsConstants.O_RDONLY;
import static android.system.OsConstants.O_RDWR;
import static android.system.OsConstants.O_TRUNC;
import static android.system.OsConstants.O_WRONLY;
import static android.system.OsConstants.R_OK;
import static android.system.OsConstants.S_IRWXG;
import static android.system.OsConstants.S_IRWXU;
import static android.system.OsConstants.W_OK;

import static com.android.providers.media.util.DatabaseUtils.getAsBoolean;
import static com.android.providers.media.util.DatabaseUtils.getAsLong;
import static com.android.providers.media.util.DatabaseUtils.parseBoolean;
import static com.android.providers.media.util.Logging.TAG;

import android.content.ClipDescription;
import android.content.ContentValues;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
import android.os.SystemProperties;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
import android.provider.MediaStore;
import android.provider.MediaStore.MediaColumns;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Log;
import android.webkit.MimeTypeMap;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;

import com.android.modules.utils.build.SdkLevel;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class FileUtils {
    // Even though vfat allows 255 UCS-2 chars, we might eventually write to
    // ext4 through a FUSE layer, so use that limit.
    @VisibleForTesting
    static final int MAX_FILENAME_BYTES = 255;

    /**
     * Drop-in replacement for {@link ParcelFileDescriptor#open(File, int)}
     * which adds security features like {@link OsConstants#O_CLOEXEC} and
     * {@link OsConstants#O_NOFOLLOW}.
     */
    public static @NonNull ParcelFileDescriptor openSafely(@NonNull File file, int pfdFlags)
            throws FileNotFoundException {
        final int posixFlags = translateModePfdToPosix(pfdFlags) | O_CLOEXEC | O_NOFOLLOW;
        try {
            final FileDescriptor fd = Os.open(file.getAbsolutePath(), posixFlags,
                    S_IRWXU | S_IRWXG);
            try {
                return ParcelFileDescriptor.dup(fd);
            } finally {
                closeQuietly(fd);
            }
        } catch (IOException | ErrnoException e) {
            throw new FileNotFoundException(e.getMessage());
        }
    }

    public static void closeQuietly(@Nullable AutoCloseable closeable) {
        android.os.FileUtils.closeQuietly(closeable);
    }

    public static void closeQuietly(@Nullable FileDescriptor fd) {
        if (fd == null) return;
        try {
            Os.close(fd);
        } catch (ErrnoException ignored) {
        }
    }

    public static long copy(@NonNull InputStream in, @NonNull OutputStream out) throws IOException {
        return android.os.FileUtils.copy(in, out);
    }

    public static File buildPath(File base, String... segments) {
        File cur = base;
        for (String segment : segments) {
            if (cur == null) {
                cur = new File(segment);
            } else {
                cur = new File(cur, segment);
            }
        }
        return cur;
    }

    /**
     * Delete older files in a directory until only those matching the given
     * constraints remain.
     *
     * @param minCount Always keep at least this many files.
     * @param minAgeMs Always keep files younger than this age, in milliseconds.
     * @return if any files were deleted.
     */
    public static boolean deleteOlderFiles(File dir, int minCount, long minAgeMs) {
        if (minCount < 0 || minAgeMs < 0) {
            throw new IllegalArgumentException("Constraints must be positive or 0");
        }

        final File[] files = dir.listFiles();
        if (files == null) return false;

        // Sort with newest files first
        Arrays.sort(files, new Comparator<File>() {
            @Override
            public int compare(File lhs, File rhs) {
                return Long.compare(rhs.lastModified(), lhs.lastModified());
            }
        });

        // Keep at least minCount files
        boolean deleted = false;
        for (int i = minCount; i < files.length; i++) {
            final File file = files[i];

            // Keep files newer than minAgeMs
            final long age = System.currentTimeMillis() - file.lastModified();
            if (age > minAgeMs) {
                if (file.delete()) {
                    Log.d(TAG, "Deleted old file " + file);
                    deleted = true;
                }
            }
        }
        return deleted;
    }

    /**
     * Shamelessly borrowed from {@code android.os.FileUtils}.
     */
    public static int translateModeStringToPosix(String mode) {
        // Sanity check for invalid chars
        for (int i = 0; i < mode.length(); i++) {
            switch (mode.charAt(i)) {
                case 'r':
                case 'w':
                case 't':
                case 'a':
                    break;
                default:
                    throw new IllegalArgumentException("Bad mode: " + mode);
            }
        }

        int res = 0;
        if (mode.startsWith("rw")) {
            res = O_RDWR | O_CREAT;
        } else if (mode.startsWith("w")) {
            res = O_WRONLY | O_CREAT;
        } else if (mode.startsWith("r")) {
            res = O_RDONLY;
        } else {
            throw new IllegalArgumentException("Bad mode: " + mode);
        }
        if (mode.indexOf('t') != -1) {
            res |= O_TRUNC;
        }
        if (mode.indexOf('a') != -1) {
            res |= O_APPEND;
        }
        return res;
    }

    /**
     * Shamelessly borrowed from {@code android.os.FileUtils}.
     */
    public static String translateModePosixToString(int mode) {
        String res = "";
        if ((mode & O_ACCMODE) == O_RDWR) {
            res = "rw";
        } else if ((mode & O_ACCMODE) == O_WRONLY) {
            res = "w";
        } else if ((mode & O_ACCMODE) == O_RDONLY) {
            res = "r";
        } else {
            throw new IllegalArgumentException("Bad mode: " + mode);
        }
        if ((mode & O_TRUNC) == O_TRUNC) {
            res += "t";
        }
        if ((mode & O_APPEND) == O_APPEND) {
            res += "a";
        }
        return res;
    }

    /**
     * Shamelessly borrowed from {@code android.os.FileUtils}.
     */
    public static int translateModePosixToPfd(int mode) {
        int res = 0;
        if ((mode & O_ACCMODE) == O_RDWR) {
            res = MODE_READ_WRITE;
        } else if ((mode & O_ACCMODE) == O_WRONLY) {
            res = MODE_WRITE_ONLY;
        } else if ((mode & O_ACCMODE) == O_RDONLY) {
            res = MODE_READ_ONLY;
        } else {
            throw new IllegalArgumentException("Bad mode: " + mode);
        }
        if ((mode & O_CREAT) == O_CREAT) {
            res |= MODE_CREATE;
        }
        if ((mode & O_TRUNC) == O_TRUNC) {
            res |= MODE_TRUNCATE;
        }
        if ((mode & O_APPEND) == O_APPEND) {
            res |= MODE_APPEND;
        }
        return res;
    }

    /**
     * Shamelessly borrowed from {@code android.os.FileUtils}.
     */
    public static int translateModePfdToPosix(int mode) {
        int res = 0;
        if ((mode & MODE_READ_WRITE) == MODE_READ_WRITE) {
            res = O_RDWR;
        } else if ((mode & MODE_WRITE_ONLY) == MODE_WRITE_ONLY) {
            res = O_WRONLY;
        } else if ((mode & MODE_READ_ONLY) == MODE_READ_ONLY) {
            res = O_RDONLY;
        } else {
            throw new IllegalArgumentException("Bad mode: " + mode);
        }
        if ((mode & MODE_CREATE) == MODE_CREATE) {
            res |= O_CREAT;
        }
        if ((mode & MODE_TRUNCATE) == MODE_TRUNCATE) {
            res |= O_TRUNC;
        }
        if ((mode & MODE_APPEND) == MODE_APPEND) {
            res |= O_APPEND;
        }
        return res;
    }

    /**
     * Shamelessly borrowed from {@code android.os.FileUtils}.
     */
    public static int translateModeAccessToPosix(int mode) {
        if (mode == F_OK) {
            // There's not an exact mapping, so we attempt a read-only open to
            // determine if a file exists
            return O_RDONLY;
        } else if ((mode & (R_OK | W_OK)) == (R_OK | W_OK)) {
            return O_RDWR;
        } else if ((mode & R_OK) == R_OK) {
            return O_RDONLY;
        } else if ((mode & W_OK) == W_OK) {
            return O_WRONLY;
        } else {
            throw new IllegalArgumentException("Bad mode: " + mode);
        }
    }

    /**
     * Test if a file lives under the given directory, either as a direct child
     * or a distant grandchild.
     * <p>
     * Both files <em>must</em> have been resolved using
     * {@link File#getCanonicalFile()} to avoid symlink or path traversal
     * attacks.
     *
     * @hide
     */
    public static boolean contains(File[] dirs, File file) {
        for (File dir : dirs) {
            if (contains(dir, file)) {
                return true;
            }
        }
        return false;
    }

    /** {@hide} */
    public static boolean contains(Collection<File> dirs, File file) {
        for (File dir : dirs) {
            if (contains(dir, file)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Test if a file lives under the given directory, either as a direct child
     * or a distant grandchild.
     * <p>
     * Both files <em>must</em> have been resolved using
     * {@link File#getCanonicalFile()} to avoid symlink or path traversal
     * attacks.
     *
     * @hide
     */
    public static boolean contains(File dir, File file) {
        if (dir == null || file == null) return false;
        return contains(dir.getAbsolutePath(), file.getAbsolutePath());
    }

    /**
     * Test if a file lives under the given directory, either as a direct child
     * or a distant grandchild.
     * <p>
     * Both files <em>must</em> have been resolved using
     * {@link File#getCanonicalFile()} to avoid symlink or path traversal
     * attacks.
     *
     * @hide
     */
    public static boolean contains(String dirPath, String filePath) {
        if (dirPath.equals(filePath)) {
            return true;
        }
        if (!dirPath.endsWith("/")) {
            dirPath += "/";
        }
        return filePath.startsWith(dirPath);
    }

    /**
     * Write {@link String} to the given {@link File}. Deletes any existing file
     * when the argument is {@link Optional#empty()}.
     */
    public static void writeString(@NonNull File file, @NonNull Optional<String> value)
            throws IOException {
        if (value.isPresent()) {
            Files.write(file.toPath(), value.get().getBytes(StandardCharsets.UTF_8));
        } else {
            file.delete();
        }
    }

    private static final int MAX_READ_STRING_SIZE = 4096;

    /**
     * Read given {@link File} as a single {@link String}. Returns
     * {@link Optional#empty()} when
     * <ul>
     * <li> the file doesn't exist or
     * <li> the size of the file exceeds {@code MAX_READ_STRING_SIZE}
     * </ul>
     */
    public static @NonNull Optional<String> readString(@NonNull File file) throws IOException {
        try {
            if (file.length() <= MAX_READ_STRING_SIZE) {
                final String value = new String(Files.readAllBytes(file.toPath()),
                        StandardCharsets.UTF_8);
                return Optional.of(value);
            }
            // When file size exceeds MAX_READ_STRING_SIZE, file is either
            // corrupted or doesn't the contain expected data. Hence we return
            // Optional.empty() which will be interpreted as empty file.
            Logging.logPersistent(String.format("Ignored reading %s, file size exceeds %d", file,
                    MAX_READ_STRING_SIZE));
        } catch (NoSuchFileException ignored) {
        }
        return Optional.empty();
    }

    /**
     * Recursively walk the contents of the given {@link Path}, invoking the
     * given {@link Consumer} for every file and directory encountered. This is
     * typically used for recursively deleting a directory tree.
     * <p>
     * Gracefully attempts to process as much as possible in the face of any
     * failures.
     */
    public static void walkFileTreeContents(@NonNull Path path, @NonNull Consumer<Path> operation) {
        try {
            Files.walkFileTree(path, new FileVisitor<Path>() {
                @Override
                public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
                    if (!Objects.equals(path, file)) {
                        operation.accept(file);
                    }
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult visitFileFailed(Path file, IOException e) {
                    Log.w(TAG, "Failed to visit " + file, e);
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult postVisitDirectory(Path dir, IOException e) {
                    if (!Objects.equals(path, dir)) {
                        operation.accept(dir);
                    }
                    return FileVisitResult.CONTINUE;
                }
            });
        } catch (IOException e) {
            Log.w(TAG, "Failed to walk " + path, e);
        }
    }

    /**
     * Recursively delete all contents inside the given directory. Gracefully
     * attempts to delete as much as possible in the face of any failures.
     *
     * @deprecated if you're calling this from inside {@code MediaProvider}, you
     *             likely want to call {@link #forEach} with a separate
     *             invocation to invalidate FUSE entries.
     */
    @Deprecated
    public static void deleteContents(@NonNull File dir) {
        walkFileTreeContents(dir.toPath(), (path) -> {
            path.toFile().delete();
        });
    }

    private static boolean isValidFatFilenameChar(char c) {
        if ((0x00 <= c && c <= 0x1f)) {
            return false;
        }
        switch (c) {
            case '"':
            case '*':
            case '/':
            case ':':
            case '<':
            case '>':
            case '?':
            case '\\':
            case '|':
            case 0x7F:
                return false;
            default:
                return true;
        }
    }

    /**
     * Check if given filename is valid for a FAT filesystem.
     *
     * @hide
     */
    public static boolean isValidFatFilename(String name) {
        return (name != null) && name.equals(buildValidFatFilename(name));
    }

    /**
     * Mutate the given filename to make it valid for a FAT filesystem,
     * replacing any invalid characters with "_".
     *
     * @hide
     */
    public static String buildValidFatFilename(String name) {
        if (TextUtils.isEmpty(name) || ".".equals(name) || "..".equals(name)) {
            return "(invalid)";
        }
        final StringBuilder res = new StringBuilder(name.length());
        for (int i = 0; i < name.length(); i++) {
            final char c = name.charAt(i);
            if (isValidFatFilenameChar(c)) {
                res.append(c);
            } else {
                res.append('_');
            }
        }

        trimFilename(res, MAX_FILENAME_BYTES);
        return res.toString();
    }

    /** {@hide} */
    // @VisibleForTesting
    public static String trimFilename(String str, int maxBytes) {
        final StringBuilder res = new StringBuilder(str);
        trimFilename(res, maxBytes);
        return res.toString();
    }

    /** {@hide} */
    private static void trimFilename(StringBuilder res, int maxBytes) {
        byte[] raw = res.toString().getBytes(StandardCharsets.UTF_8);
        if (raw.length > maxBytes) {
            maxBytes -= 3;
            while (raw.length > maxBytes) {
                res.deleteCharAt(res.length() / 2);
                raw = res.toString().getBytes(StandardCharsets.UTF_8);
            }
            res.insert(res.length() / 2, "...");
        }
    }

    /** {@hide} */
    private static File buildUniqueFileWithExtension(File parent, String name, String ext)
            throws FileNotFoundException {
        final Iterator<String> names = buildUniqueNameIterator(parent, name);
        while (names.hasNext()) {
            File file = buildFile(parent, names.next(), ext);
            if (!file.exists()) {
                return file;
            }
        }
        throw new FileNotFoundException("Failed to create unique file");
    }

    private static final Pattern PATTERN_DCF_STRICT = Pattern
            .compile("([A-Z0-9_]{4})([0-9]{4})");
    private static final Pattern PATTERN_DCF_RELAXED = Pattern
            .compile("((?:IMG|MVIMG|VID)_[0-9]{8}_[0-9]{6})(?:~([0-9]+))?");

    private static boolean isDcim(@NonNull File dir) {
        while (dir != null) {
            if (Objects.equals("DCIM", dir.getName())) {
                return true;
            }
            dir = dir.getParentFile();
        }
        return false;
    }

    private static @NonNull Iterator<String> buildUniqueNameIterator(@NonNull File parent,
            @NonNull String name) {
        if (isDcim(parent)) {
            final Matcher dcfStrict = PATTERN_DCF_STRICT.matcher(name);
            if (dcfStrict.matches()) {
                // Generate names like "IMG_1001"
                final String prefix = dcfStrict.group(1);
                return new Iterator<String>() {
                    int i = Integer.parseInt(dcfStrict.group(2));
                    @Override
                    public String next() {
                        final String res = String.format(Locale.US, "%s%04d", prefix, i);
                        i++;
                        return res;
                    }
                    @Override
                    public boolean hasNext() {
                        return i <= 9999;
                    }
                };
            }

            final Matcher dcfRelaxed = PATTERN_DCF_RELAXED.matcher(name);
            if (dcfRelaxed.matches()) {
                // Generate names like "IMG_20190102_030405~2"
                final String prefix = dcfRelaxed.group(1);
                return new Iterator<String>() {
                    int i = TextUtils.isEmpty(dcfRelaxed.group(2))
                            ? 1
                            : Integer.parseInt(dcfRelaxed.group(2));
                    @Override
                    public String next() {
                        final String res = (i == 1)
                            ? prefix
                            : String.format(Locale.US, "%s~%d", prefix, i);
                        i++;
                        return res;
                    }
                    @Override
                    public boolean hasNext() {
                        return i <= 99;
                    }
                };
            }
        }

        // Generate names like "foo (2)"
        return new Iterator<String>() {
            int i = 0;
            @Override
            public String next() {
                final String res = (i == 0) ? name : name + " (" + i + ")";
                i++;
                return res;
            }
            @Override
            public boolean hasNext() {
                return i < 32;
            }
        };
    }

    /**
     * Generates a unique file name under the given parent directory. If the display name doesn't
     * have an extension that matches the requested MIME type, the default extension for that MIME
     * type is appended. If a file already exists, the name is appended with a numerical value to
     * make it unique.
     *
     * For example, the display name 'example' with 'text/plain' MIME might produce
     * 'example.txt' or 'example (1).txt', etc.
     *
     * @throws FileNotFoundException
     * @hide
     */
    public static File buildUniqueFile(File parent, String mimeType, String displayName)
            throws FileNotFoundException {
        final String[] parts = splitFileName(mimeType, displayName);
        return buildUniqueFileWithExtension(parent, parts[0], parts[1]);
    }

    /** {@hide} */
    public static File buildNonUniqueFile(File parent, String mimeType, String displayName) {
        final String[] parts = splitFileName(mimeType, displayName);
        return buildFile(parent, parts[0], parts[1]);
    }

    /**
     * Generates a unique file name under the given parent directory, keeping
     * any extension intact.
     *
     * @hide
     */
    public static File buildUniqueFile(File parent, String displayName)
            throws FileNotFoundException {
        final String name;
        final String ext;

        // Extract requested extension from display name
        final int lastDot = displayName.lastIndexOf('.');
        if (lastDot >= 0) {
            name = displayName.substring(0, lastDot);
            ext = displayName.substring(lastDot + 1);
        } else {
            name = displayName;
            ext = null;
        }

        return buildUniqueFileWithExtension(parent, name, ext);
    }

    /**
     * Splits file name into base name and extension.
     * If the display name doesn't have an extension that matches the requested MIME type, the
     * extension is regarded as a part of filename and default extension for that MIME type is
     * appended.
     *
     * @hide
     */
    public static String[] splitFileName(String mimeType, String displayName) {
        String name;
        String ext;

        {
            String mimeTypeFromExt;

            // Extract requested extension from display name
            final int lastDot = displayName.lastIndexOf('.');
            if (lastDot > 0) {
                name = displayName.substring(0, lastDot);
                ext = displayName.substring(lastDot + 1);
                mimeTypeFromExt = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
                        ext.toLowerCase(Locale.ROOT));
            } else {
                name = displayName;
                ext = null;
                mimeTypeFromExt = null;
            }

            if (mimeTypeFromExt == null) {
                mimeTypeFromExt = ClipDescription.MIMETYPE_UNKNOWN;
            }

            final String extFromMimeType;
            if (ClipDescription.MIMETYPE_UNKNOWN.equalsIgnoreCase(mimeType)) {
                extFromMimeType = null;
            } else {
                extFromMimeType = MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType);
            }

            if (StringUtils.equalIgnoreCase(mimeType, mimeTypeFromExt)
                    || StringUtils.equalIgnoreCase(ext, extFromMimeType)) {
                // Extension maps back to requested MIME type; allow it
            } else {
                // No match; insist that create file matches requested MIME
                name = displayName;
                ext = extFromMimeType;
            }
        }

        if (ext == null) {
            ext = "";
        }

        return new String[] { name, ext };
    }

    /** {@hide} */
    private static File buildFile(File parent, String name, String ext) {
        if (TextUtils.isEmpty(ext)) {
            return new File(parent, name);
        } else {
            return new File(parent, name + "." + ext);
        }
    }

    public static @Nullable String extractDisplayName(@Nullable String data) {
        if (data == null) return null;
        if (data.indexOf('/') == -1) {
            return data;
        }
        if (data.endsWith("/")) {
            data = data.substring(0, data.length() - 1);
        }
        return data.substring(data.lastIndexOf('/') + 1);
    }

    public static @Nullable String extractFileName(@Nullable String data) {
        if (data == null) return null;
        data = extractDisplayName(data);

        final int lastDot = data.lastIndexOf('.');
        if (lastDot == -1) {
            return data;
        } else {
            return data.substring(0, lastDot);
        }
    }

    public static @Nullable String extractFileExtension(@Nullable String data) {
        if (data == null) return null;
        data = extractDisplayName(data);

        final int lastDot = data.lastIndexOf('.');
        if (lastDot == -1) {
            return null;
        } else {
            return data.substring(lastDot + 1);
        }
    }

    /**
     * Return list of paths that should be scanned with
     * {@link com.android.providers.media.scan.MediaScanner} for the given
     * volume name.
     */
    public static @NonNull Collection<File> getVolumeScanPaths(@NonNull Context context,
            @NonNull String volumeName) throws FileNotFoundException {
        final ArrayList<File> res = new ArrayList<>();
        switch (volumeName) {
            case MediaStore.VOLUME_INTERNAL: {
                res.addAll(Environment.getInternalMediaDirectories());
                break;
            }
            case MediaStore.VOLUME_EXTERNAL: {
                for (String resolvedVolumeName : MediaStore.getExternalVolumeNames(context)) {
                    res.add(getVolumePath(context, resolvedVolumeName));
                }
                break;
            }
            default: {
                res.add(getVolumePath(context, volumeName));
            }
        }
        return res;
    }

    /**
     * Return path where the given volume name is mounted.
     */
    public static @NonNull File getVolumePath(@NonNull Context context,
            @NonNull String volumeName) throws FileNotFoundException {
        switch (volumeName) {
            case MediaStore.VOLUME_INTERNAL:
            case MediaStore.VOLUME_EXTERNAL:
                throw new FileNotFoundException(volumeName + " has no associated path");
        }

        final Uri uri = MediaStore.Files.getContentUri(volumeName);
        File path = null;

        try {
            path = context.getSystemService(StorageManager.class).getStorageVolume(uri)
                    .getDirectory();
        } catch (IllegalStateException e) {
            Log.w("Ignoring volume not found exception", e);
        }

        if (path != null) {
            return path;
        } else {
            throw new FileNotFoundException(volumeName + " has no associated path");
        }
    }

    /**
     * Returns the content URI for the volume that contains the given path.
     *
     * <p>{@link MediaStore.Files#getContentUriForPath(String)} can't detect public volumes and can
     * only return the URI for the primary external storage, that's why this utility should be used
     * instead.
     */
    public static @NonNull Uri getContentUriForPath(@NonNull String path) {
        Objects.requireNonNull(path);
        return MediaStore.Files.getContentUri(extractVolumeName(path));
    }

    /**
     * Return StorageVolume corresponding to the file on Path
     */
    public static @NonNull StorageVolume getStorageVolume(@NonNull Context context,
            @NonNull File path) throws FileNotFoundException {
        int userId = extractUserId(path.getPath());
        Context userContext = context;
        if (userId >= 0 && (context.getUser().getIdentifier() != userId)) {
            // This volume is for a different user than our context, create a context
            // for that user to retrieve the correct volume.
            try {
                userContext = context.createPackageContextAsUser("system", 0,
                        UserHandle.of(userId));
            } catch (PackageManager.NameNotFoundException e) {
                throw new FileNotFoundException("Can't get package context for user " + userId);
            }
        }

        StorageVolume volume = userContext.getSystemService(StorageManager.class)
                .getStorageVolume(path);
        if (volume == null) {
            throw new FileNotFoundException("Can't find volume for " + path.getPath());
        }

        return volume;
    }

    /**
     * Return volume name which hosts the given path.
     */
    public static @NonNull String getVolumeName(@NonNull Context context, @NonNull File path)
            throws FileNotFoundException {
        if (contains(Environment.getStorageDirectory(), path)) {
            StorageVolume volume = getStorageVolume(context, path);
            return volume.getMediaStoreVolumeName();
        } else {
            return MediaStore.VOLUME_INTERNAL;
        }
    }

    public static final Pattern PATTERN_DOWNLOADS_FILE = Pattern.compile(
            "(?i)^/storage/[^/]+/(?:[0-9]+/)?Download/.+");
    public static final Pattern PATTERN_DOWNLOADS_DIRECTORY = Pattern.compile(
            "(?i)^/storage/[^/]+/(?:[0-9]+/)?Download/?");
    public static final Pattern PATTERN_EXPIRES_FILE = Pattern.compile(
            "(?i)^\\.(pending|trashed)-(\\d+)-([^/]+)$");
    public static final Pattern PATTERN_PENDING_FILEPATH_FOR_SQL = Pattern.compile(
            ".*/\\.pending-(\\d+)-([^/]+)$");

    /**
     * File prefix indicating that the file {@link MediaColumns#IS_PENDING}.
     */
    public static final String PREFIX_PENDING = "pending";

    /**
     * File prefix indicating that the file {@link MediaColumns#IS_TRASHED}.
     */
    public static final String PREFIX_TRASHED = "trashed";

    /**
     * Default duration that {@link MediaColumns#IS_PENDING} items should be
     * preserved for until automatically cleaned by {@link #runIdleMaintenance}.
     */
    public static final long DEFAULT_DURATION_PENDING = 7 * DateUtils.DAY_IN_MILLIS;

    /**
     * Default duration that {@link MediaColumns#IS_TRASHED} items should be
     * preserved for until automatically cleaned by {@link #runIdleMaintenance}.
     */
    public static final long DEFAULT_DURATION_TRASHED = 30 * DateUtils.DAY_IN_MILLIS;

    /**
     * Default duration that expired items should be extended in
     * {@link #runIdleMaintenance}.
     */
    public static final long DEFAULT_DURATION_EXTENDED = 7 * DateUtils.DAY_IN_MILLIS;

    public static boolean isDownload(@NonNull String path) {
        return PATTERN_DOWNLOADS_FILE.matcher(path).matches();
    }

    public static boolean isDownloadDir(@NonNull String path) {
        return PATTERN_DOWNLOADS_DIRECTORY.matcher(path).matches();
    }

    private static final boolean PROP_CROSS_USER_ALLOWED =
            SystemProperties.getBoolean("external_storage.cross_user.enabled", false);

    private static final String PROP_CROSS_USER_ROOT = isCrossUserEnabled()
            ? SystemProperties.get("external_storage.cross_user.root", "") : "";

    private static final String PROP_CROSS_USER_ROOT_PATTERN = ((PROP_CROSS_USER_ROOT.isEmpty())
            ? "" : "(?:" + PROP_CROSS_USER_ROOT + "/)?");

    /**
     * Regex that matches paths in all well-known package-specific directories,
     * and which captures the package name as the first group.
     */
    public static final Pattern PATTERN_OWNED_PATH = Pattern.compile(
            "(?i)^/storage/[^/]+/(?:[0-9]+/)?"
            + PROP_CROSS_USER_ROOT_PATTERN
            + "Android/(?:data|media|obb)/([^/]+)(/?.*)?");

    /**
     * Regex that matches paths in all well-known package-specific relative directory
     * path (as defined in {@link MediaColumns#RELATIVE_PATH})
     * and which captures the package name as the first group.
     */
    private static final Pattern PATTERN_OWNED_RELATIVE_PATH = Pattern.compile(
            "(?i)^Android/(?:data|media|obb)/([^/]+)(/?.*)?");

    /**
     * Regex that matches Android/obb or Android/data path.
     */
    private static final Pattern PATTERN_DATA_OR_OBB_PATH = Pattern.compile(
            "(?i)^/storage/[^/]+/(?:[0-9]+/)?"
            + PROP_CROSS_USER_ROOT_PATTERN
            + "Android/(?:data|obb)(?:/.*)?$");

    /**
     * Regex that matches Android/obb or Android/data relative path (as defined in
     * {@link MediaColumns#RELATIVE_PATH})
     */
    private static final Pattern PATTERN_DATA_OR_OBB_RELATIVE_PATH = Pattern.compile(
            "(?i)^Android/(?:data|obb)(?:/.*)?$");

    /**
     * Regex that matches Android/obb {@link MediaColumns#RELATIVE_PATH}.
     */
    private static final Pattern PATTERN_OBB_OR_CHILD_RELATIVE_PATH = Pattern.compile(
            "(?i)^Android/obb(?:/.*)?$");

    private static final Pattern PATTERN_VISIBLE = Pattern.compile(
            "(?i)^/storage/[^/]+(?:/[0-9]+)?$");

    private static final Pattern PATTERN_INVISIBLE = Pattern.compile(
            "(?i)^/storage/[^/]+(?:/[0-9]+)?/"
                    + "(?:(?:Android/(?:data|obb|sandbox)$)|"
                    + "(?:\\.transforms$)|"
                    + "(?:(?:Movies|Music|Pictures)/.thumbnails$))");

    /**
     * The recordings directory. This is used for R OS. For S OS or later,
     * we use {@link Environment#DIRECTORY_RECORDINGS} directly.
     */
    public static final String DIRECTORY_RECORDINGS = "Recordings";

    @VisibleForTesting
    public static final String[] DEFAULT_FOLDER_NAMES;
    static {
        if (SdkLevel.isAtLeastS()) {
            DEFAULT_FOLDER_NAMES = new String[]{
                    Environment.DIRECTORY_MUSIC,
                    Environment.DIRECTORY_PODCASTS,
                    Environment.DIRECTORY_RINGTONES,
                    Environment.DIRECTORY_ALARMS,
                    Environment.DIRECTORY_NOTIFICATIONS,
                    Environment.DIRECTORY_PICTURES,
                    Environment.DIRECTORY_MOVIES,
                    Environment.DIRECTORY_DOWNLOADS,
                    Environment.DIRECTORY_DCIM,
                    Environment.DIRECTORY_DOCUMENTS,
                    Environment.DIRECTORY_AUDIOBOOKS,
                    Environment.DIRECTORY_RECORDINGS,
            };
        } else {
            DEFAULT_FOLDER_NAMES = new String[]{
                    Environment.DIRECTORY_MUSIC,
                    Environment.DIRECTORY_PODCASTS,
                    Environment.DIRECTORY_RINGTONES,
                    Environment.DIRECTORY_ALARMS,
                    Environment.DIRECTORY_NOTIFICATIONS,
                    Environment.DIRECTORY_PICTURES,
                    Environment.DIRECTORY_MOVIES,
                    Environment.DIRECTORY_DOWNLOADS,
                    Environment.DIRECTORY_DCIM,
                    Environment.DIRECTORY_DOCUMENTS,
                    Environment.DIRECTORY_AUDIOBOOKS,
                    DIRECTORY_RECORDINGS,
            };
        }
    }

    /**
     * Regex that matches paths for {@link MediaColumns#RELATIVE_PATH}
     */
    private static final Pattern PATTERN_RELATIVE_PATH = Pattern.compile(
            "(?i)^/storage/(?:emulated/[0-9]+/|[^/]+/)");

    /**
     * Regex that matches paths under well-known storage paths.
     */
    private static final Pattern PATTERN_VOLUME_NAME = Pattern.compile(
            "(?i)^/storage/([^/]+)");

    /**
     * Regex that matches user-ids under well-known storage paths.
     */
    private static final Pattern PATTERN_USER_ID = Pattern.compile(
            "(?i)^/storage/emulated/([0-9]+)");

    private static final String CAMERA_RELATIVE_PATH =
            String.format("%s/%s/", Environment.DIRECTORY_DCIM, "Camera");

    public static boolean isCrossUserEnabled() {
        return PROP_CROSS_USER_ALLOWED || SdkLevel.isAtLeastS();
    }

    private static @Nullable String normalizeUuid(@Nullable String fsUuid) {
        return fsUuid != null ? fsUuid.toLowerCase(Locale.ROOT) : null;
    }

    public static int extractUserId(@Nullable String data) {
        if (data == null) return -1;
        final Matcher matcher = PATTERN_USER_ID.matcher(data);
        if (matcher.find()) {
            return Integer.parseInt(matcher.group(1));
        }

        return -1;
    }

    public static @Nullable String extractVolumePath(@Nullable String data) {
        if (data == null) return null;
        final Matcher matcher = PATTERN_RELATIVE_PATH.matcher(data);
        if (matcher.find()) {
            return data.substring(0, matcher.end());
        } else {
            return null;
        }
    }

    public static @Nullable String extractVolumeName(@Nullable String data) {
        if (data == null) return null;
        final Matcher matcher = PATTERN_VOLUME_NAME.matcher(data);
        if (matcher.find()) {
            final String volumeName = matcher.group(1);
            if (volumeName.equals("emulated")) {
                return MediaStore.VOLUME_EXTERNAL_PRIMARY;
            } else {
                return normalizeUuid(volumeName);
            }
        } else {
            return MediaStore.VOLUME_INTERNAL;
        }
    }

    public static @Nullable String extractRelativePath(@Nullable String data) {
        if (data == null) return null;
        final Matcher matcher = PATTERN_RELATIVE_PATH.matcher(data);
        if (matcher.find()) {
            final int lastSlash = data.lastIndexOf('/');
            if (lastSlash == -1 || lastSlash < matcher.end()) {
                // This is a file in the top-level directory, so relative path is "/"
                // which is different than null, which means unknown path
                return "/";
            } else {
                return data.substring(matcher.end(), lastSlash + 1);
            }
        } else {
            return null;
        }
    }

    /**
     * Returns relative path with display name.
     */
    @VisibleForTesting
    public static @Nullable String extractRelativePathWithDisplayName(@Nullable String path) {
        if (path == null) return null;

        if (path.equals("/storage/emulated") || path.equals("/storage/emulated/")) {
            // This path is not reachable for MediaProvider.
            return null;
        }

        // We are extracting relative path for the directory itself, we add "/" so that we can use
        // same PATTERN_RELATIVE_PATH to match relative path for directory. For example, relative
        // path of '/storage/<volume_name>' is null where as relative path for directory is "/", for
        // PATTERN_RELATIVE_PATH to match '/storage/<volume_name>', it should end with "/".
        if (!path.endsWith("/")) {
            // Relative path for directory should end with "/".
            path += "/";
        }

        final Matcher matcher = PATTERN_RELATIVE_PATH.matcher(path);
        if (matcher.find()) {
            if (matcher.end() == path.length()) {
                // This is the top-level directory, so relative path is "/"
                return "/";
            }
            return path.substring(matcher.end());
        }
        return null;
    }

    public static @Nullable String extractPathOwnerPackageName(@Nullable String path) {
        if (path == null) return null;
        final Matcher m = PATTERN_OWNED_PATH.matcher(path);
        if (m.matches()) {
            return m.group(1);
        }
        return null;
    }

    public static @Nullable String extractOwnerPackageNameFromRelativePath(@Nullable String path) {
        if (path == null) return null;
        final Matcher m = PATTERN_OWNED_RELATIVE_PATH.matcher(path);
        if (m.matches()) {
            return m.group(1);
        }
        return null;
    }

    public static boolean isExternalMediaDirectory(@NonNull String path) {
        return isExternalMediaDirectory(path, PROP_CROSS_USER_ROOT);
    }

    @VisibleForTesting
    static boolean isExternalMediaDirectory(@NonNull String path, String crossUserRoot) {
        final String relativePath = extractRelativePath(path);
        if (relativePath == null) {
            return false;
        }

        if (StringUtils.startsWithIgnoreCase(relativePath, "Android/media")) {
            return true;
        }
        if (!TextUtils.isEmpty(crossUserRoot)) {
            return StringUtils.startsWithIgnoreCase(relativePath, crossUserRoot + "/Android/media");
        }

        return false;
    }

    /**
     * Returns true if path is Android/data or Android/obb path.
     */
    public static boolean isDataOrObbPath(@Nullable String path) {
        if (path == null) return false;
        final Matcher m = PATTERN_DATA_OR_OBB_PATH.matcher(path);
        return m.matches();
    }

    /**
     * Returns true if relative path is Android/data or Android/obb path.
     */
    public static boolean isDataOrObbRelativePath(@Nullable String path) {
        if (path == null) return false;
        final Matcher m = PATTERN_DATA_OR_OBB_RELATIVE_PATH.matcher(path);
        return m.matches();
    }

    /**
     * Returns true if relative path is Android/obb path.
     */
    public static boolean isObbOrChildRelativePath(@Nullable String path) {
        if (path == null) return false;
        final Matcher m = PATTERN_OBB_OR_CHILD_RELATIVE_PATH.matcher(path);
        return m.matches();
    }

    public static boolean shouldBeVisible(@Nullable String path) {
        if (path == null) return false;
        final Matcher m = PATTERN_VISIBLE.matcher(path);
        return m.matches();
    }

    public static boolean shouldBeInvisible(@Nullable String path) {
        if (path == null) return false;
        final Matcher m = PATTERN_INVISIBLE.matcher(path);
        return m.matches();
    }

    /**
     * Returns the name of the top level directory, or null if the path doesn't go through the
     * external storage directory.
     */
    @Nullable
    public static String extractTopLevelDir(String path) {
        final String relativePath = extractRelativePath(path);
        if (relativePath == null) {
            return null;
        }

        return extractTopLevelDir(relativePath.split("/"));
    }

    @Nullable
    public static String extractTopLevelDir(String[] relativePathSegments) {
        return extractTopLevelDir(relativePathSegments, PROP_CROSS_USER_ROOT);
    }

    @VisibleForTesting
    @Nullable
    static String extractTopLevelDir(String[] relativePathSegments, String crossUserRoot) {
        if (relativePathSegments == null) return null;

        final String topLevelDir = relativePathSegments.length > 0 ? relativePathSegments[0] : null;
        if (crossUserRoot != null && crossUserRoot.equals(topLevelDir)) {
            return relativePathSegments.length > 1 ? relativePathSegments[1] : null;
        }

        return topLevelDir;
    }

    public static boolean isDefaultDirectoryName(@Nullable String dirName) {
        for (String defaultDirName : DEFAULT_FOLDER_NAMES) {
            if (defaultDirName.equalsIgnoreCase(dirName)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Compute the value of {@link MediaColumns#DATE_EXPIRES} based on other
     * columns being modified by this operation.
     */
    public static void computeDateExpires(@NonNull ContentValues values) {
        // External apps have no ability to change this field
        values.remove(MediaColumns.DATE_EXPIRES);

        // Only define the field when this modification is actually adjusting
        // one of the flags that should influence the expiration
        final Object pending = values.get(MediaColumns.IS_PENDING);
        if (pending != null) {
            if (parseBoolean(pending, false)) {
                values.put(MediaColumns.DATE_EXPIRES,
                        (System.currentTimeMillis() + DEFAULT_DURATION_PENDING) / 1000);
            } else {
                values.putNull(MediaColumns.DATE_EXPIRES);
            }
        }
        final Object trashed = values.get(MediaColumns.IS_TRASHED);
        if (trashed != null) {
            if (parseBoolean(trashed, false)) {
                values.put(MediaColumns.DATE_EXPIRES,
                        (System.currentTimeMillis() + DEFAULT_DURATION_TRASHED) / 1000);
            } else {
                values.putNull(MediaColumns.DATE_EXPIRES);
            }
        }
    }

    /**
     * Compute several scattered {@link MediaColumns} values from
     * {@link MediaColumns#DATA}. This method performs no enforcement of
     * argument validity.
     */
    public static void computeValuesFromData(@NonNull ContentValues values, boolean isForFuse) {
        // Worst case we have to assume no bucket details
        values.remove(MediaColumns.VOLUME_NAME);
        values.remove(MediaColumns.RELATIVE_PATH);
        values.remove(MediaColumns.IS_TRASHED);
        values.remove(MediaColumns.DATE_EXPIRES);
        values.remove(MediaColumns.DISPLAY_NAME);
        values.remove(MediaColumns.BUCKET_ID);
        values.remove(MediaColumns.BUCKET_DISPLAY_NAME);

        final String data = values.getAsString(MediaColumns.DATA);
        if (TextUtils.isEmpty(data)) return;

        final File file = new File(data);
        final File fileLower = new File(data.toLowerCase(Locale.ROOT));

        values.put(MediaColumns.VOLUME_NAME, extractVolumeName(data));
        values.put(MediaColumns.RELATIVE_PATH, extractRelativePath(data));
        final String displayName = extractDisplayName(data);
        final Matcher matcher = FileUtils.PATTERN_EXPIRES_FILE.matcher(displayName);
        if (matcher.matches()) {
            values.put(MediaColumns.IS_PENDING,
                    matcher.group(1).equals(FileUtils.PREFIX_PENDING) ? 1 : 0);
            values.put(MediaColumns.IS_TRASHED,
                    matcher.group(1).equals(FileUtils.PREFIX_TRASHED) ? 1 : 0);
            values.put(MediaColumns.DATE_EXPIRES, Long.parseLong(matcher.group(2)));
            values.put(MediaColumns.DISPLAY_NAME, matcher.group(3));
        } else {
            if (isForFuse) {
                // Allow Fuse thread to set IS_PENDING when using DATA column.
                // TODO(b/156867379) Unset IS_PENDING when Fuse thread doesn't explicitly specify
                // IS_PENDING. It can't be done now because we scan after create. Scan doesn't
                // explicitly specify the value of IS_PENDING.
            } else {
                values.put(MediaColumns.IS_PENDING, 0);
            }
            values.put(MediaColumns.IS_TRASHED, 0);
            values.putNull(MediaColumns.DATE_EXPIRES);
            values.put(MediaColumns.DISPLAY_NAME, displayName);
        }

        // Buckets are the parent directory
        final String parent = fileLower.getParent();
        if (parent != null) {
            values.put(MediaColumns.BUCKET_ID, parent.hashCode());
            // The relative path for files in the top directory is "/"
            if (!"/".equals(values.getAsString(MediaColumns.RELATIVE_PATH))) {
                values.put(MediaColumns.BUCKET_DISPLAY_NAME, file.getParentFile().getName());
            } else {
                values.putNull(MediaColumns.BUCKET_DISPLAY_NAME);
            }
        }
    }

    /**
     * Compute {@link MediaColumns#DATA} from several scattered
     * {@link MediaColumns} values.  This method performs no enforcement of
     * argument validity.
     */
    public static void computeDataFromValues(@NonNull ContentValues values,
            @NonNull File volumePath, boolean isForFuse) {
        values.remove(MediaColumns.DATA);

        final String displayName = values.getAsString(MediaColumns.DISPLAY_NAME);
        final String resolvedDisplayName;
        // Pending file path shouldn't be rewritten for files inserted via filepath.
        if (!isForFuse && getAsBoolean(values, MediaColumns.IS_PENDING, false)) {
            final long dateExpires = getAsLong(values, MediaColumns.DATE_EXPIRES,
                    (System.currentTimeMillis() + DEFAULT_DURATION_PENDING) / 1000);
            final String combinedString = String.format(
                    Locale.US, ".%s-%d-%s", FileUtils.PREFIX_PENDING, dateExpires, displayName);
            // trim the file name to avoid ENAMETOOLONG error
            // after trim the file, if the user unpending the file,
            // the file name is not the original one
            resolvedDisplayName = trimFilename(combinedString, MAX_FILENAME_BYTES);
        } else if (getAsBoolean(values, MediaColumns.IS_TRASHED, false)) {
            final long dateExpires = getAsLong(values, MediaColumns.DATE_EXPIRES,
                    (System.currentTimeMillis() + DEFAULT_DURATION_TRASHED) / 1000);
            final String combinedString = String.format(
                    Locale.US, ".%s-%d-%s", FileUtils.PREFIX_TRASHED, dateExpires, displayName);
            // trim the file name to avoid ENAMETOOLONG error
            // after trim the file, if the user untrashes the file,
            // the file name is not the original one
            resolvedDisplayName = trimFilename(combinedString, MAX_FILENAME_BYTES);
        } else {
            resolvedDisplayName = displayName;
        }

        final File filePath = buildPath(volumePath,
                values.getAsString(MediaColumns.RELATIVE_PATH), resolvedDisplayName);
        values.put(MediaColumns.DATA, filePath.getAbsolutePath());
    }

    public static void sanitizeValues(@NonNull ContentValues values,
            boolean rewriteHiddenFileName) {
        final String[] relativePath = values.getAsString(MediaColumns.RELATIVE_PATH).split("/");
        for (int i = 0; i < relativePath.length; i++) {
            relativePath[i] = sanitizeDisplayName(relativePath[i], rewriteHiddenFileName);
        }
        values.put(MediaColumns.RELATIVE_PATH,
                String.join("/", relativePath) + "/");

        final String displayName = values.getAsString(MediaColumns.DISPLAY_NAME);
        values.put(MediaColumns.DISPLAY_NAME,
                sanitizeDisplayName(displayName, rewriteHiddenFileName));
    }

    /** {@hide} **/
    @Nullable
    public static String getAbsoluteSanitizedPath(String path) {
        final String[] pathSegments = sanitizePath(path);
        if (pathSegments.length == 0) {
            return null;
        }
        return path = "/" + String.join("/",
                Arrays.copyOfRange(pathSegments, 1, pathSegments.length));
    }

    /** {@hide} */
    public static @NonNull String[] sanitizePath(@Nullable String path) {
        if (path == null) {
            return new String[0];
        } else {
            final String[] segments = path.split("/");
            // If the path corresponds to the top level directory, then we return an empty path
            // which denotes the top level directory
            if (segments.length == 0) {
                return new String[] { "" };
            }
            for (int i = 0; i < segments.length; i++) {
                segments[i] = sanitizeDisplayName(segments[i]);
            }
            return segments;
        }
    }

    /**
     * Sanitizes given name by mutating the file name to make it valid for a FAT filesystem.
     * @hide
     */
    public static @Nullable String sanitizeDisplayName(@Nullable String name) {
        return sanitizeDisplayName(name, /*rewriteHiddenFileName*/ false);
    }

    /**
     * Sanitizes given name by appending '_' to make it non-hidden and mutating the file name to
     * make it valid for a FAT filesystem.
     * @hide
     */
    public static @Nullable String sanitizeDisplayName(@Nullable String name,
            boolean rewriteHiddenFileName) {
        if (name == null) {
            return null;
        } else if (rewriteHiddenFileName && name.startsWith(".")) {
            // The resulting file must not be hidden.
            return "_" + name;
        } else {
            return buildValidFatFilename(name);
        }
    }

    /**
     * Returns true if the given File should be hidden (if it or any of its parents is hidden).
     * This can be called before the file is created, to check if it will be hidden once created.
     */
    @VisibleForTesting
    public static boolean shouldFileBeHidden(@NonNull File file) {
        if (isFileHidden(file)) {
            return true;
        }

        File parent = file.getParentFile();
        while (parent != null) {
            if (isDirectoryHidden(parent)) {
                return true;
            }
            parent = parent.getParentFile();
        }

        return false;
    }

    /**
     * Returns true if the given dir should be hidden (if it or any of its parents is hidden).
     * This can be called before the file is created, to check if it will be hidden once created.
     */
    @VisibleForTesting
    public static boolean shouldDirBeHidden(@NonNull File file) {
        if (isDirectoryHidden(file)) {
            return true;
        }

        File parent = file.getParentFile();
        while (parent != null) {
            if (isDirectoryHidden(parent)) {
                return true;
            }
            parent = parent.getParentFile();
        }

        return false;
    }

    /**
     * Test if this given directory should be considered hidden.
     */
    @VisibleForTesting
    public static boolean isDirectoryHidden(@NonNull File dir) {
        final String name = dir.getName();
        if (name.startsWith(".")) {
            return true;
        }

        final File nomedia = new File(dir, ".nomedia");

        // check for .nomedia presence
        if (!nomedia.exists()) {
            return false;
        }

        if (shouldBeVisible(dir.getAbsolutePath())) {
            nomedia.delete();
            return false;
        }

        // Handle top-level default directories. These directories should always be visible,
        // regardless of .nomedia presence.
        final String[] relativePath = sanitizePath(extractRelativePath(dir.getAbsolutePath()));
        final boolean isTopLevelDir =
                relativePath.length == 1 && TextUtils.isEmpty(relativePath[0]);
        if (isTopLevelDir && isDefaultDirectoryName(name)) {
            nomedia.delete();
            return false;
        }

        // DCIM/Camera should always be visible regardless of .nomedia presence.
        if (CAMERA_RELATIVE_PATH.equalsIgnoreCase(
                extractRelativePathWithDisplayName(dir.getAbsolutePath()))) {
            nomedia.delete();
            return false;
        }

        if (isScreenshotsDirNonHidden(relativePath, name)) {
            nomedia.delete();
            return false;
        }

        // .nomedia is present which makes this directory as hidden directory
        Logging.logPersistent("Observed non-standard " + nomedia);
        return true;
    }

    /**
     * Consider Screenshots directory in root directory or inside well-known directory as always
     * non-hidden. Nomedia file in these directories will not be able to hide these directories.
     * i.e., some examples of directories that will be considered non-hidden are
     * <ul>
     * <li> /storage/emulated/0/Screenshots or
     * <li> /storage/emulated/0/DCIM/Screenshots or
     * <li> /storage/emulated/0/Pictures/Screenshots ...
     * </ul>
     * Some examples of directories that can be considered as hidden with nomedia are
     * <ul>
     * <li> /storage/emulated/0/foo/Screenshots or
     * <li> /storage/emulated/0/DCIM/Foo/Screenshots or
     * <li> /storage/emulated/0/Pictures/foo/bar/Screenshots ...
     * </ul>
     */
    private static boolean isScreenshotsDirNonHidden(@NonNull String[] relativePath,
            @NonNull String name) {
        if (name.equalsIgnoreCase(Environment.DIRECTORY_SCREENSHOTS)) {
            return (relativePath.length == 1 &&
                (TextUtils.isEmpty(relativePath[0]) || isDefaultDirectoryName(relativePath[0])));
        }
        return false;
    }

    /**
     * Test if this given file should be considered hidden.
     */
    @VisibleForTesting
    public static boolean isFileHidden(@NonNull File file) {
        final String name = file.getName();

        // Handle well-known file names that are pending or trashed; they
        // normally appear hidden, but we give them special treatment
        if (PATTERN_EXPIRES_FILE.matcher(name).matches()) {
            return false;
        }

        // Otherwise fall back to file name
        if (name.startsWith(".")) {
            return true;
        }
        return false;
    }

    /**
     * Clears all app's external cache directories, i.e. for each app we delete
     * /sdcard/Android/data/app/cache/* but we keep the directory itself.
     *
     * @return 0 in case of success, or {@link OsConstants#EIO} if any error occurs.
     *
     * <p>This method doesn't perform any checks, so make sure that the calling package is allowed
     * to clear cache directories first.
     *
     * <p>If this method returned {@link OsConstants#EIO}, then we can't guarantee whether all, none
     * or part of the directories were cleared.
     */
    public static int clearAppCacheDirectories() {
        int status = 0;
        Log.i(TAG, "Clearing cache for all apps");
        final File rootDataDir = buildPath(Environment.getExternalStorageDirectory(),
                "Android", "data");
        for (File appDataDir : rootDataDir.listFiles()) {
            try {
                final File appCacheDir = new File(appDataDir, "cache");
                if (appCacheDir.isDirectory()) {
                    FileUtils.deleteContents(appCacheDir);
                }
            } catch (Exception e) {
                // We want to avoid crashing MediaProvider at all costs, so we handle all "generic"
                // exceptions here, and just report to the caller that an IO exception has occurred.
                // We still try to clear the rest of the directories.
                Log.e(TAG, "Couldn't delete all app cache dirs!", e);
                status = OsConstants.EIO;
            }
        }
        return status;
    }

    /**
     * @return {@code true} if {@code dir} has nomedia and it is dirty directory, so it should be
     * scanned. Returns {@code false} otherwise.
     */
    public static boolean isDirectoryDirty(File dir) {
        File nomedia = new File(dir, ".nomedia");

        // We return false for directories that don't have .nomedia
        if (!nomedia.exists()) {
            return false;
        }

        // We don't write to ".nomedia" dirs, only to ".nomedia" files. If this ".nomedia" is not
        // a file, then don't try to read it.
        if (!nomedia.isFile()) {
            return true;
        }

        try {
            Optional<String> expectedPath = readString(nomedia);
            // Returns true If .nomedia file is empty or content doesn't match |dir|
            // Returns false otherwise
            return !expectedPath.isPresent()
                    || !expectedPath.get().equals(dir.getPath());
        } catch (IOException e) {
            Log.w(TAG, "Failed to read directory dirty" + dir);
            return true;
        }
    }

    /**
     * {@code isDirty} == {@code true} will force {@code dir} scanning even if it's hidden
     * {@code isDirty} == {@code false} will skip {@code dir} scanning on next scan.
     */
    public static void setDirectoryDirty(File dir, boolean isDirty) {
        File nomedia = new File(dir, ".nomedia");
        if (nomedia.exists() && nomedia.isFile()) {
            try {
                writeString(nomedia, isDirty ? Optional.of("") : Optional.of(dir.getPath()));
            } catch (IOException e) {
                Log.w(TAG, "Failed to change directory dirty: " + dir + ". isDirty: " + isDirty);
            }
        }
    }

    /**
     * @return the folder containing the top-most .nomedia in {@code file} hierarchy.
     * E.g input as /sdcard/foo/bar/ will return /sdcard/foo
     * even if foo and bar contain .nomedia files.
     *
     * Returns {@code null} if there's no .nomedia in hierarchy
     */
    public static File getTopLevelNoMedia(@NonNull File file) {
        File topNoMediaDir = null;

        File parent = file;
        while (parent != null) {
            File nomedia = new File(parent, ".nomedia");
            if (nomedia.exists()) {
                topNoMediaDir = parent;
            }
            parent = parent.getParentFile();
        }

        return topNoMediaDir;
    }

    /**
     * Generate the extended absolute path from the expired file path
     * E.g. the input expiredFilePath is /storage/emulated/0/DCIM/.trashed-1621147340-test.jpg
     * The returned result is /storage/emulated/0/DCIM/.trashed-1888888888-test.jpg
     *
     * @hide
     */
    @Nullable
    public static String getAbsoluteExtendedPath(@NonNull String expiredFilePath,
            long extendedTime) {
        final String displayName = extractDisplayName(expiredFilePath);

        final Matcher matcher = PATTERN_EXPIRES_FILE.matcher(displayName);
        if (matcher.matches()) {
            final String newDisplayName = String.format(Locale.US, ".%s-%d-%s", matcher.group(1),
                    extendedTime, matcher.group(3));
            final int lastSlash = expiredFilePath.lastIndexOf('/');
            final String newPath = expiredFilePath.substring(0, lastSlash + 1).concat(
                    newDisplayName);
            return newPath;
        }

        return null;
    }

    public static File buildPrimaryVolumeFile(int userId, String... segments) {
        return buildPath(new File("/storage/emulated/" + userId), segments);
    }

    private static final String LOWER_FS_PREFIX = "/storage/";
    private static final String FUSE_FS_PREFIX = "/mnt/user/" + UserHandle.myUserId() + "/";

    public static File toFuseFile(File file) {
        return new File(file.getPath().replaceFirst(LOWER_FS_PREFIX, FUSE_FS_PREFIX));
    }

    public static File fromFuseFile(File file) {
        return new File(file.getPath().replaceFirst(FUSE_FS_PREFIX, LOWER_FS_PREFIX));
    }
}
